league support check from db

This commit is contained in:
Asher Samuel 2025-06-06 03:36:15 +03:00
parent eb4f267142
commit aedefbdb0b
9 changed files with 283 additions and 67 deletions

View File

@ -76,3 +76,4 @@ DROP TABLE IF EXISTS refresh_tokens;
DROP TABLE IF EXISTS otps; DROP TABLE IF EXISTS otps;
DROP TABLE IF EXISTS odds; DROP TABLE IF EXISTS odds;
DROP TABLE IF EXISTS events; DROP TABLE IF EXISTS events;
DROP TABLE IF EXISTS leagues;

View File

@ -232,6 +232,13 @@ CREATE TABLE companies (
admin_id BIGINT NOT NULL, admin_id BIGINT NOT NULL,
wallet_id BIGINT NOT NULL wallet_id BIGINT NOT NULL
); );
CREATE TABLE leagues (
id BIGINT PRIMARY KEY,
name TEXT NOT NULL,
country_code TEXT,
bet365_id INT,
is_active BOOLEAN DEFAULT true
);
-- Views -- Views
CREATE VIEW companies_details AS CREATE VIEW companies_details AS
SELECT companies.*, SELECT companies.*,

37
db/query/leagues.sql Normal file
View File

@ -0,0 +1,37 @@
-- name: InsertLeague :exec
INSERT INTO leagues (
id,
name,
country_code,
bet365_id,
is_active
) VALUES (
$1, $2, $3, $4, $5
)
ON CONFLICT (id) DO UPDATE
SET name = EXCLUDED.name,
country_code = EXCLUDED.country_code,
bet365_id = EXCLUDED.bet365_id,
is_active = EXCLUDED.is_active;
-- name: GetSupportedLeagues :many
SELECT id,
name,
country_code,
bet365_id,
is_active
FROM leagues
WHERE is_active = true;
-- name: CheckLeagueSupport :one
SELECT EXISTS(
SELECT 1
FROM leagues
WHERE id = $1
AND is_active = true
);
-- name: UpdateLeague :exec
UPDATE leagues
SET name = $1,
country_code = $2,
bet365_id = $3,
is_active = $4
WHERE id = $5;

128
gen/db/leagues.sql.go Normal file
View File

