Compare commits
9
Commits
6bb37b7e4c
...
v0.0.11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
780e0fa39b | ||
|
|
62c31bb28c | ||
|
|
c836a3b201 | ||
|
|
710b63045f | ||
|
|
072ee12197 | ||
|
|
da8e8f15c8 | ||
|
|
54099afcb1 | ||
|
|
959630f7b6 | ||
|
|
96dc4c924d |
@@ -6,27 +6,35 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build-image:
|
build-image:
|
||||||
container:
|
container:
|
||||||
image: catthehacker/ubuntu:act-latest
|
image: node:24-bookworm
|
||||||
|
env:
|
||||||
|
USER: node
|
||||||
|
HOME: /home/node
|
||||||
|
NIX_CONFIG: experimental-features = nix-command flakes
|
||||||
|
volumes:
|
||||||
|
- /var/lib/pbri/docker/nix_runner_nix:/nix
|
||||||
|
- /var/lib/pbri/docker/nix_runner_etc:/etc/nix
|
||||||
|
- /var/lib/pbri/docker/nix_runner_home_node:/home/node
|
||||||
|
options: --user 1000:1000
|
||||||
steps:
|
steps:
|
||||||
|
- name: Prep nix env
|
||||||
|
run: |
|
||||||
|
if [ ! -f ~/.nix-profile/etc/profile.d/nix.sh ]; then
|
||||||
|
curl -L https://nixos.org/nix/install | bash -s -- --no-daemon
|
||||||
|
fi
|
||||||
|
. ~/.nix-profile/etc/profile.d/nix.sh
|
||||||
|
env >> "$GITHUB_ENV"
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
# Required for installing nix
|
|
||||||
- name: Install sudo
|
|
||||||
run: apt-get update && apt-get install -y sudo
|
|
||||||
- name: Install Nix
|
|
||||||
uses: cachix/install-nix-action@v31
|
|
||||||
with:
|
|
||||||
enable_kvm: false
|
|
||||||
- name: Get image meta
|
- name: Get image meta
|
||||||
run: nix build .#image-meta -o image-meta
|
run: nix build .#image-meta -o image-meta
|
||||||
- name: Version check
|
- name: Version check
|
||||||
run: |
|
run: |
|
||||||
VERSION=$(cat image-meta/version)
|
VERSION=$(cat image-meta/version)
|
||||||
[ "$GITHUB_REF_NAME" = v"$VERSION" ]
|
[ "$GITHUB_REF_NAME" = v"$VERSION" ]
|
||||||
- name: Build image
|
- run: nix build --log-format raw --print-build-logs .#image -o image.tar.gz
|
||||||
run: nix build .#image -o image.tar.gz
|
- run: gunzip -c image.tar.gz > image.tar
|
||||||
- run: docker login -u paul -p "$PASSWORD" git.pbrinkmeier.de
|
- run: nix run .#crane -- auth login git.pbrinkmeier.de -u paul -p "$PASSWORD"
|
||||||
env:
|
env:
|
||||||
PASSWORD: "${{ secrets.REGISTRY_PASSWORD }}"
|
PASSWORD: "${{ secrets.REGISTRY_PASSWORD }}"
|
||||||
- run: docker load < image.tar.gz
|
- run: nix run .#crane -- push image.tar $(cat image-meta/name)
|
||||||
- run: docker image push $(cat image-meta/name)
|
|
||||||
|
|||||||
+231
-1
@@ -1,19 +1,233 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "cmp"
|
||||||
|
import "encoding/json"
|
||||||
|
import "errors"
|
||||||
|
import "fmt"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "net/url"
|
import "net/url"
|
||||||
|
import "slices"
|
||||||
|
import "strconv"
|
||||||
import "strings"
|
import "strings"
|
||||||
|
import "time"
|
||||||
|
|
||||||
type EFAClient interface {
|
type EFAClient interface {
|
||||||
GetName() string
|
GetName() string
|
||||||
BuildRequest(string) (*http.Request, error)
|
BuildRequest(string) (*http.Request, error)
|
||||||
|
ParseResponse(*http.Response) (Departures, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchDepartures(c EFAClient, stopId string) (Departures, error) {
|
||||||
|
req, err := c.BuildRequest(stopId)
|
||||||
|
if err != nil {
|
||||||
|
return Departures{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the request, wait max 10 seconds
|
||||||
|
client := http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
res, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return Departures{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ParseResponse(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON unmarshaling types for departure monitor API
|
||||||
|
|
||||||
|
type DMResponse struct {
|
||||||
|
DateTime DMDateTime `json:"dateTime"`
|
||||||
|
DepartureList []DMDeparture `json:"departureList"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DMDeparture struct {
|
||||||
|
StopName string `json:"stopName"`
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
Countdown string `json:"countdown"`
|
||||||
|
DateTime DMDateTime `json:"dateTime"`
|
||||||
|
RealDateTime *DMDateTime `json:"realDateTime"`
|
||||||
|
ServingLine DMServingLine `json:"servingLine"`
|
||||||
|
OnwardStopSeq []DMStop `json:"onwardStopSeq"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DMServingLine struct {
|
||||||
|
Symbol string `json:"symbol"`
|
||||||
|
Direction string `json:"direction"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DMStop struct {
|
||||||
|
PlaceID string `json:"placeID"`
|
||||||
|
Place string `json:"place"`
|
||||||
|
NameWO string `json:"nameWO"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DMDateTime struct {
|
||||||
|
Hour string `json:"hour"`
|
||||||
|
Minute string `json:"minute"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types for JSON marshaling
|
||||||
|
|
||||||
|
type Departures struct {
|
||||||
|
Departures []Departure `json:"departures"`
|
||||||
|
ServerTime string `json:"serverTime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Departure struct {
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
Symbol string `json:"symbol"`
|
||||||
|
Direction string `json:"direction"`
|
||||||
|
Leaving string `json:"leaving"`
|
||||||
|
Countdown int `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDMResponse(res *http.Response) (Departures, error) {
|
||||||
|
defer res.Body.Close()
|
||||||
|
var dmResponse DMResponse
|
||||||
|
err := json.NewDecoder(res.Body).Decode(&dmResponse)
|
||||||
|
if err != nil {
|
||||||
|
return Departures{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseDepartures(dmResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDepartures(response DMResponse) (Departures, error) {
|
||||||
|
var ds []Departure
|
||||||
|
|
||||||
|
for _, d := range response.DepartureList {
|
||||||
|
direction := d.ServingLine.Direction
|
||||||
|
// If available, use name of last stop as direction
|
||||||
|
// Note that OnwardStopSeq is only populated if includeCompleteStopSeq=1 is set.
|
||||||
|
if len(d.OnwardStopSeq) != 0 {
|
||||||
|
last := d.OnwardStopSeq[len(d.OnwardStopSeq)-1]
|
||||||
|
if slices.Contains([]string{"5", "6"}, last.PlaceID) {
|
||||||
|
direction = last.NameWO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leaving := fmt.Sprintf("%s min", d.Countdown)
|
||||||
|
countdown, err := strconv.Atoi(d.Countdown)
|
||||||
|
if err != nil {
|
||||||
|
return Departures{}, errors.New("could not parse countdown")
|
||||||
|
}
|
||||||
|
|
||||||
|
isInThePast := countdown < 0
|
||||||
|
if isInThePast {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if countdown == 0 {
|
||||||
|
leaving = "sofort"
|
||||||
|
}
|
||||||
|
if countdown > 20 {
|
||||||
|
dt := d.DateTime
|
||||||
|
if d.RealDateTime != nil {
|
||||||
|
dt = *d.RealDateTime
|
||||||
|
}
|
||||||
|
leaving = fmt.Sprintf("%02s:%02s", dt.Hour, dt.Minute)
|
||||||
|
}
|
||||||
|
|
||||||
|
ds = append(ds, Departure{
|
||||||
|
d.Platform,
|
||||||
|
d.ServingLine.Symbol,
|
||||||
|
direction,
|
||||||
|
leaving,
|
||||||
|
countdown,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.SortFunc(ds, func(a Departure, b Departure) int {
|
||||||
|
return cmp.Compare(a.Countdown, b.Countdown)
|
||||||
|
})
|
||||||
|
|
||||||
|
dt := response.DateTime
|
||||||
|
|
||||||
|
return Departures{
|
||||||
|
ds,
|
||||||
|
fmt.Sprintf("%02s:%02s", dt.Hour, dt.Minute),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var allEfaClients []EFAClient = []EFAClient{
|
var allEfaClients []EFAClient = []EFAClient{
|
||||||
|
IVBEFAClient{},
|
||||||
BwegtEFAClient{},
|
BwegtEFAClient{},
|
||||||
VRNEFAClient{},
|
|
||||||
KVVEFAClient{},
|
KVVEFAClient{},
|
||||||
VAGEFAClient{},
|
VAGEFAClient{},
|
||||||
|
VRNEFAClient{},
|
||||||
|
}
|
||||||
|
|
||||||
|
type IVBEFAClient struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c IVBEFAClient) GetName() string {
|
||||||
|
return "IVB"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c IVBEFAClient) BuildRequest(stopId string) (*http.Request, error) {
|
||||||
|
// curl https://smartinfo.ivb.at/api/JSON/PASSAGE'?stopID=64003&count=3'
|
||||||
|
req, err := http.NewRequest("GET", "https://smartinfo.ivb.at/api/JSON/PASSAGE", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query := url.Values{}
|
||||||
|
query.Set("stopID", stopId)
|
||||||
|
req.URL.RawQuery = query.Encode()
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c IVBEFAClient) ParseResponse(res *http.Response) (Departures, error) {
|
||||||
|
defer res.Body.Close()
|
||||||
|
var response []IVBResponseElem
|
||||||
|
err := json.NewDecoder(res.Body).Decode(&response)
|
||||||
|
if err != nil {
|
||||||
|
return Departures{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ds []Departure
|
||||||
|
|
||||||
|
for _, responseElem := range response {
|
||||||
|
if responseElem.Smartinfo == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
si := responseElem.Smartinfo
|
||||||
|
|
||||||
|
leaving := si.Time
|
||||||
|
if leaving == "0 min" {
|
||||||
|
leaving = "sofort"
|
||||||
|
}
|
||||||
|
|
||||||
|
ds = append(ds, Departure{
|
||||||
|
si.Plabel,
|
||||||
|
si.Route,
|
||||||
|
si.Direction,
|
||||||
|
leaving,
|
||||||
|
// TODO
|
||||||
|
0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return Departures{
|
||||||
|
ds,
|
||||||
|
fmt.Sprintf("%02d:%02d", 0, 0),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IVB smartinfo API unmarshaling types
|
||||||
|
type IVBResponseElem struct {
|
||||||
|
Smartinfo *IVBSmartInfo `json:"smartinfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IVBSmartInfo struct {
|
||||||
|
Uid string `json:"uid"`
|
||||||
|
Route string `json:"route"`
|
||||||
|
Direction string `json:"direction"`
|
||||||
|
Time string `json:"time"`
|
||||||
|
Plabel string `json:"plabel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VRNEFAClient struct {
|
type VRNEFAClient struct {
|
||||||
@@ -48,6 +262,10 @@ func (c VRNEFAClient) BuildRequest(stopId string) (*http.Request, error) {
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c VRNEFAClient) ParseResponse(res *http.Response) (Departures, error) {
|
||||||
|
return ParseDMResponse(res)
|
||||||
|
}
|
||||||
|
|
||||||
type KVVEFAClient struct {
|
type KVVEFAClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +296,10 @@ func (c KVVEFAClient) BuildRequest(stopId string) (*http.Request, error) {
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c KVVEFAClient) ParseResponse(res *http.Response) (Departures, error) {
|
||||||
|
return ParseDMResponse(res)
|
||||||
|
}
|
||||||
|
|
||||||
type BwegtEFAClient struct {
|
type BwegtEFAClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +332,10 @@ func (c BwegtEFAClient) BuildRequest(stopId string) (*http.Request, error) {
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c BwegtEFAClient) ParseResponse(res *http.Response) (Departures, error) {
|
||||||
|
return ParseDMResponse(res)
|
||||||
|
}
|
||||||
|
|
||||||
type VAGEFAClient struct {
|
type VAGEFAClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,3 +367,7 @@ func (c VAGEFAClient) BuildRequest(stopId string) (*http.Request, error) {
|
|||||||
|
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c VAGEFAClient) ParseResponse(res *http.Response) (Departures, error) {
|
||||||
|
return ParseDMResponse(res)
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,15 +16,22 @@
|
|||||||
|
|
||||||
vrnp-static = pkgs.buildGoModule {
|
vrnp-static = pkgs.buildGoModule {
|
||||||
pname = "vrnp";
|
pname = "vrnp";
|
||||||
version = "0.0.10";
|
version = "0.0.11";
|
||||||
vendorHash = null;
|
vendorHash = null;
|
||||||
|
|
||||||
# For building the package, we use only the files not ignored by Git as inputs.
|
# For building the package, we use only the files not ignored by Git as inputs.
|
||||||
# Also, flake.nix and flake.lock are not included to avoid annoying rebuilds when
|
# Also, flake.nix, flake.lock and .gitea are not included to avoid annoying rebuilds when
|
||||||
# working on them.
|
# working on them.
|
||||||
src = pkgs.lib.cleanSourceWith {
|
src = pkgs.lib.cleanSourceWith {
|
||||||
src = gitignore.lib.gitignoreSource ./.;
|
src = ./.;
|
||||||
filter = path: type: builtins.baseNameOf path != "flake.nix" && builtins.baseNameOf path != "flake.lock";
|
filter = gitignore.lib.gitignoreFilterWith {
|
||||||
|
basePath = ./.;
|
||||||
|
extraRules = ''
|
||||||
|
flake.nix
|
||||||
|
flake.lock
|
||||||
|
.gitea
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Avoid linking against libc
|
# Avoid linking against libc
|
||||||
@@ -55,6 +62,12 @@
|
|||||||
config.Cmd = [ "${vrnp-static}/bin/vrnp" ];
|
config.Cmd = [ "${vrnp-static}/bin/vrnp" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
apps = {
|
||||||
|
crane = {
|
||||||
|
type = "app";
|
||||||
|
program = "${pkgs.crane}/bin/crane";
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,148 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "cmp"
|
|
||||||
import "encoding/json"
|
import "encoding/json"
|
||||||
import "errors"
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "log"
|
import "log"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "os"
|
import "os"
|
||||||
import "slices"
|
import "slices"
|
||||||
import "strings"
|
import "strings"
|
||||||
import "strconv"
|
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
import "time"
|
|
||||||
|
|
||||||
// JSON unmarshaling types for departure monitor API
|
|
||||||
|
|
||||||
type DMResponse struct {
|
|
||||||
DateTime DMDateTime `json:"dateTime"`
|
|
||||||
DepartureList []DMDeparture `json:"departureList"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DMDeparture struct {
|
|
||||||
StopName string `json:"stopName"`
|
|
||||||
Platform string `json:"platform"`
|
|
||||||
Countdown string `json:"countdown"`
|
|
||||||
DateTime DMDateTime `json:"dateTime"`
|
|
||||||
RealDateTime *DMDateTime `json:"realDateTime"`
|
|
||||||
ServingLine DMServingLine `json:"servingLine"`
|
|
||||||
OnwardStopSeq []DMStop `json:"onwardStopSeq"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DMServingLine struct {
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
Direction string `json:"direction"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DMStop struct {
|
|
||||||
PlaceID string `json:"placeID"`
|
|
||||||
Place string `json:"place"`
|
|
||||||
NameWO string `json:"nameWO"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DMDateTime struct {
|
|
||||||
Hour string `json:"hour"`
|
|
||||||
Minute string `json:"minute"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func FetchDepartures(c EFAClient, stopId string) (DMResponse, error) {
|
|
||||||
req, err := c.BuildRequest(stopId)
|
|
||||||
if err != nil {
|
|
||||||
return DMResponse{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the request, wait max 10 seconds
|
|
||||||
client := http.Client{
|
|
||||||
Timeout: 10 * time.Second,
|
|
||||||
}
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return DMResponse{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer res.Body.Close()
|
|
||||||
var dmResponse DMResponse
|
|
||||||
err = json.NewDecoder(res.Body).Decode(&dmResponse)
|
|
||||||
if err != nil {
|
|
||||||
return DMResponse{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return dmResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Types for JSON marshaling
|
|
||||||
|
|
||||||
type Departures struct {
|
|
||||||
Departures []Departure `json:"departures"`
|
|
||||||
ServerTime string `json:"serverTime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Departure struct {
|
|
||||||
Platform string `json:"platform"`
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
Direction string `json:"direction"`
|
|
||||||
Leaving string `json:"leaving"`
|
|
||||||
Countdown int `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseDepartures(response DMResponse, allowedPlatform *string) (Departures, error) {
|
|
||||||
var ds []Departure
|
|
||||||
|
|
||||||
for _, d := range response.DepartureList {
|
|
||||||
direction := d.ServingLine.Direction
|
|
||||||
// If available, use name of last stop as direction
|
|
||||||
// Note that OnwardStopSeq is only populated if includeCompleteStopSeq=1 is set.
|
|
||||||
if len(d.OnwardStopSeq) != 0 {
|
|
||||||
last := d.OnwardStopSeq[len(d.OnwardStopSeq)-1]
|
|
||||||
if slices.Contains([]string{"5", "6"}, last.PlaceID) {
|
|
||||||
direction = last.NameWO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
leaving := fmt.Sprintf("%s min", d.Countdown)
|
|
||||||
countdown, err := strconv.Atoi(d.Countdown)
|
|
||||||
if err != nil {
|
|
||||||
return Departures{}, errors.New("could not parse countdown")
|
|
||||||
}
|
|
||||||
|
|
||||||
matchesPlatform := allowedPlatform == nil || d.Platform == *allowedPlatform
|
|
||||||
isInThePast := countdown < 0
|
|
||||||
if !matchesPlatform || isInThePast {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if countdown == 0 {
|
|
||||||
leaving = "sofort"
|
|
||||||
}
|
|
||||||
if countdown > 20 {
|
|
||||||
dt := d.DateTime
|
|
||||||
if d.RealDateTime != nil {
|
|
||||||
dt = *d.RealDateTime
|
|
||||||
}
|
|
||||||
leaving = fmt.Sprintf("%02s:%02s", dt.Hour, dt.Minute)
|
|
||||||
}
|
|
||||||
|
|
||||||
ds = append(ds, Departure{
|
|
||||||
d.Platform,
|
|
||||||
d.ServingLine.Symbol,
|
|
||||||
direction,
|
|
||||||
leaving,
|
|
||||||
countdown,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
slices.SortFunc(ds, func(a Departure, b Departure) int {
|
|
||||||
return cmp.Compare(a.Countdown, b.Countdown)
|
|
||||||
})
|
|
||||||
|
|
||||||
dt := response.DateTime
|
|
||||||
|
|
||||||
return Departures{
|
|
||||||
ds,
|
|
||||||
fmt.Sprintf("%02s:%02s", dt.Hour, dt.Minute),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
password := os.Getenv("VRNP_PASSWORD")
|
password := os.Getenv("VRNP_PASSWORD")
|
||||||
@@ -182,18 +47,15 @@ func main() {
|
|||||||
platform = &query["platform"][0]
|
platform = &query["platform"][0]
|
||||||
}
|
}
|
||||||
|
|
||||||
c := efaClients[(efaClient.Add(1) - 1) % uint64(len(efaClients))]
|
c := efaClients[(efaClient.Add(1)-1)%uint64(len(efaClients))]
|
||||||
ds, err := FetchDepartures(c, stopId)
|
departures, err := FetchDepartures(c, stopId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// TODO: Filter for platform here
|
||||||
|
|
||||||
departures, err := ParseDepartures(ds, platform)
|
filterAndLimitDepartures(&departures, platform, 8)
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does not handle multiple media types
|
// Does not handle multiple media types
|
||||||
if r.Header.Get("Accept") == "application/json" {
|
if r.Header.Get("Accept") == "application/json" {
|
||||||
@@ -203,7 +65,7 @@ func main() {
|
|||||||
// plain text
|
// plain text
|
||||||
for _, d := range departures.Departures {
|
for _, d := range departures.Departures {
|
||||||
fmt.Fprintf(w, "%2s %-11s %6s\n",
|
fmt.Fprintf(w, "%2s %-11s %6s\n",
|
||||||
d.Symbol,
|
d.Symbol[:min(2, len(d.Symbol))],
|
||||||
d.Direction[:min(11, len(d.Direction))],
|
d.Direction[:min(11, len(d.Direction))],
|
||||||
d.Leaving,
|
d.Leaving,
|
||||||
)
|
)
|
||||||
@@ -213,3 +75,21 @@ func main() {
|
|||||||
})
|
})
|
||||||
log.Fatal(http.ListenAndServe(":8000", nil))
|
log.Fatal(http.ListenAndServe(":8000", nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterAndLimitDepartures(departures *Departures, platform *string, limit int) {
|
||||||
|
oldDepartures := departures.Departures
|
||||||
|
|
||||||
|
departures.Departures = []Departure{}
|
||||||
|
for _, departure := range oldDepartures {
|
||||||
|
if len(departures.Departures) >= limit {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
isPlatformMatch := platform == nil || departure.Platform == *platform
|
||||||
|
if !isPlatformMatch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
departures.Departures = append(departures.Departures, departure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user