Skip to content

Commit

Permalink
add rss/atom feed for flights
Browse files Browse the repository at this point in the history
  • Loading branch information
its-felix committed Nov 6, 2024
1 parent b680f39 commit 8a060b0
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 0 deletions.
23 changes: 23 additions & 0 deletions go/api/data/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,29 @@ func (h *Handler) FlightSchedule(ctx context.Context, fn common.FlightNumber) (*
})
}

func (h *Handler) Flight(ctx context.Context, fn common.FlightNumber, departureDateUTC xtime.LocalDate, departureAirport string, allowCodeShare bool) (*common.Flight, error) {
var flights []*common.Flight
if err := adapt.S3GetJson(ctx, h.s3c, h.bucket, "processed/flights/"+departureDateUTC.Time(nil).Format("2006/01/02")+".json", &flights); err != nil {
if adapt.IsS3NotFound(err) {
return nil, nil
} else {
return nil, err
}
}

for _, f := range flights {
if f.DepartureAirport == departureAirport {
if f.Number() == fn {
return f, nil
} else if _, ok := f.CodeShares[fn]; allowCodeShare && ok {
return f, nil
}
}
}

return nil, nil
}

func (h *Handler) FlightNumbers(ctx context.Context, prefix string, limit int) ([]common.FlightNumber, error) {
var fns []common.FlightNumber
if err := adapt.S3GetJson(ctx, h.s3c, h.bucket, "processed/metadata/flightNumbers.json", &fns); err != nil {
Expand Down
1 change: 1 addition & 0 deletions go/api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/goccy/go-graphviz v0.2.2
github.com/gofrs/uuid/v5 v5.3.0
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/gorilla/feeds v1.2.0
github.com/labstack/echo/v4 v4.12.0
golang.org/x/sync v0.8.0
golang.org/x/time v0.7.0
Expand Down
8 changes: 8 additions & 0 deletions go/api/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,16 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
Expand All @@ -76,6 +82,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
Expand Down
3 changes: 3 additions & 0 deletions go/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/explore-flights/monorepo/go/api/data"
"github.com/explore-flights/monorepo/go/api/search"
"github.com/explore-flights/monorepo/go/api/web"
"github.com/gorilla/feeds"
"github.com/labstack/echo/v4"
"log/slog"
"net/http"
Expand Down Expand Up @@ -73,6 +74,8 @@ func main() {
e.GET("/data/flight/:fn", web.NewFlightNumberEndpoint(dataHandler))
e.GET("/data/flight/:fn/seatmap/:departure/:arrival/:date/:aircraft", web.NewSeatMapEndpoint(dataHandler))
e.GET("/data/:airline/schedule/:aircraftType/:aircraftConfigurationVersion/v2", web.NewQueryFlightSchedulesEndpoint(dataHandler))
e.GET("/data/:fn/:departureDate/:departureAirport/feed.rss", web.NewFlightUpdateFeedEndpoint(dataHandler, "application/rss+xml", (*feeds.Feed).WriteRss))
e.GET("/data/:fn/:departureDate/:departureAirport/feed.atom", web.NewFlightUpdateFeedEndpoint(dataHandler, "application/atom+xml", (*feeds.Feed).WriteAtom))

if err := run(ctx, e); err != nil {
panic(err)
Expand Down
102 changes: 102 additions & 0 deletions go/api/web/feed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package web

import (
"fmt"
"github.com/explore-flights/monorepo/go/api/data"
"github.com/explore-flights/monorepo/go/common"
"github.com/explore-flights/monorepo/go/common/xiter"
"github.com/explore-flights/monorepo/go/common/xtime"
"github.com/gorilla/feeds"
"github.com/labstack/echo/v4"
"io"
"maps"
"net/http"
"slices"
"strings"
"time"
)

func NewFlightUpdateFeedEndpoint(dh *data.Handler, contentType string, writer func(*feeds.Feed, io.Writer) error) echo.HandlerFunc {
feedContent := func(f *common.Flight) string {
content := fmt.Sprintf(
`
Flight %s from %s to %s
Departure: %s
Arrival: %s
Aircraft: %s (%s)
Codeshares: %+v
`,
f.Number().String(),
f.DepartureAirport,
f.ArrivalAirport,
f.DepartureTime.Format(time.RFC3339),
f.ArrivalTime.Format(time.RFC3339),
f.AircraftType,
f.AircraftConfigurationVersion,
strings.Join(slices.Sorted(xiter.Map(maps.Keys(f.CodeShares), common.FlightNumber.String)), ", "),
)

return strings.TrimSpace(content)
}

return func(c echo.Context) error {
fnRaw := c.Param("fn")
departureDateRaw := c.Param("departureDate")
departureAirport := strings.ToUpper(c.Param("departureAirport"))

fn, err := common.ParseFlightNumber(fnRaw)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err)
}

departureDate, err := xtime.ParseLocalDate(departureDateRaw)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err)
}

feedId := baseUrl(c) + fmt.Sprintf("/%s/%s/%s", fn.String(), departureDate.String(), departureAirport)
link := &feeds.Link{Href: fmt.Sprintf("https://explore.flights/flight/%s", fn.String())}
feed := &feeds.Feed{
Id: feedId,
Title: fmt.Sprintf("Flight %s from %s on %s (UTC)", fn.String(), departureAirport, departureDate.String()),
Link: link,
}

f, err := dh.Flight(c.Request().Context(), fn, departureDate, departureAirport, true)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError)
}

if f == nil {
now := time.Now()

feed.Created = now
feed.Updated = now
feed.Items = append(feed.Items, &feeds.Item{
Id: feedId,
Title: "Flight no longer available",
Link: link,
Created: now,
Updated: now,
Content: "The flight is no longer available",
})
} else {
feed.Created = f.Metadata.CreationTime
feed.Updated = f.Metadata.UpdateTime
feed.Items = append(feed.Items, &feeds.Item{
Id: feedId,
Title: fmt.Sprintf("Flight %s from %s to %s on %s (local) updated", fn.String(), f.DepartureAirport, f.ArrivalAirport, f.DepartureTime.Format(time.DateOnly)),
Link: link,
Created: f.Metadata.CreationTime,
Updated: f.Metadata.UpdateTime,
Content: feedContent(f),
})
}

c.Response().Header().Add(echo.HeaderContentType, contentType)
addExpirationHeaders(c, time.Now(), time.Hour)

_ = writer(feed, c.Response())
return nil
}
}

0 comments on commit 8a060b0

Please sign in to comment.