You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
3.5 KiB
Go

package main
import (
"./src/config"
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/olekukonko/tablewriter"
"io/ioutil"
"log"
"net/http"
"strings"
"time"
)
// SL is my SL struct
type SL struct {
Config *config.Config
lastResponse SLResponse
nextRefresh int64
}
// SLResponse is a struct to get the interesting data from API Responses
type SLResponse struct {
StatusCode int
ExecutionTime int
ResponseData struct {
LatestUpdate string
Metros []struct {
LineNumber string
Destination string
TimeTabledDateTime string
ExpectedDateTime string
TransportMode string
}
StopPointDeviations []struct {
Deviation struct {
Text string
}
}
}
}
// GetOutput returns a rendered result of this module
func (sl *SL) GetOutput() []string {
var b bytes.Buffer
// Prepare table
table := tablewriter.NewWriter(&b)
table.SetHeader([]string{
"Line",
"Destination",
"DisplayTime",
"Timetable",
"Expected",
})
// Check if it's time to refresh yet
if sl.nextRefresh <= time.Now().Unix() {
sl.nextRefresh += 10
go sl.getData()
}
for _, v := range sl.lastResponse.ResponseData.Metros {
formattedTime, err := sl.formatDisplayTime(v.ExpectedDateTime)
if err == nil {
table.Append([]string{
v.LineNumber,
v.Destination,
formattedTime,
v.TimeTabledDateTime[11:], // Remove YYYY-MM-DDT from the beginning of the string
v.ExpectedDateTime[11:], // Remove YYYY-MM-DDT from the beginning of the string
})
}
}
table.Render()
// Go through deviations and add it after the table
for _, v := range sl.lastResponse.ResponseData.StopPointDeviations {
b.WriteString(v.Deviation.Text + "\n")
}
return strings.Split(b.String(), "\n")
}
func (sl *SL) getData() {
// If it is, refresh the data
sldata, err := sl.getTimeTable()
// If no error occured, save the latest data to the struct
if err == nil {
sl.lastResponse = sldata
sl.nextRefresh = time.Now().Unix() + sl.Config.SL.RefreshDelay
} else {
// log.Fatal(err)
}
}
func (sl *SL) getTimeTable() (SLResponse, error) {
parsedResponse := SLResponse{}
// Construct URL with APIKey and Site
url := fmt.Sprintf(sl.Config.SL.APIURL, sl.Config.SL.APIKey, sl.Config.SL.SiteID)
// Set up http client to talk to SL
client := http.Client{
Timeout: time.Second * 5,
}
// Do request
resp, err := client.Get(url)
if err != nil {
return parsedResponse, err
}
// Read response
body, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil {
return parsedResponse, readErr
}
// Parse response from SL
parseErr := json.Unmarshal(body, &parsedResponse)
if parseErr != nil {
return parsedResponse, parseErr
}
return parsedResponse, nil
}
func (sl *SL) formatDisplayTime(expected string) (string, error) {
myTimeZone, _ := time.Now().Zone()
then, err := time.Parse("2006-01-02T15:04:05 MST", expected+" "+myTimeZone)
if err != nil {
log.Fatal(err)
}
timeLeft := time.Since(then).Seconds() * -1
// If time is less than zero
if timeLeft < 0 {
return "undefined", errors.New("Train is gone already")
}
// If time is less than one minute, show seconds
if timeLeft <= 60 && timeLeft > 0 {
return fmt.Sprintf("%d sec", int(timeLeft)), nil
}
// If time is less than one hour, show minutes
if timeLeft <= 3600 && timeLeft > 0 {
return fmt.Sprintf("%d min", int(timeLeft)/60), nil
}
// Otherwise, just return a timestamp: HH:MM:SS
return fmt.Sprintf("%02d:%02d:%02d", then.Hour(), then.Minute(), then.Second()), nil
}