fetch events from betfair

This commit is contained in:
Asher Samuel 2025-05-23 13:09:44 +03:00
parent 97dc54e8ae
commit 11a70ec1dc
26 changed files with 134 additions and 58 deletions

View File

@ -3,5 +3,7 @@
"Cashout", "Cashout",
"narg", "narg",
"sqlc" "sqlc"
] ],
"postman.settings.dotenv-detection-notification-visibility": false,
"makefile.configureOnOpen": false
} }

View File

@ -2,6 +2,7 @@ package main
import ( import (
// "context" // "context"
"context"
"fmt" "fmt"
"log/slog" "log/slog"
"os" "os"
@ -69,6 +70,13 @@ func main() {
userSvc := user.NewService(store, store, mockSms, mockEmail) userSvc := user.NewService(store, store, mockSms, mockEmail)
eventSvc := event.New(cfg.Bet365Token, store) eventSvc := event.New(cfg.Bet365Token, store)
// test start
logger.Info("test fetching...")
if err := eventSvc.FetchUpcomingEvents(context.TODO()); err != nil {
panic(err)
}
// test end
oddsSvc := odds.New(cfg.Bet365Token, store) oddsSvc := odds.New(cfg.Bet365Token, store)
resultSvc := result.NewService(store, cfg, logger) resultSvc := result.NewService(store, cfg, logger)
ticketSvc := ticket.NewService(store) ticketSvc := ticket.NewService(store)

View File

@ -204,7 +204,8 @@ CREATE TABLE events (
match_period INT, match_period INT,
is_live BOOLEAN, is_live BOOLEAN,
status TEXT, status TEXT,
fetched_at TIMESTAMP DEFAULT now() fetched_at TIMESTAMP DEFAULT now(),
source TEXT DEFAULT 'b365api'
); );
CREATE TABLE odds ( CREATE TABLE odds (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,

View File

@ -19,7 +19,8 @@ INSERT INTO events (
added_time, added_time,
match_period, match_period,
is_live, is_live,
status status,
source
) )
VALUES ( VALUES (
$1, $1,
@ -41,7 +42,8 @@ VALUES (
$17, $17,
$18, $18,
$19, $19,
$20 $20,
$21
) ON CONFLICT (id) DO ) ON CONFLICT (id) DO
UPDATE UPDATE
SET sport_id = EXCLUDED.sport_id, SET sport_id = EXCLUDED.sport_id,
@ -63,6 +65,7 @@ SET sport_id = EXCLUDED.sport_id,
match_period = EXCLUDED.match_period, match_period = EXCLUDED.match_period,
is_live = EXCLUDED.is_live, is_live = EXCLUDED.is_live,
status = EXCLUDED.status, status = EXCLUDED.status,
source = EXCLUDED.source,
fetched_at = now(); fetched_at = now();
-- name: InsertUpcomingEvent :exec -- name: InsertUpcomingEvent :exec
INSERT INTO events ( INSERT INTO events (
@ -80,7 +83,8 @@ INSERT INTO events (
league_cc, league_cc,
start_time, start_time,
is_live, is_live,
status status,
source
) )
VALUES ( VALUES (
$1, $1,
@ -97,7 +101,8 @@ VALUES (
$12, $12,
$13, $13,
false, false,
'upcoming' 'upcoming',
$14
) ON CONFLICT (id) DO ) ON CONFLICT (id) DO
UPDATE UPDATE
SET sport_id = EXCLUDED.sport_id, SET sport_id = EXCLUDED.sport_id,
@ -114,6 +119,7 @@ SET sport_id = EXCLUDED.sport_id,
start_time = EXCLUDED.start_time, start_time = EXCLUDED.start_time,
is_live = false, is_live = false,
status = 'upcoming', status = 'upcoming',
source = EXCLUDED.source,
fetched_at = now(); fetched_at = now();
-- name: ListLiveEvents :many -- name: ListLiveEvents :many
SELECT id SELECT id
@ -135,6 +141,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE is_live = false WHERE is_live = false
@ -156,6 +163,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE is_live = false WHERE is_live = false
@ -191,6 +199,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE is_live = false WHERE is_live = false
@ -221,6 +230,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE id = $1 WHERE id = $1

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: auth.sql // source: auth.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: bet.sql // source: bet.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: branch.sql // source: branch.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: company.sql // source: company.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: copyfrom.go // source: copyfrom.go
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: events.sql // source: events.sql
package dbgen package dbgen
@ -37,6 +37,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE is_live = false WHERE is_live = false
@ -60,6 +61,7 @@ type GetAllUpcomingEventsRow struct {
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
} }
@ -88,6 +90,7 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEve
&i.StartTime, &i.StartTime,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
); err != nil { ); err != nil {
return nil, err return nil, err
@ -116,6 +119,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE is_live = false WHERE is_live = false
@ -140,6 +144,7 @@ type GetExpiredUpcomingEventsRow struct {
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
} }
@ -168,6 +173,7 @@ func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context) ([]GetExpiredUpc
&i.StartTime, &i.StartTime,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
); err != nil { ); err != nil {
return nil, err return nil, err
@ -196,6 +202,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE is_live = false WHERE is_live = false
@ -235,6 +242,7 @@ type GetPaginatedUpcomingEventsRow struct {
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
} }
@ -268,6 +276,7 @@ func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginat
&i.StartTime, &i.StartTime,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
); err != nil { ); err != nil {
return nil, err return nil, err
@ -323,6 +332,7 @@ SELECT id,
start_time, start_time,
is_live, is_live,
status, status,
source,
fetched_at fetched_at
FROM events FROM events
WHERE id = $1 WHERE id = $1
@ -347,6 +357,7 @@ type GetUpcomingByIDRow struct {
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
} }
@ -369,6 +380,7 @@ func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (GetUpcomingBy
&i.StartTime, &i.StartTime,
&i.IsLive, &i.IsLive,
&i.Status, &i.Status,
&i.Source,
&i.FetchedAt, &i.FetchedAt,
) )
return i, err return i, err
@ -395,7 +407,8 @@ INSERT INTO events (
added_time, added_time,
match_period, match_period,
is_live, is_live,
status status,
source
) )
VALUES ( VALUES (
$1, $1,
@ -417,7 +430,8 @@ VALUES (
$17, $17,
$18, $18,
$19, $19,
$20 $20,
$21
) ON CONFLICT (id) DO ) ON CONFLICT (id) DO
UPDATE UPDATE
SET sport_id = EXCLUDED.sport_id, SET sport_id = EXCLUDED.sport_id,
@ -439,6 +453,7 @@ SET sport_id = EXCLUDED.sport_id,
match_period = EXCLUDED.match_period, match_period = EXCLUDED.match_period,
is_live = EXCLUDED.is_live, is_live = EXCLUDED.is_live,
status = EXCLUDED.status, status = EXCLUDED.status,
source = EXCLUDED.source,
fetched_at = now() fetched_at = now()
` `
@ -463,6 +478,7 @@ type InsertEventParams struct {
MatchPeriod pgtype.Int4 `json:"match_period"` MatchPeriod pgtype.Int4 `json:"match_period"`
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
Source pgtype.Text `json:"source"`
} }
func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error { func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error {
@ -487,6 +503,7 @@ func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error
arg.MatchPeriod, arg.MatchPeriod,
arg.IsLive, arg.IsLive,
arg.Status, arg.Status,
arg.Source,
) )
return err return err
} }
@ -507,7 +524,8 @@ INSERT INTO events (
league_cc, league_cc,
start_time, start_time,
is_live, is_live,
status status,
source
) )
VALUES ( VALUES (
$1, $1,
@ -524,7 +542,8 @@ VALUES (
$12, $12,
$13, $13,
false, false,
'upcoming' 'upcoming',
$14
) ON CONFLICT (id) DO ) ON CONFLICT (id) DO
UPDATE UPDATE
SET sport_id = EXCLUDED.sport_id, SET sport_id = EXCLUDED.sport_id,
@ -541,6 +560,7 @@ SET sport_id = EXCLUDED.sport_id,
start_time = EXCLUDED.start_time, start_time = EXCLUDED.start_time,
is_live = false, is_live = false,
status = 'upcoming', status = 'upcoming',
source = EXCLUDED.source,
fetched_at = now() fetched_at = now()
` `
@ -558,6 +578,7 @@ type InsertUpcomingEventParams struct {
LeagueName pgtype.Text `json:"league_name"` LeagueName pgtype.Text `json:"league_name"`
LeagueCc pgtype.Text `json:"league_cc"` LeagueCc pgtype.Text `json:"league_cc"`
StartTime pgtype.Timestamp `json:"start_time"` StartTime pgtype.Timestamp `json:"start_time"`
Source pgtype.Text `json:"source"`
} }
func (q *Queries) InsertUpcomingEvent(ctx context.Context, arg InsertUpcomingEventParams) error { func (q *Queries) InsertUpcomingEvent(ctx context.Context, arg InsertUpcomingEventParams) error {
@ -575,6 +596,7 @@ func (q *Queries) InsertUpcomingEvent(ctx context.Context, arg InsertUpcomingEve
arg.LeagueName, arg.LeagueName,
arg.LeagueCc, arg.LeagueCc,
arg.StartTime, arg.StartTime,
arg.Source,
) )
return err return err
} }

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
package dbgen package dbgen
@ -194,6 +194,7 @@ type Event struct {
IsLive pgtype.Bool `json:"is_live"` IsLive pgtype.Bool `json:"is_live"`
Status pgtype.Text `json:"status"` Status pgtype.Text `json:"status"`
FetchedAt pgtype.Timestamp `json:"fetched_at"` FetchedAt pgtype.Timestamp `json:"fetched_at"`
Source pgtype.Text `json:"source"`
} }
type Notification struct { type Notification struct {

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: notification.sql // source: notification.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: odds.sql // source: odds.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: otp.sql // source: otp.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: referal.sql // source: referal.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: result.sql // source: result.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: ticket.sql // source: ticket.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: transactions.sql // source: transactions.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: transfer.sql // source: transfer.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: user.sql // source: user.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: virtual_games.sql // source: virtual_games.sql
package dbgen package dbgen

View File

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.28.0 // sqlc v1.29.0
// source: wallet.sql // source: wallet.sql
package dbgen package dbgen

View File

@ -24,6 +24,33 @@ type Event struct {
IsLive bool IsLive bool
Status string Status string
} }
type BetResult struct {
Success int `json:"success"`
Pager struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Total int `json:"total"`
}
Results []struct {
ID string `json:"id"`
SportID string `json:"sport_id"`
Time string `json:"time"`
League struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"home"`
Away *struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"away"`
} `json:"results"`
}
type UpcomingEvent struct { type UpcomingEvent struct {
ID string // Event ID ID string // Event ID
SportID string // Sport ID SportID string // Sport ID
@ -38,6 +65,7 @@ type UpcomingEvent struct {
LeagueName string // League name LeagueName string // League name
LeagueCC string // League country code LeagueCC string // League country code
StartTime time.Time // Converted from "time" field in UNIX format StartTime time.Time // Converted from "time" field in UNIX format
Source string // bet api provider (bet365, betfair)
} }
type MatchResult struct { type MatchResult struct {
EventID string EventID string

View File

@ -57,6 +57,7 @@ func (s *Store) SaveUpcomingEvent(ctx context.Context, e domain.UpcomingEvent) e
LeagueName: pgtype.Text{String: e.LeagueName, Valid: true}, LeagueName: pgtype.Text{String: e.LeagueName, Valid: true},
LeagueCc: pgtype.Text{String: e.LeagueCC, Valid: true}, LeagueCc: pgtype.Text{String: e.LeagueCC, Valid: true},
StartTime: pgtype.Timestamp{Time: e.StartTime, Valid: true}, StartTime: pgtype.Timestamp{Time: e.StartTime, Valid: true},
Source: pgtype.Text{String: e.Source, Valid: true},
}) })
} }
@ -85,6 +86,7 @@ func (s *Store) GetAllUpcomingEvents(ctx context.Context) ([]domain.UpcomingEven
LeagueName: e.LeagueName.String, LeagueName: e.LeagueName.String,
LeagueCC: e.LeagueCc.String, LeagueCC: e.LeagueCc.String,
StartTime: e.StartTime.Time.UTC(), StartTime: e.StartTime.Time.UTC(),
Source: e.Source.String,
} }
} }
return upcomingEvents, nil return upcomingEvents, nil
@ -112,6 +114,7 @@ func (s *Store) GetExpiredUpcomingEvents(ctx context.Context) ([]domain.Upcoming
LeagueName: e.LeagueName.String, LeagueName: e.LeagueName.String,
LeagueCC: e.LeagueCc.String, LeagueCC: e.LeagueCc.String,
StartTime: e.StartTime.Time.UTC(), StartTime: e.StartTime.Time.UTC(),
Source: e.Source.String,
} }
} }
return upcomingEvents, nil return upcomingEvents, nil
@ -151,6 +154,7 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, limit int32, off
LeagueName: e.LeagueName.String, LeagueName: e.LeagueName.String,
LeagueCC: e.LeagueCc.String, LeagueCC: e.LeagueCc.String,
StartTime: e.StartTime.Time.UTC(), StartTime: e.StartTime.Time.UTC(),
Source: e.Source.String,
} }
} }
totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{ totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{
@ -190,6 +194,7 @@ func (s *Store) GetUpcomingEventByID(ctx context.Context, ID string) (domain.Upc
LeagueName: event.LeagueName.String, LeagueName: event.LeagueName.String,
LeagueCC: event.LeagueCc.String, LeagueCC: event.LeagueCc.String,
StartTime: event.StartTime.Time.UTC(), StartTime: event.StartTime.Time.UTC(),
Source: event.Source.String,
}, nil }, nil
} }
func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore, status string) error { func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore, status string) error {

View File

@ -99,6 +99,29 @@ func (s *service) FetchLiveEvents(ctx context.Context) error {
} }
func (s *service) FetchUpcomingEvents(ctx context.Context) error { func (s *service) FetchUpcomingEvents(ctx context.Context) error {
var wg sync.WaitGroup
urls := []struct {
name string
source string
}{
{"https://api.b365api.com/v1/bet365/upcoming?sport_id=%d&token=%s&page=%d", "bet365"},
{"https://api.b365api.com/v1/betfair/sb/upcoming?sport_id=%d&token=%s&page=%d", "betfair"},
}
for _, url := range urls {
wg.Add(1)
go func() {
defer wg.Done()
s.fetchUpcomingEventsFromProvider(ctx, url.name, url.source)
}()
}
wg.Wait()
return nil
}
func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, source string) {
sportIDs := []int{1, 18} sportIDs := []int{1, 18}
var totalPages int = 1 var totalPages int = 1
var page int = 0 var page int = 0
@ -109,8 +132,8 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
time.Sleep(3 * time.Second) //This will restrict the fetching to 1200 requests per hour time.Sleep(3 * time.Second) //This will restrict the fetching to 1200 requests per hour
page = page + 1 page = page + 1
url := fmt.Sprintf("https://api.b365api.com/v1/bet365/upcoming?sport_id=%d&token=%s&page=%d", sportID, s.token, page) url := fmt.Sprintf(url, sportID, s.token, page)
log.Printf("📡 Fetching data for event data page %d", page) log.Printf("📡 Fetching event data from %s, data page %d", source, page)
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
log.Printf("❌ Failed to fetch event data for page %d: %v", page, err) log.Printf("❌ Failed to fetch event data for page %d: %v", page, err)
@ -119,31 +142,8 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
defer resp.Body.Close() defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body) body, _ := io.ReadAll(resp.Body)
var data struct { var data domain.BetResult
Success int `json:"success"`
Pager struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
Total int `json:"total"`
}
Results []struct {
ID string `json:"id"`
SportID string `json:"sport_id"`
Time string `json:"time"`
League struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"home"`
Away *struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"away"`
} `json:"results"`
}
if err := json.Unmarshal(body, &data); err != nil || data.Success != 1 { if err := json.Unmarshal(body, &data); err != nil || data.Success != 1 {
continue continue
} }
@ -181,6 +181,7 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
LeagueName: ev.League.Name, LeagueName: ev.League.Name,
LeagueCC: "", LeagueCC: "",
StartTime: time.Unix(startUnix, 0).UTC(), StartTime: time.Unix(startUnix, 0).UTC(),
Source: source,
} }
if ev.Away != nil { if ev.Away != nil {
@ -198,8 +199,6 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
count++ count++
} }
} }
return nil
} }
func getString(v interface{}) string { func getString(v interface{}) string {