From 259b78ebd3e2bc881d739379f06642fae0671d0b Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Sat, 22 Oct 2022 03:12:59 +0200 Subject: [PATCH] Some changes --- api/lines.go | 4 +- api/schedules.go | 30 +++++++-- api/stations.go | 6 +- api/traffic.go | 164 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 194 insertions(+), 10 deletions(-) diff --git a/api/lines.go b/api/lines.go index 2a2ef6d..f04692b 100644 --- a/api/lines.go +++ b/api/lines.go @@ -121,7 +121,7 @@ func declareLinesRoutes(router *gin.RouterGroup) { } pgline := PGLine{ - Code: fmt.Sprintf("IDFM:%s", line.Fields.IdLine), + Code: fmt.Sprintf("STIF:Line::%s:", line.Fields.IdLine), Name: name, Directions: "", Id: line.Fields.IdLine, @@ -132,7 +132,7 @@ func declareLinesRoutes(router *gin.RouterGroup) { } c.JSON(http.StatusOK, APIResult(c, map[string][]PGLine{ - t: lines, + string(c.Param("type")): lines, })) }) } diff --git a/api/schedules.go b/api/schedules.go index 4b46e03..e6c3eb1 100644 --- a/api/schedules.go +++ b/api/schedules.go @@ -7,6 +7,7 @@ import ( "math" "net/http" "net/url" + "strings" "time" "github.com/gin-gonic/gin" @@ -81,13 +82,18 @@ type IDFMSchedule struct { } type PGSchedule struct { - Destination string `json:"destionation"` + Destination string `json:"destination"` Message string `json:"message"` } +func convertLineCode(code string) string { + return strings.TrimSuffix(strings.Replace(code, "STIF:Line::", "IDFM:", 1), ":") +} + func declareSchedulesRoutes(router *gin.RouterGroup) { router.GET("/schedules/:type/:code/:station/:way", func(c *gin.Context) { t := string(c.Param("type")) + line := string(c.Param("code")) station := convertLineType(string(c.Param("station"))) rurl, err := url.JoinPath(IDFM_BASEURL, "stop-monitoring") @@ -132,11 +138,25 @@ func declareSchedulesRoutes(router *gin.RouterGroup) { pgs := []PGSchedule{} for _, vehicule := range schedules.Siri.ServiceDelivery.StopMonitoringDelivery[0].MonitoredStopVisit { + if len(line) > 0 && vehicule.MonitoredVehicleJourney.LineRef.Value != line { + continue + } + msg := vehicule.MonitoredVehicleJourney.MonitoredCall.ExpectedDepartureTime.String() - if t == "metros" || t == "buses" || t == "tramways" { + if t == "metros" || t == "buses" || t == "noctiliens" || t == "tramways" { if vehicule.MonitoredVehicleJourney.MonitoredCall.VehicleAtStop { - msg = "À quai" + if t == "metros" { + msg = "Train à quai" + } else { + msg = "A l'arret" + } + } else if time.Until(vehicule.MonitoredVehicleJourney.MonitoredCall.ExpectedDepartureTime) < 0 { + if t == "metros" { + msg = "Train retardé" + } else { + msg = "…" + } } else { msg = fmt.Sprintf("%d mn", int(math.Floor(time.Until(vehicule.MonitoredVehicleJourney.MonitoredCall.ExpectedDepartureTime).Minutes()))) } @@ -148,6 +168,8 @@ func declareSchedulesRoutes(router *gin.RouterGroup) { }) } - c.JSON(http.StatusOK, pgs) + c.JSON(http.StatusOK, APIResult(c, map[string][]PGSchedule{ + "schedules": pgs, + })) }) } diff --git a/api/stations.go b/api/stations.go index 9366906..c55e73a 100644 --- a/api/stations.go +++ b/api/stations.go @@ -2,9 +2,11 @@ package api import ( "encoding/json" + "fmt" "log" "net/http" "os" + "strings" "github.com/gin-gonic/gin" ) @@ -52,13 +54,13 @@ func init() { func declareStationsRoutes(router *gin.RouterGroup) { router.GET("/stations/:type/:code", func(c *gin.Context) { - code := convertLineType(string(c.Param("code"))) + code := convertLineCode(string(c.Param("code"))) var stations []PGStation for _, station := range IDFMStations { if station.Fields.Id == code { pgstation := PGStation{ - Id: station.Fields.StopId, + Id: fmt.Sprintf("STIF:StopPoint:Q:%s:", strings.TrimPrefix(station.Fields.StopId, "IDFM:")), Name: station.Fields.StopName, } diff --git a/api/traffic.go b/api/traffic.go index 8a08325..43d34a5 100644 --- a/api/traffic.go +++ b/api/traffic.go @@ -1,9 +1,169 @@ package api import ( + "encoding/json" + "net/http" + "net/url" + "time" + "github.com/gin-gonic/gin" ) -func declareTrafficRoutes(route *gin.RouterGroup) { - +type IDFMTraffic struct { + Siri struct { + ServiceDelivery struct { + ResponseTimestamp time.Time `json:"ResponseTimestamp"` + ProducerRef string `json:"ProducerRef"` + ResponseMessageIdentifier string `json:"ResponseMessageIdentifier"` + GeneralMessageDelivery []struct { + ResponseTimestamp time.Time `json:"ResponseTimestamp"` + Version string `json:"Version"` + Status string `json:"Status"` + InfoMessage []struct { + FormatRef string `json:"FormatRef"` + RecordedAtTime time.Time `json:"RecordedAtTime"` + ItemIdentifier string `json:"ItemIdentifier"` + InfoMessageIdentifier struct { + Value string `json:"value"` + } `json:"InfoMessageIdentifier"` + InfoMessageVersion int `json:"InfoMessageVersion"` + InfoChannelRef struct { + Value string `json:"value"` + } `json:"InfoChannelRef"` + ValidUntilTime time.Time `json:"ValidUntilTime"` + SituationRef struct { + SituationSimpleRef struct { + Value string `json:"value"` + } `json:"SituationSimpleRef"` + } `json:"SituationRef"` + Content struct { + LineRef []struct { + Value string `json:"value"` + } `json:"LineRef"` + Message []struct { + MessageType string `json:"MessageType"` + MessageText struct { + Value string `json:"value"` + Lang string `json:"lang"` + } `json:"MessageText"` + } `json:"Message"` + } `json:"Content"` + } `json:"InfoMessage"` + } `json:"GeneralMessageDelivery"` + } `json:"ServiceDelivery"` + } `json:"Siri"` +} + +type PGTraffic struct { + Line string `json:"line"` + Slug string `json:"slug"` + Title string `json:"title"` + Message string `json:"message"` +} + +func infoChannelRef2Slug(icr string) int { + switch icr { + case "Information": + return 1 + case "Perturbation": + return 2 + case "Commercial": + return 3 + default: + return 0 + } +} + +func declareTrafficRoutes(router *gin.RouterGroup) { + router.GET("/traffic/:type/:code", func(c *gin.Context) { + code := convertLineType(string(c.Param("code"))) + + rurl, err := url.JoinPath(IDFM_BASEURL, "general-message") + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) + return + } + + requrl, err := url.Parse(rurl) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) + return + } + + reqquery := url.Values{} + reqquery.Add("LineRef", code) + requrl.RawQuery = reqquery.Encode() + + req, err := http.NewRequest("GET", requrl.String(), nil) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) + return + } + + req.Header.Add("Accept", "application/json") + req.Header.Add("apikey", IDFM_TOKEN) + + res, err := http.DefaultClient.Do(req) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) + return + } + defer res.Body.Close() + + var traffic IDFMTraffic + + dec := json.NewDecoder(res.Body) + if err = dec.Decode(&traffic); err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) + return + } + + pgt := PGTraffic{ + Line: code, + Slug: "normal", // normal_trav alerte critique + Title: "Trafic normal", + Message: "Trafic normal sur l'ensemble de la ligne.", + } + + message := "" + slug := 0 + + for _, msg := range traffic.Siri.ServiceDelivery.GeneralMessageDelivery[0].InfoMessage { + mm := "" + + for _, m := range msg.Content.Message { + if m.MessageType == "TEXT_ONLY" { + mm = m.MessageText.Value + } else if mm == "" { + mm = m.MessageText.Value + } + } + + message += mm + + icr := infoChannelRef2Slug(msg.InfoChannelRef.Value) + if icr > slug { + slug = icr + } + } + + switch slug { + case 1: + pgt.Slug = "normal_trav" + pgt.Slug = "Informations" + case 2: + pgt.Slug = "alerte" + pgt.Title = "Perturbations" + case 3: + pgt.Slug = "critique" + pgt.Title = "Commercial" + default: + pgt.Slug = "normal" + } + if message != "" { + pgt.Message = message + } + + c.JSON(http.StatusOK, APIResult(c, pgt)) + }) }