@ -0,0 +1,128 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: leagues.sql
package dbgen
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const CheckLeagueSupport = `-- name: CheckLeagueSupport :one
SELECT EXISTS(
SELECT 1
FROM leagues
WHERE id = $1
AND is_active = true
)
`
func (q *Queries) CheckLeagueSupport(ctx context.Context, id int64) (bool, error) {
row := q.db.QueryRow(ctx, CheckLeagueSupport, id)
var exists bool
err := row.Scan(&exists)
return exists, err
}
const GetSupportedLeagues = `-- name: GetSupportedLeagues :many
SELECT id,
name,
country_code,
bet365_id,
is_active
FROM leagues
WHERE is_active = true
`
func (q *Queries) GetSupportedLeagues(ctx context.Context) ([]League, error) {
rows, err := q.db.Query(ctx, GetSupportedLeagues)
if err != nil {
return nil, err
}
defer rows.Close()
var items []League
for rows.Next() {
var i League
if err := rows.Scan(
&i.ID,
&i.Name,
&i.CountryCode,
&i.Bet365ID,
&i.IsActive,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const InsertLeague = `-- name: InsertLeague :exec
INSERT INTO leagues (
id,
name,
country_code,
bet365_id,
is_active
) VALUES (
$1, $2, $3, $4, $5
)
ON CONFLICT (id) DO UPDATE
SET name = EXCLUDED.name,
country_code = EXCLUDED.country_code,
bet365_id = EXCLUDED.bet365_id,
is_active = EXCLUDED.is_active
`
type InsertLeagueParams struct {
ID int64 `json:"id"`
Name string `json:"name"`
CountryCode pgtype.Text `json:"country_code"`
Bet365ID pgtype.Int4 `json:"bet365_id"`
IsActive pgtype.Bool `json:"is_active"`
}
func (q *Queries) InsertLeague(ctx context.Context, arg InsertLeagueParams) error {
_, err := q.db.Exec(ctx, InsertLeague,
arg.ID,
arg.Name,
arg.CountryCode,
arg.Bet365ID,
arg.IsActive,
)
return err
}
const UpdateLeague = `-- name: UpdateLeague :exec
UPDATE leagues
SET name = $1,
country_code = $2,
bet365_id = $3,
is_active = $4
WHERE id = $5
`
type UpdateLeagueParams struct {
Name string `json:"name"`
CountryCode pgtype.Text `json:"country_code"`
Bet365ID pgtype.Int4 `json:"bet365_id"`
IsActive pgtype.Bool `json:"is_active"`
ID int64 `json:"id"`
}
func (q *Queries) UpdateLeague(ctx context.Context, arg UpdateLeagueParams) error {
_, err := q.db.Exec(ctx, UpdateLeague,
arg.Name,
arg.CountryCode,
arg.Bet365ID,
arg.IsActive,
arg.ID,
)
return err
}

View File

@ -199,6 +199,14 @@ type Event struct {
Source pgtype.Text `json:"source"` Source pgtype.Text `json:"source"`
} }
type League struct {
ID int64 `json:"id"`
Name string `json:"name"`
CountryCode pgtype.Text `json:"country_code"`
Bet365ID pgtype.Int4 `json:"bet365_id"`
IsActive pgtype.Bool `json:"is_active"`
}
type Notification struct { type Notification struct {
ID string `json:"id"` ID string `json:"id"`
RecipientID int64 `json:"recipient_id"` RecipientID int64 `json:"recipient_id"`

View File

@ -1,39 +1,9 @@
package domain package domain
// TODO Will make this dynamic by moving into the database type League struct {
ID int64
var SupportedLeagues = []int64{ Name string
// Football CountryCode string
10041282, //Premier League Bet365ID int32
10083364, //La Liga IsActive bool
10041095, //German Bundesliga
10041100, //Ligue 1
10041809, //UEFA Champions League
10041957, //UEFA Europa League
10079560, //UEFA Conference League
10047168, // US MLS
10044469, // Ethiopian Premier League
10050282, //UEFA Nations League
10043156, //England FA Cup
10042103, //France Cup
10041088, //Premier League 2
10084250, //Turkiye Super League
10041187, //Kenya Super League
10041315, //Italian Serie A
10041391, //Netherlands Eredivisie
// Basketball
173998768, //NBA
10041830, //NBA
10049984, //WNBA
10037165, //German Bundesliga
10036608, //Italian Lega 1
10040795, //EuroLeague
// Ice Hockey
10037477, //NHL
10037447, //AHL
10069385, //IIHF World Championship
} }

View File

@ -9,7 +9,7 @@ type BaseResultResponse struct {
Results []json.RawMessage `json:"results"` Results []json.RawMessage `json:"results"`
} }
type League struct { type LeagueRes struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
CC string `json:"cc"` CC string `json:"cc"`
@ -32,7 +32,7 @@ type FootballResultResponse struct {
SportID string `json:"sport_id"` SportID string `json:"sport_id"`
Time string `json:"time"` Time string `json:"time"`
TimeStatus string `json:"time_status"` TimeStatus string `json:"time_status"`
League League `json:"league"` League LeagueRes `json:"league"`
Home Team `json:"home"` Home Team `json:"home"`
Away Team `json:"away"` Away Team `json:"away"`
SS string `json:"ss"` SS string `json:"ss"`
@ -71,7 +71,7 @@ type BasketballResultResponse struct {
SportID string `json:"sport_id"` SportID string `json:"sport_id"`
Time string `json:"time"` Time string `json:"time"`
TimeStatus string `json:"time_status"` TimeStatus string `json:"time_status"`
League League `json:"league"` League LeagueRes `json:"league"`
Home Team `json:"home"` Home Team `json:"home"`
Away Team `json:"away"` Away Team `json:"away"`
SS string `json:"ss"` SS string `json:"ss"`
@ -118,7 +118,7 @@ type IceHockeyResultResponse struct {
SportID string `json:"sport_id"` SportID string `json:"sport_id"`
Time string `json:"time"` Time string `json:"time"`
TimeStatus string `json:"time_status"` TimeStatus string `json:"time_status"`
League League `json:"league"` League LeagueRes `json:"league"`
Home Team `json:"home"` Home Team `json:"home"`
Away Team `json:"away"` Away Team `json:"away"`
SS string `json:"ss"` SS string `json:"ss"`

View File

@ -0,0 +1,61 @@
package repository
import (
"context"
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/jackc/pgx/v5/pgtype"
)
func (s *Store) SaveLeague(ctx context.Context, l domain.League) error {
return s.queries.InsertLeague(ctx, dbgen.InsertLeagueParams{
ID: l.ID,
Name: l.Name,
CountryCode: pgtype.Text{String: l.CountryCode, Valid: true},
Bet365ID: pgtype.Int4{Int32: l.Bet365ID, Valid: true},
IsActive: pgtype.Bool{Bool: l.IsActive, Valid: true},
})
}
func (s *Store) GetSupportedLeagues(ctx context.Context) ([]domain.League, error) {
leagues, err := s.queries.GetSupportedLeagues(ctx)
if err != nil {
return nil, err
}
supportedLeagues := make([]domain.League, len(leagues))
for i, league := range leagues {
supportedLeagues[i] = domain.League{
ID: league.ID,
Name: league.Name,
CountryCode: league.CountryCode.String,
Bet365ID: league.Bet365ID.Int32,
IsActive: league.IsActive.Bool,
}
}
return supportedLeagues, nil
}
func (s *Store) CheckLeagueSupport(ctx context.Context, leagueID int64) (bool, error) {
return s.queries.CheckLeagueSupport(ctx, leagueID)
}
// TODO: change to only take league id instad of the whole league
func (s *Store) SetLeagueActive(ctx context.Context, l domain.League) error {
return s.queries.UpdateLeague(ctx, dbgen.UpdateLeagueParams{
Name: l.Name,
CountryCode: pgtype.Text{String: l.CountryCode, Valid: true},
Bet365ID: pgtype.Int4{Int32: l.Bet365ID, Valid: true},
IsActive: pgtype.Bool{Bool: true, Valid: true},
})
}
func (s *Store) SetLeagueInActive(ctx context.Context, l domain.League) error {
return s.queries.UpdateLeague(ctx, dbgen.UpdateLeagueParams{
Name: l.Name,
CountryCode: pgtype.Text{String: l.CountryCode, Valid: true},
Bet365ID: pgtype.Int4{Int32: l.Bet365ID, Valid: true},
IsActive: pgtype.Bool{Bool: false, Valid: true},
})
}

View File

@ -7,7 +7,6 @@ import (
"io" "io"
"log" "log"
"net/http" "net/http"
"slices"
"strconv" "strconv"
"sync" "sync"
"time" "time"
@ -242,11 +241,16 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, sour
continue continue
} }
if !slices.Contains(domain.SupportedLeagues, leagueID) { // doesn't make sense to save and check back to back, but for now it can be here
// fmt.Printf("⚠️ Skipping league %s (%d) as it is not supported\n", ev.League.Name, leagueID) s.store.SaveLeague(ctx, domain.League{
ID: leagueID,
Name: ev.League.Name,
IsActive: true,
})
if supported, err := s.store.CheckLeagueSupport(ctx, leagueID); !supported || err != nil {
skippedLeague = append(skippedLeague, ev.League.Name) skippedLeague = append(skippedLeague, ev.League.Name)
// ! for now continue
// continue
} }
event := domain.UpcomingEvent{ event := domain.UpcomingEvent{