···11+package flyghttracker
22+33+import (
44+ "encoding/json"
55+ "flag"
66+ "fmt"
77+ "net/http"
88+ "strings"
99+ "time"
1010+1111+ "within.website/x/web"
1212+)
1313+1414+var (
1515+ flyghttrackerURL = flag.String("flyghttracker-url", "https://flyght-tracker.fly.dev/api/upcoming_events", "Flyghttracker URL")
1616+)
1717+1818+// Date represents a date in the format "YYYY-MM-DD"
1919+type Date struct {
2020+ time.Time
2121+}
2222+2323+// UnmarshalJSON parses a JSON string in the format "YYYY-MM-DD" to a Date
2424+func (d *Date) UnmarshalJSON(b []byte) error {
2525+ s := strings.Trim(string(b), "\"")
2626+ t, err := time.Parse("2006-01-02", s)
2727+ if err != nil {
2828+ return err
2929+ }
3030+ d.Time = t
3131+ return nil
3232+}
3333+3434+// MarshalJSON returns a JSON string in the format "YYYY-MM-DD"
3535+func (d Date) MarshalJSON() ([]byte, error) {
3636+ return json.Marshal(d.Time.Format("2006-01-02"))
3737+}
3838+3939+// Event represents an event that members of DevRel will be attending.
4040+type Event struct {
4141+ Name string `json:"name"`
4242+ URL string `json:"url"`
4343+ StartDate Date `json:"start_date"`
4444+ EndDate Date `json:"end_date"`
4545+ Location string `json:"location"`
4646+ People []string `json:"people"`
4747+}
4848+4949+// Fetch new events from the Flyght Tracker URL.
5050+//
5151+// It returns a list of events that end in the future and that have "Xe" as one of the attendees.
5252+func Fetch() ([]Event, error) {
5353+ resp, err := http.Get(*flyghttrackerURL)
5454+ if err != nil {
5555+ return nil, fmt.Errorf("failed to fetch flyghttracker events: %w", err)
5656+ }
5757+ defer resp.Body.Close()
5858+5959+ if resp.StatusCode != http.StatusOK {
6060+ return nil, web.NewError(http.StatusOK, resp)
6161+ }
6262+6363+ var events []Event
6464+ if err := json.NewDecoder(resp.Body).Decode(&events); err != nil {
6565+ return nil, fmt.Errorf("failed to decode flyghttracker events: %w", err)
6666+ }
6767+6868+ var result []Event
6969+7070+ for _, event := range events {
7171+ if event.EndDate.Before(time.Now()) {
7272+ continue
7373+ }
7474+7575+ found := false
7676+ for _, person := range event.People {
7777+ if person == "Xe" {
7878+ found = true
7979+ break
8080+ }
8181+ }
8282+8383+ if found {
8484+ result = append(result, event)
8585+ }
8686+ }
8787+8888+ return result, nil
8989+}