diff --git a/cmd/content.go b/cmd/content.go
index 379b68c..a5ec907 100644
--- a/cmd/content.go
+++ b/cmd/content.go
@@ -17,23 +17,28 @@ along with this program. If not, see .
package cmd
import (
+ "context"
+ "encoding/json"
"fmt"
"log"
- "strconv"
"github.com/spf13/cobra"
- "scm.dairydemon.net/filifa/mlbstats/cmd/internal/statsapi"
+ "scm.dairydemon.net/filifa/mlbstats/api"
)
func content(cmd *cobra.Command, args []string) {
- pkStr := strconv.Itoa(gamePk)
-
- contentResp, err := statsapi.RequestContent(pkStr)
+ client := api.NewAPIClient(api.NewConfiguration())
+ standing, _, err := client.GameApi.Content(context.Background(), gamePk, nil)
if err != nil {
log.Fatal(err)
}
- fmt.Println(string(contentResp))
+ json, err := json.Marshal(standing)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println(string(json))
}
// contentCmd represents the content command
@@ -56,6 +61,6 @@ func init() {
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
- contentCmd.Flags().IntVarP(&gamePk, "gamePk", "g", 0, "game PK")
+ contentCmd.Flags().Int32VarP(&gamePk, "gamePk", "g", 0, "game PK")
contentCmd.MarkFlagRequired("gamePk")
}
diff --git a/cmd/feed.go b/cmd/feed.go
index 38b7495..c0405b2 100644
--- a/cmd/feed.go
+++ b/cmd/feed.go
@@ -17,23 +17,28 @@ along with this program. If not, see .
package cmd
import (
+ "context"
+ "encoding/json"
"fmt"
"log"
- "strconv"
"github.com/spf13/cobra"
- "scm.dairydemon.net/filifa/mlbstats/cmd/internal/statsapi"
+ "scm.dairydemon.net/filifa/mlbstats/api"
)
func feed(cmd *cobra.Command, args []string) {
- pkStr := strconv.Itoa(gamePk)
-
- feedResp, err := statsapi.RequestFeed(pkStr)
+ client := api.NewAPIClient(api.NewConfiguration())
+ standing, _, err := client.GameApi.LiveGameV1(context.Background(), gamePk, nil)
if err != nil {
log.Fatal(err)
}
- fmt.Println(string(feedResp))
+ json, err := json.Marshal(standing)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println(string(json))
}
// feedCmd represents the feed command
@@ -56,6 +61,6 @@ func init() {
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
- feedCmd.Flags().IntVarP(&gamePk, "gamePk", "g", 0, "game PK")
+ feedCmd.Flags().Int32VarP(&gamePk, "gamePk", "g", 0, "game PK")
feedCmd.MarkFlagRequired("gamePk")
}
diff --git a/cmd/internal/statsapi/client.go b/cmd/internal/statsapi/client.go
deleted file mode 100644
index 4d13caa..0000000
--- a/cmd/internal/statsapi/client.go
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-Copyright © 2024 filifa
-
-This program is free software: you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation, either version 3 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program. If not, see .
-*/
-package statsapi
-
-import (
- "encoding/json"
- "io"
- "net/http"
- "net/url"
-
- "github.com/evanphx/json-patch/v5"
-)
-
-// DefaultClient is a statsapi.Client instantiated using http.DefaultClient.
-var DefaultClient = NewClient(http.DefaultClient)
-
-// RequestSchedule uses DefaultClient to access the schedule endpoint.
-func RequestSchedule(sportId, teamId, date string) ([]byte, error) {
- return DefaultClient.RequestSchedule(sportId, teamId, date)
-}
-
-// RequestFeed uses DefaultClient to access the feed endpoint.
-func RequestFeed(gamePk string) ([]byte, error) {
- return DefaultClient.RequestFeed(gamePk)
-}
-
-// RequestDiffPatch uses DefaultClient to access the diffpatch endpoint.
-func RequestDiffPatch(gamePk, startTimecode, pushUpdateId string) (DiffPatchResponse, error) {
- return DefaultClient.RequestDiffPatch(gamePk, startTimecode, pushUpdateId)
-}
-
-// RequestContent uses DefaultClient to access the content endpoint.
-func RequestContent(gamePk string) ([]byte, error) {
- return DefaultClient.RequestContent(gamePk)
-}
-
-// RequestStandings uses DefaultClient to access the standings endpoint.
-func RequestStandings(leagueId string) ([]byte, error) {
- return DefaultClient.RequestStandings(leagueId)
-}
-
-type DiffPatchResponse []byte
-
-// Client is a struct used for making Stats API requests.
-type Client struct {
- baseURL url.URL
- httpClient *http.Client
-}
-
-// NewClient returns a statsapi.Client with statsapi.mlb.com as the base URL.
-func NewClient(c *http.Client) *Client {
- return &Client{
- baseURL: url.URL{
- Scheme: "https",
- Host: "statsapi.mlb.com",
- },
- httpClient: c,
- }
-}
-
-// ExtractPatches extracts a list of jsonpatch.Patch structs from the response
-// given by the diffpatch endpoint. These patches can then be applied more
-// easily than the raw response.
-func (resp *DiffPatchResponse) ExtractPatches() ([]jsonpatch.Patch, error) {
- var patches []jsonpatch.Patch
-
- var objs []map[string]jsonpatch.Patch
- err := json.Unmarshal([]byte(*resp), &objs)
- if err != nil {
- return patches, err
- }
-
- for _, obj := range objs {
- patch := obj["diff"]
- patches = append(patches, patch)
- }
-
- return patches, err
-}
-
-// RequestSchedule accesses the schedule endpoint.
-func (c *Client) RequestSchedule(sportId, teamId, date string) ([]byte, error) {
- endpoint := url.URL{Path: "api/v1/schedule"}
- query := endpoint.Query()
- query.Add("sportId", sportId)
- query.Add("teamId", teamId)
- query.Add("date", date)
- endpoint.RawQuery = query.Encode()
-
- return c.get(&endpoint)
-}
-
-// RequestFeed accesses the feed endpoint.
-func (c *Client) RequestFeed(gamePk string) ([]byte, error) {
- endpoint := url.URL{Path: "api/v1.1/game/" + gamePk + "/feed/live"}
- return c.get(&endpoint)
-}
-
-// RequestDiffPatch accesses the diffpatch endpoint.
-func (c *Client) RequestDiffPatch(gamePk, startTimecode, pushUpdateId string) (DiffPatchResponse, error) {
- endpoint := url.URL{Path: "api/v1.1/game/" + gamePk + "/feed/live/diffPatch"}
- query := endpoint.Query()
- query.Add("language", "en")
- query.Add("startTimecode", startTimecode)
- query.Add("pushUpdateId", pushUpdateId)
- endpoint.RawQuery = query.Encode()
-
- return c.get(&endpoint)
-}
-
-// RequestContent accesses the content endpoint.
-func (c *Client) RequestContent(gamePk string) ([]byte, error) {
- endpoint := url.URL{Path: "api/v1/game/" + gamePk + "/content"}
- return c.get(&endpoint)
-}
-
-// RequestStandings accesses the standings endpoint.
-func (c *Client) RequestStandings(leagueId string) ([]byte, error) {
- endpoint := url.URL{Path: "api/v1/standings"}
- query := endpoint.Query()
- query.Add("leagueId", leagueId)
- endpoint.RawQuery = query.Encode()
-
- return c.get(&endpoint)
-}
-
-// get makes a GET request to the given endpoint and returns the bytes from the
-// body of the response.
-func (c *Client) get(endpoint *url.URL) ([]byte, error) {
- url := c.baseURL.ResolveReference(endpoint)
-
- resp, err := c.httpClient.Get(url.String())
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- body, err := io.ReadAll(resp.Body)
- return body, err
-}
diff --git a/cmd/internal/statsapi/websocket.go b/cmd/internal/statsapi/websocket.go
index fba6c01..0c309b3 100644
--- a/cmd/internal/statsapi/websocket.go
+++ b/cmd/internal/statsapi/websocket.go
@@ -17,6 +17,7 @@ package statsapi
import (
"net/url"
+ "strconv"
"time"
"github.com/gorilla/websocket"
@@ -42,7 +43,7 @@ type GamedayWebsocket struct {
// NewGamedayWebsocket creates a statsapi.GamedayWebsocket using the Stats API
// websocket URL and establishes a connection.
-func NewGamedayWebsocket(gamePk string) (*GamedayWebsocket, error) {
+func NewGamedayWebsocket(gamePk int32) (*GamedayWebsocket, error) {
ws := GamedayWebsocket{
baseURL: url.URL{
Scheme: "wss",
@@ -54,9 +55,9 @@ func NewGamedayWebsocket(gamePk string) (*GamedayWebsocket, error) {
return &ws, err
}
-func (g *GamedayWebsocket) init(gamePk string) error {
+func (g *GamedayWebsocket) init(gamePk int32) error {
endpoint := url.URL{
- Path: "api/v1/game/push/subscribe/gameday/" + gamePk,
+ Path: "api/v1/game/push/subscribe/gameday/" + strconv.Itoa(int(gamePk)),
}
url := g.baseURL.ResolveReference(&endpoint)
diff --git a/cmd/schedule.go b/cmd/schedule.go
index 2e0c015..22443fb 100644
--- a/cmd/schedule.go
+++ b/cmd/schedule.go
@@ -18,12 +18,12 @@ package cmd
import (
"context"
- "fmt"
"encoding/json"
+ "fmt"
"log"
- "github.com/spf13/cobra"
"github.com/antihax/optional"
+ "github.com/spf13/cobra"
"scm.dairydemon.net/filifa/mlbstats/api"
)
@@ -40,7 +40,7 @@ func schedule(cmd *cobra.Command, args []string) {
sportId := int32(sportIDs[string(sport)])
opts := api.ScheduleApiScheduleOpts{
- TeamId: optional.NewInterface(teamIds),
+ TeamId: optional.NewInterface(teamIds),
SportId: optional.NewInterface([]int32{sportId}),
}
diff --git a/cmd/standings.go b/cmd/standings.go
index 6429a0e..01cea33 100644
--- a/cmd/standings.go
+++ b/cmd/standings.go
@@ -22,8 +22,8 @@ import (
"fmt"
"log"
- "github.com/spf13/cobra"
"github.com/antihax/optional"
+ "github.com/spf13/cobra"
"scm.dairydemon.net/filifa/mlbstats/api"
"scm.dairydemon.net/filifa/mlbstats/api/models"
)
@@ -39,7 +39,7 @@ func standings(cmd *cobra.Command, args []string) {
}
client := api.NewAPIClient(api.NewConfiguration())
- standing, _, err := client.StandingsApi.Standings1(context.Background(),string(models.REGULAR_SEASON_StandingsType), &opts)
+ standing, _, err := client.StandingsApi.Standings1(context.Background(), string(models.REGULAR_SEASON_StandingsType), &opts)
if err != nil {
log.Fatal(err)
}
diff --git a/cmd/subscribe.go b/cmd/subscribe.go
index 68335a0..6f62e75 100644
--- a/cmd/subscribe.go
+++ b/cmd/subscribe.go
@@ -17,49 +17,72 @@ along with this program. If not, see .
package cmd
import (
+ "context"
"encoding/json"
"fmt"
"log"
- "strconv"
"time"
+ "github.com/antihax/optional"
+ "github.com/evanphx/json-patch/v5"
"github.com/gorilla/websocket"
"github.com/spf13/cobra"
+ "scm.dairydemon.net/filifa/mlbstats/api"
+ "scm.dairydemon.net/filifa/mlbstats/api/models"
"scm.dairydemon.net/filifa/mlbstats/cmd/internal/statsapi"
)
-var gamePk int
+var gamePk int32
-type Feed struct {
- MetaData metadata
-}
+func extractPatches(resp string) ([]jsonpatch.Patch, error) {
+ var patches []jsonpatch.Patch
-type metadata struct {
- TimeStamp string
-}
-
-func patch(feedResp []byte, gamePk, ts, updateId string) ([]byte, error) {
- diffPatchResp, err := statsapi.RequestDiffPatch(gamePk, ts, updateId)
+ var objs []map[string]jsonpatch.Patch
+ err := json.Unmarshal([]byte(resp), &objs)
if err != nil {
- return feedResp, err
+ return patches, err
}
- patches, err := diffPatchResp.ExtractPatches()
+ for _, obj := range objs {
+ patch := obj["diff"]
+ patches = append(patches, patch)
+ }
+
+ return patches, err
+}
+
+func patch(feed *models.BaseballGameRestObject, client *api.APIClient) error {
+ opts := api.GameApiLiveGameDiffPatchV1Opts{
+ StartTimecode: optional.NewString(feed.MetaData.TimeStamp),
+ }
+
+ diffPatch, _, err := client.GameApi.LiveGameDiffPatchV1(context.Background(), feed.GamePk, &opts)
if err != nil {
- return feedResp, err
+ return err
+ }
+
+ patches, err := extractPatches(diffPatch)
+ if err != nil {
+ return err
+ }
+
+ enc, err := json.Marshal(feed)
+ if err != nil {
+ return err
}
for _, patch := range patches {
- feedResp, err = patch.Apply(feedResp)
+ enc, err = patch.Apply(enc)
if err != nil {
- return feedResp, err
+ return err
}
}
- return feedResp, err
+ err = json.Unmarshal(enc, &feed)
+ return err
}
-func newWebsocket(gamePk string) (*statsapi.GamedayWebsocket, <-chan error, error) {
+func newWebsocket(gamePk int32) (*statsapi.GamedayWebsocket, <-chan error, error) {
ws, err := statsapi.NewGamedayWebsocket(gamePk)
if err != nil {
return nil, nil, err
@@ -71,63 +94,69 @@ func newWebsocket(gamePk string) (*statsapi.GamedayWebsocket, <-chan error, erro
return ws, ch, err
}
-func handleUnexpectedClose(gamePk string) (*statsapi.GamedayWebsocket, []byte, error) {
- ws, _, err := newWebsocket(gamePk)
- if err != nil {
- return nil, nil, err
- }
-
- feedResp, err := statsapi.RequestFeed(gamePk)
- return ws, feedResp, err
-}
-
-func updateFeed(ws *statsapi.GamedayWebsocket, feedResp []byte, gamePk string) ([]byte, error) {
- var feed Feed
- err := json.Unmarshal(feedResp, &feed)
+func handleUnexpectedClose(feed *models.BaseballGameRestObject, client *api.APIClient) (*statsapi.GamedayWebsocket, error) {
+ ws, _, err := newWebsocket(feed.GamePk)
if err != nil {
return nil, err
}
- ts := feed.MetaData.TimeStamp
+ newFeed, _, err := client.GameApi.LiveGameV1(context.Background(), feed.GamePk, nil)
+ *feed = newFeed
+ return ws, err
+}
+
+func updateFeed(feed *models.BaseballGameRestObject, ws *statsapi.GamedayWebsocket, client *api.APIClient) error {
var p statsapi.Push
- err = ws.ReadJSON(&p)
+ err := ws.ReadJSON(&p)
if websocket.IsUnexpectedCloseError(err, statsapi.GameFinalCode, statsapi.GameUnavailableCode) {
log.Println(err)
- newWs, feedResp, err := handleUnexpectedClose(gamePk)
+ newWs, err := handleUnexpectedClose(feed, client)
if err != nil {
- return feedResp, err
+ return err
}
+
*ws = *newWs
- return feedResp, err
+ return err
} else if err != nil {
- return nil, err
+ return err
}
- feedResp, err = patch(feedResp, gamePk, ts, p.UpdateId)
+ err = patch(feed, client)
if err != nil {
- feedResp, err = statsapi.RequestFeed(gamePk)
+ newFeed, _, err := client.GameApi.LiveGameV1(context.Background(), feed.GamePk, nil)
+ if err != nil {
+ return err
+ }
+
+ *feed = newFeed
}
- return feedResp, err
+
+ return err
}
func subscribe(cmd *cobra.Command, args []string) {
- pkStr := strconv.Itoa(gamePk)
- ws, _, err := newWebsocket(pkStr)
+ ws, _, err := newWebsocket(gamePk)
if err != nil {
log.Fatal(err)
}
defer ws.Close()
- feedResp, err := statsapi.RequestFeed(pkStr)
+ client := api.NewAPIClient(api.NewConfiguration())
+ feed, _, err := client.GameApi.LiveGameV1(context.Background(), gamePk, nil)
if err != nil {
log.Fatal(err)
}
for {
- fmt.Println(string(feedResp))
+ json, err := json.Marshal(feed)
+ if err != nil {
+ log.Fatal(err)
+ }
- feedResp, err = updateFeed(ws, feedResp, pkStr)
+ fmt.Println(string(json))
+
+ err = updateFeed(&feed, ws, client)
if err != nil {
log.Fatal(err)
}
@@ -157,6 +186,6 @@ func init() {
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
- subscribeCmd.Flags().IntVarP(&gamePk, "gamePk", "g", 0, "game PK")
+ subscribeCmd.Flags().Int32VarP(&gamePk, "gamePk", "g", 0, "game PK")
subscribeCmd.MarkFlagRequired("gamePk")
}