fix: event and odd fetching for all sports

This commit is contained in:
Samuel Tariku 2025-05-31 20:34:10 +03:00
parent bab1c6bb4c
commit c0680537db
13 changed files with 1030 additions and 633 deletions

View File

@ -14,6 +14,13 @@ var SupportedLeagues = []int64{
10047168, // US MLS 10047168, // US MLS
10044469, // Ethiopian Premier League 10044469, // Ethiopian Premier League
10050282, //UEFA Nations League 10050282, //UEFA Nations League
10044685, //FIFA Club World Cup
10082328, //Kings League World Cup
10081269, //CONCACAF Champions Cup
10040162, //Asia - World Cup Qualifying
10067624, //South America - World Cup Qualifying
10067913, // Europe - World Cup Qualifying
10067624, // South America - World Cup Qualifying
10043156, //England FA Cup 10043156, //England FA Cup
10042103, //France Cup 10042103, //France Cup
@ -22,6 +29,21 @@ var SupportedLeagues = []int64{
10041187, //Kenya Super League 10041187, //Kenya Super League
10041315, //Italian Serie A 10041315, //Italian Serie A
10041391, //Netherlands Eredivisie 10041391, //Netherlands Eredivisie
10036538, //Spain Segunda
10041058, //Denmark Superligaen
10077480, //Womens International
10046936, // USA NPSL
10085159, //Baller League UK
10040601, //Argentina Cup
10037440, //Brazil Serie A
10043205, //Copa Sudamericana
10037327, //Austria Landesliga
10082020, //USA USL League One Cup
10037075, //International Match
10046648, //Kenya Cup
10040485, //Kenya Super League
10041369, //Norway Eliteserien
// Basketball // Basketball
173998768, //NBA 173998768, //NBA
@ -30,10 +52,15 @@ var SupportedLeagues = []int64{
10037165, //German Bundesliga 10037165, //German Bundesliga
10036608, //Italian Lega 1 10036608, //Italian Lega 1
10040795, //EuroLeague 10040795, //EuroLeague
10084178, //Kenya Premier League
10043548, //International Women
// Ice Hockey // Ice Hockey
10037477, //NHL 10037477, //NHL
10037447, //AHL 10037447, //AHL
10074238, // AIHL
10069385, //IIHF World Championship 10069385, //IIHF World Championship
// Cricket
} }

View File

@ -49,3 +49,76 @@ type IceHockeyOddsResponse struct {
FirstPeriod OddsSection `json:"1st_period"` FirstPeriod OddsSection `json:"1st_period"`
Others []OddsSection `json:"others"` Others []OddsSection `json:"others"`
} }
type CricketOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
First_Over OddsSection `json:"1st_over"`
First_Innings OddsSection `json:"innings_1"`
Main OddsSection `json:"main"`
Match OddsSection `json:"match"`
Others []OddsSection `json:"others"`
Player OddsSection `json:"player"`
Team OddsSection `json:"team"`
}
type VolleyballOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
Main OddsSection `json:"main"`
Others []OddsSection `json:"others"`
}
type DartsOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
OneEightys OddsSection `json:"180s"`
Extra OddsSection `json:"extra"`
Leg OddsSection `json:"leg"`
Main OddsSection `json:"main"`
Others []OddsSection `json:"others"`
}
type FutsalOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
Main OddsSection `json:"main"`
Score OddsSection `json:"score"`
Others []OddsSection `json:"others"`
}
type AmericanFootballOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
HalfProps OddsSection `json:"half_props"`
Main OddsSection `json:"main"`
QuarterProps OddsSection `json:"quarter_props"`
Others []OddsSection `json:"others"`
}
type RugbyLeagueOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
TenMinute OddsSection `json:"10minute"`
Half OddsSection `json:"half"`
Main OddsSection `json:"main"`
Main2 OddsSection `json:"main_2"`
Others []OddsSection `json:"others"`
Player OddsSection `json:"player"`
Score OddsSection `json:"score"`
Team OddsSection `json:"team"`
}
type RugbyUnionOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
Half OddsSection `json:"half"`
Main OddsSection `json:"main"`
Main2 OddsSection `json:"main_2"`
Others []OddsSection `json:"others"`
Player OddsSection `json:"player"`
Score OddsSection `json:"score"`
Team OddsSection `json:"team"`
}
type BaseballOddsResponse struct {
EventID string `json:"event_id"`
FI string `json:"FI"`
Main OddsSection `json:"main"`
MainProps OddsSection `json:"main_props"`
}

View File

@ -290,3 +290,168 @@ type FutsalResultResponse struct {
ConfirmedAt string `json:"confirmed_at"` ConfirmedAt string `json:"confirmed_at"`
Bet365ID string `json:"bet365_id"` Bet365ID string `json:"bet365_id"`
} }
// NFLResultResponse represents the structure for NFL game results
type NFLResultResponse struct {
ID string `json:"id"`
SportID string `json:"sport_id"`
Time string `json:"time"`
TimeStatus string `json:"time_status"`
League struct {
ID string `json:"id"`
Name string `json:"name"`
CC string `json:"cc"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"home"`
Away struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"away"`
SS string `json:"ss"`
Scores struct {
FirstQuarter Score `json:"1"`
SecondQuarter Score `json:"2"`
ThirdQuarter Score `json:"3"`
FourthQuarter Score `json:"4"`
Overtime Score `json:"5"`
TotalScore Score `json:"7"`
} `json:"scores"`
Stats struct {
FirstDowns []string `json:"first_downs"`
TotalYards []string `json:"total_yards"`
PassingYards []string `json:"passing_yards"`
RushingYards []string `json:"rushing_yards"`
Turnovers []string `json:"turnovers"`
TimeOfPossession []string `json:"time_of_possession"`
ThirdDownEfficiency []string `json:"third_down_efficiency"`
FourthDownEfficiency []string `json:"fourth_down_efficiency"`
} `json:"stats"`
Extra struct {
HomePos string `json:"home_pos"`
AwayPos string `json:"away_pos"`
StadiumData map[string]string `json:"stadium_data"`
Round string `json:"round"`
} `json:"extra"`
Events []map[string]string `json:"events"`
HasLineup int `json:"has_lineup"`
ConfirmedAt string `json:"confirmed_at"`
Bet365ID string `json:"bet365_id"`
}
// RugbyResultResponse represents the structure for Rugby game results
type RugbyResultResponse struct {
ID string `json:"id"`
SportID string `json:"sport_id"`
Time string `json:"time"`
TimeStatus string `json:"time_status"`
League struct {
ID string `json:"id"`
Name string `json:"name"`
CC string `json:"cc"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"home"`
Away struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"away"`
SS string `json:"ss"`
Scores struct {
FirstHalf Score `json:"1"`
SecondHalf Score `json:"2"`
TotalScore Score `json:"7"`
} `json:"scores"`
Stats struct {
Tries []string `json:"tries"`
Conversions []string `json:"conversions"`
Penalties []string `json:"penalties"`
DropGoals []string `json:"drop_goals"`
Possession []string `json:"possession"`
Territory []string `json:"territory"`
Lineouts []string `json:"lineouts"`
Scrums []string `json:"scrums"`
PenaltiesConceded []string `json:"penalties_conceded"`
} `json:"stats"`
Extra struct {
HomePos string `json:"home_pos"`
AwayPos string `json:"away_pos"`
StadiumData map[string]string `json:"stadium_data"`
Round string `json:"round"`
} `json:"extra"`
Events []map[string]string `json:"events"`
HasLineup int `json:"has_lineup"`
ConfirmedAt string `json:"confirmed_at"`
Bet365ID string `json:"bet365_id"`
}
// BaseballResultResponse represents the structure for Baseball game results
type BaseballResultResponse struct {
ID string `json:"id"`
SportID string `json:"sport_id"`
Time string `json:"time"`
TimeStatus string `json:"time_status"`
League struct {
ID string `json:"id"`
Name string `json:"name"`
CC string `json:"cc"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"home"`
Away struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"away"`
SS string `json:"ss"`
Scores struct {
FirstInning Score `json:"1"`
SecondInning Score `json:"2"`
ThirdInning Score `json:"3"`
FourthInning Score `json:"4"`
FifthInning Score `json:"5"`
SixthInning Score `json:"6"`
SeventhInning Score `json:"7"`
EighthInning Score `json:"8"`
NinthInning Score `json:"9"`
ExtraInnings Score `json:"10"`
TotalScore Score `json:"11"`
} `json:"scores"`
Stats struct {
Hits []string `json:"hits"`
Errors []string `json:"errors"`
LeftOnBase []string `json:"left_on_base"`
Strikeouts []string `json:"strikeouts"`
Walks []string `json:"walks"`
HomeRuns []string `json:"home_runs"`
TotalBases []string `json:"total_bases"`
BattingAverage []string `json:"batting_average"`
} `json:"stats"`
Extra struct {
HomePos string `json:"home_pos"`
AwayPos string `json:"away_pos"`
StadiumData map[string]string `json:"stadium_data"`
Round string `json:"round"`
} `json:"extra"`
Events []map[string]string `json:"events"`
HasLineup int `json:"has_lineup"`
ConfirmedAt string `json:"confirmed_at"`
Bet365ID string `json:"bet365_id"`
}

View File

@ -171,32 +171,28 @@ type AmericanFootballMarket int64
const ( const (
// Main // Main
AMERICAN_FOOTBALL_MONEY_LINE AmericanFootballMarket = 170001 AMERICAN_FOOTBALL_GAME_LINES AmericanFootballMarket = 1441
AMERICAN_FOOTBALL_SPREAD AmericanFootballMarket = 170002
AMERICAN_FOOTBALL_TOTAL_POINTS AmericanFootballMarket = 170003
) )
type RugbyMarket int64 type RugbyLeagueMarket int64
const ( const (
// Main // Main
RUGBY_MONEY_LINE RugbyMarket = 180001 RUGBY_L_GAME_BETTING_2_WAY RugbyLeagueMarket = 190006
RUGBY_SPREAD RugbyMarket = 180002 )
RUGBY_TOTAL_POINTS RugbyMarket = 180003
RUGBY_HANDICAP RugbyMarket = 180004 type RugbyUnionMarket int64
RUGBY_FIRST_HALF RugbyMarket = 180005
RUGBY_SECOND_HALF RugbyMarket = 180006 const (
// Main
RUGBY_U_GAME_BETTING_2_WAY RugbyLeagueMarket = 80007
) )
type BaseballMarket int64 type BaseballMarket int64
const ( const (
// Main // Main
BASEBALL_MONEY_LINE BaseballMarket = 190001 BASEBALL_GAME_LINES BaseballMarket = 1096
BASEBALL_SPREAD BaseballMarket = 190002
BASEBALL_TOTAL_RUNS BaseballMarket = 190003
BASEBALL_FIRST_INNING BaseballMarket = 190004
BASEBALL_FIRST_5_INNINGS BaseballMarket = 190005
) )
// TODO: Move this into the database so that it can be modified dynamically // TODO: Move this into the database so that it can be modified dynamically
@ -229,7 +225,7 @@ var SupportedMarkets = map[int64]bool{
int64(BASKETBALL_RESULT_AND_BOTH_TEAMS_TO_SCORE_X_POINTS): true, int64(BASKETBALL_RESULT_AND_BOTH_TEAMS_TO_SCORE_X_POINTS): true,
int64(BASKETBALL_DOUBLE_RESULT): true, int64(BASKETBALL_DOUBLE_RESULT): true,
int64(BASKETBALL_MATCH_RESULT_AND_TOTAL): true, int64(BASKETBALL_MATCH_RESULT_AND_TOTAL): true,
int64(BASKETBALL_MATCH_HANDICAP_AND_TOTAL): false, int64(BASKETBALL_MATCH_HANDICAP_AND_TOTAL): true,
int64(BASKETBALL_GAME_TOTAL_ODD_EVEN): true, int64(BASKETBALL_GAME_TOTAL_ODD_EVEN): true,
int64(BASKETBALL_TEAM_TOTALS): true, int64(BASKETBALL_TEAM_TOTALS): true,
int64(BASKETBALL_TEAM_TOTAL_ODD_EVEN): true, int64(BASKETBALL_TEAM_TOTAL_ODD_EVEN): true,
@ -250,7 +246,7 @@ var SupportedMarkets = map[int64]bool{
int64(BASKETBALL_FIRST_HALF_TEAM_TO_SCORE_X_POINTS): false, int64(BASKETBALL_FIRST_HALF_TEAM_TO_SCORE_X_POINTS): false,
int64(BASKETBALL_FIRST_QUARTER): true, int64(BASKETBALL_FIRST_QUARTER): true,
int64(BASKETBALL_FIRST_QUARTER_HANDICAP_AND_TOTAL): false, int64(BASKETBALL_FIRST_QUARTER_HANDICAP_AND_TOTAL): true,
int64(BASKETBALL_FIRST_QUARTER_DOUBLE_CHANCE): true, int64(BASKETBALL_FIRST_QUARTER_DOUBLE_CHANCE): true,
int64(BASKETBALL_FIRST_QUARTER_TEAM_TOTALS): true, int64(BASKETBALL_FIRST_QUARTER_TEAM_TOTALS): true,
int64(BASKETBALL_FIRST_QUARTER_WINNING_MARGIN): false, int64(BASKETBALL_FIRST_QUARTER_WINNING_MARGIN): false,
@ -259,7 +255,7 @@ var SupportedMarkets = map[int64]bool{
int64(BASKETBALL_TEAM_WITH_HIGHEST_SCORING_QUARTER): true, int64(BASKETBALL_TEAM_WITH_HIGHEST_SCORING_QUARTER): true,
int64(BASKETBALL_QUARTER_CORRECT_SCORE): false, int64(BASKETBALL_QUARTER_CORRECT_SCORE): false,
int64(BASKETBALL_FIRST_QUARTER_3_WAY_LINES): false, int64(BASKETBALL_FIRST_QUARTER_3_WAY_LINES): false,
int64(BASKETBALL_FIRST_QUARTER_RESULT_AND_TOTAL): false, int64(BASKETBALL_FIRST_QUARTER_RESULT_AND_TOTAL): true,
int64(BASKETBALL_FIRST_QUARTER_RACE_TO_POINTS): false, int64(BASKETBALL_FIRST_QUARTER_RACE_TO_POINTS): false,
int64(BASKETBALL_FIRST_QUARTER_BOTH_TEAMS_TO_SCORE_X_POINTS): false, int64(BASKETBALL_FIRST_QUARTER_BOTH_TEAMS_TO_SCORE_X_POINTS): false,
int64(BASKETBALL_FIRST_QUARTER_TEAM_TO_SCORE_X_POINTS): false, int64(BASKETBALL_FIRST_QUARTER_TEAM_TO_SCORE_X_POINTS): false,
@ -325,22 +321,14 @@ var SupportedMarkets = map[int64]bool{
int64(FUTSAL_RACE_TO_GOALS): false, int64(FUTSAL_RACE_TO_GOALS): false,
// American Football Markets // American Football Markets
int64(AMERICAN_FOOTBALL_MONEY_LINE): true, int64(AMERICAN_FOOTBALL_GAME_LINES): true,
int64(AMERICAN_FOOTBALL_SPREAD): true,
int64(AMERICAN_FOOTBALL_TOTAL_POINTS): true,
// Rugby Markets // Rugby League Markets
int64(RUGBY_MONEY_LINE): true, int64(RUGBY_L_GAME_BETTING_2_WAY): true,
int64(RUGBY_SPREAD): true,
int64(RUGBY_TOTAL_POINTS): true, // Ruby Union Markets
int64(RUGBY_HANDICAP): true, int64(RUGBY_U_GAME_BETTING_2_WAY): true,
int64(RUGBY_FIRST_HALF): true,
int64(RUGBY_SECOND_HALF): true,
// Baseball Markets // Baseball Markets
int64(BASEBALL_MONEY_LINE): true, int64(BASEBALL_GAME_LINES): true,
int64(BASEBALL_SPREAD): true,
int64(BASEBALL_TOTAL_RUNS): true,
int64(BASEBALL_FIRST_INNING): true,
int64(BASEBALL_FIRST_5_INNINGS): true,
} }

View File

@ -1,290 +1,125 @@
package domain package domain
import ( // import (
"encoding/json" // "encoding/json"
"strconv" // "strconv"
"strings" // "strings"
) // )
// NFLResultResponse represents the structure for NFL game results // // ParseNFLResult parses NFL result from raw JSON data
type NFLResultResponse struct { // func ParseNFLResult(data json.RawMessage) (*NFLResultResponse, error) {
ID string `json:"id"` // var result NFLResultResponse
SportID string `json:"sport_id"` // if err := json.Unmarshal(data, &result); err != nil {
Time string `json:"time"` // return nil, err
TimeStatus string `json:"time_status"` // }
League struct { // return &result, nil
ID string `json:"id"` // }
Name string `json:"name"`
CC string `json:"cc"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"home"`
Away struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"away"`
SS string `json:"ss"`
Scores struct {
FirstQuarter Score `json:"1"`
SecondQuarter Score `json:"2"`
ThirdQuarter Score `json:"3"`
FourthQuarter Score `json:"4"`
Overtime Score `json:"5"`
TotalScore Score `json:"7"`
} `json:"scores"`
Stats struct {
FirstDowns []string `json:"first_downs"`
TotalYards []string `json:"total_yards"`
PassingYards []string `json:"passing_yards"`
RushingYards []string `json:"rushing_yards"`
Turnovers []string `json:"turnovers"`
TimeOfPossession []string `json:"time_of_possession"`
ThirdDownEfficiency []string `json:"third_down_efficiency"`
FourthDownEfficiency []string `json:"fourth_down_efficiency"`
} `json:"stats"`
Extra struct {
HomePos string `json:"home_pos"`
AwayPos string `json:"away_pos"`
StadiumData map[string]string `json:"stadium_data"`
Round string `json:"round"`
} `json:"extra"`
Events []map[string]string `json:"events"`
HasLineup int `json:"has_lineup"`
ConfirmedAt string `json:"confirmed_at"`
Bet365ID string `json:"bet365_id"`
}
// RugbyResultResponse represents the structure for Rugby game results // // ParseRugbyResult parses Rugby result from raw JSON data
type RugbyResultResponse struct { // func ParseRugbyResult(data json.RawMessage) (*RugbyResultResponse, error) {
ID string `json:"id"` // var result RugbyResultResponse
SportID string `json:"sport_id"` // if err := json.Unmarshal(data, &result); err != nil {
Time string `json:"time"` // return nil, err
TimeStatus string `json:"time_status"` // }
League struct { // return &result, nil
ID string `json:"id"` // }
Name string `json:"name"`
CC string `json:"cc"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"home"`
Away struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"away"`
SS string `json:"ss"`
Scores struct {
FirstHalf Score `json:"1"`
SecondHalf Score `json:"2"`
TotalScore Score `json:"7"`
} `json:"scores"`
Stats struct {
Tries []string `json:"tries"`
Conversions []string `json:"conversions"`
Penalties []string `json:"penalties"`
DropGoals []string `json:"drop_goals"`
Possession []string `json:"possession"`
Territory []string `json:"territory"`
Lineouts []string `json:"lineouts"`
Scrums []string `json:"scrums"`
PenaltiesConceded []string `json:"penalties_conceded"`
} `json:"stats"`
Extra struct {
HomePos string `json:"home_pos"`
AwayPos string `json:"away_pos"`
StadiumData map[string]string `json:"stadium_data"`
Round string `json:"round"`
} `json:"extra"`
Events []map[string]string `json:"events"`
HasLineup int `json:"has_lineup"`
ConfirmedAt string `json:"confirmed_at"`
Bet365ID string `json:"bet365_id"`
}
// BaseballResultResponse represents the structure for Baseball game results // // ParseRugbyUnionResult parses Rugby Union result from raw JSON data
type BaseballResultResponse struct { // func ParseRugbyUnionResult(data json.RawMessage) (*RugbyResultResponse, error) {
ID string `json:"id"` // return ParseRugbyResult(data)
SportID string `json:"sport_id"` // }
Time string `json:"time"`
TimeStatus string `json:"time_status"`
League struct {
ID string `json:"id"`
Name string `json:"name"`
CC string `json:"cc"`
} `json:"league"`
Home struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"home"`
Away struct {
ID string `json:"id"`
Name string `json:"name"`
ImageID string `json:"image_id"`
CC string `json:"cc"`
} `json:"away"`
SS string `json:"ss"`
Scores struct {
FirstInning Score `json:"1"`
SecondInning Score `json:"2"`
ThirdInning Score `json:"3"`
FourthInning Score `json:"4"`
FifthInning Score `json:"5"`
SixthInning Score `json:"6"`
SeventhInning Score `json:"7"`
EighthInning Score `json:"8"`
NinthInning Score `json:"9"`
ExtraInnings Score `json:"10"`
TotalScore Score `json:"11"`
} `json:"scores"`
Stats struct {
Hits []string `json:"hits"`
Errors []string `json:"errors"`
LeftOnBase []string `json:"left_on_base"`
Strikeouts []string `json:"strikeouts"`
Walks []string `json:"walks"`
HomeRuns []string `json:"home_runs"`
TotalBases []string `json:"total_bases"`
BattingAverage []string `json:"batting_average"`
} `json:"stats"`
Extra struct {
HomePos string `json:"home_pos"`
AwayPos string `json:"away_pos"`
StadiumData map[string]string `json:"stadium_data"`
Round string `json:"round"`
} `json:"extra"`
Events []map[string]string `json:"events"`
HasLineup int `json:"has_lineup"`
ConfirmedAt string `json:"confirmed_at"`
Bet365ID string `json:"bet365_id"`
}
// ParseNFLResult parses NFL result from raw JSON data // // ParseRugbyLeagueResult parses Rugby League result from raw JSON data
func ParseNFLResult(data json.RawMessage) (*NFLResultResponse, error) { // func ParseRugbyLeagueResult(data json.RawMessage) (*RugbyResultResponse, error) {
var result NFLResultResponse // return ParseRugbyResult(data)
if err := json.Unmarshal(data, &result); err != nil { // }
return nil, err
}
return &result, nil
}
// ParseRugbyResult parses Rugby result from raw JSON data // // ParseBaseballResult parses Baseball result from raw JSON data
func ParseRugbyResult(data json.RawMessage) (*RugbyResultResponse, error) { // func ParseBaseballResult(data json.RawMessage) (*BaseballResultResponse, error) {
var result RugbyResultResponse // var result BaseballResultResponse
if err := json.Unmarshal(data, &result); err != nil { // if err := json.Unmarshal(data, &result); err != nil {
return nil, err // return nil, err
} // }
return &result, nil // return &result, nil
} // }
// ParseRugbyUnionResult parses Rugby Union result from raw JSON data // // GetNFLWinner determines the winner of an NFL game
func ParseRugbyUnionResult(data json.RawMessage) (*RugbyResultResponse, error) { // func GetNFLWinner(result *NFLResultResponse) (string, error) {
return ParseRugbyResult(data) // homeScore, err := strconv.Atoi(result.Scores.TotalScore.Home)
} // if err != nil {
// return "", err
// }
// awayScore, err := strconv.Atoi(result.Scores.TotalScore.Away)
// if err != nil {
// return "", err
// }
// ParseRugbyLeagueResult parses Rugby League result from raw JSON data // if homeScore > awayScore {
func ParseRugbyLeagueResult(data json.RawMessage) (*RugbyResultResponse, error) { // return result.Home.Name, nil
return ParseRugbyResult(data) // } else if awayScore > homeScore {
} // return result.Away.Name, nil
// }
// return "Draw", nil
// }
// ParseBaseballResult parses Baseball result from raw JSON data // // GetRugbyWinner determines the winner of a Rugby game
func ParseBaseballResult(data json.RawMessage) (*BaseballResultResponse, error) { // func GetRugbyWinner(result *RugbyResultResponse) (string, error) {
var result BaseballResultResponse // homeScore, err := strconv.Atoi(result.Scores.TotalScore.Home)
if err := json.Unmarshal(data, &result); err != nil { // if err != nil {
return nil, err // return "", err
} // }
return &result, nil // awayScore, err := strconv.Atoi(result.Scores.TotalScore.Away)
} // if err != nil {
// return "", err
// }
// GetNFLWinner determines the winner of an NFL game // if homeScore > awayScore {
func GetNFLWinner(result *NFLResultResponse) (string, error) { // return result.Home.Name, nil
homeScore, err := strconv.Atoi(result.Scores.TotalScore.Home) // } else if awayScore > homeScore {
if err != nil { // return result.Away.Name, nil
return "", err // }
} // return "Draw", nil
awayScore, err := strconv.Atoi(result.Scores.TotalScore.Away) // }
if err != nil {
return "", err
}
if homeScore > awayScore { // // GetBaseballWinner determines the winner of a Baseball game
return result.Home.Name, nil // func GetBaseballWinner(result *BaseballResultResponse) (string, error) {
} else if awayScore > homeScore { // homeScore, err := strconv.Atoi(result.Scores.TotalScore.Home)
return result.Away.Name, nil // if err != nil {
} // return "", err
return "Draw", nil // }
} // awayScore, err := strconv.Atoi(result.Scores.TotalScore.Away)
// if err != nil {
// return "", err
// }
// GetRugbyWinner determines the winner of a Rugby game // if homeScore > awayScore {
func GetRugbyWinner(result *RugbyResultResponse) (string, error) { // return result.Home.Name, nil
homeScore, err := strconv.Atoi(result.Scores.TotalScore.Home) // } else if awayScore > homeScore {
if err != nil { // return result.Away.Name, nil
return "", err // }
} // return "Draw", nil
awayScore, err := strconv.Atoi(result.Scores.TotalScore.Away) // }
if err != nil {
return "", err
}
if homeScore > awayScore { // // FormatNFLScore formats the NFL score in a readable format
return result.Home.Name, nil // func FormatNFLScore(result *NFLResultResponse) string {
} else if awayScore > homeScore { // return strings.Join([]string{
return result.Away.Name, nil // result.Home.Name + " " + result.Scores.TotalScore.Home,
} // result.Away.Name + " " + result.Scores.TotalScore.Away,
return "Draw", nil // }, " - ")
} // }
// GetBaseballWinner determines the winner of a Baseball game // // FormatRugbyScore formats the Rugby score in a readable format
func GetBaseballWinner(result *BaseballResultResponse) (string, error) { // func FormatRugbyScore(result *RugbyResultResponse) string {
homeScore, err := strconv.Atoi(result.Scores.TotalScore.Home) // return strings.Join([]string{
if err != nil { // result.Home.Name + " " + result.Scores.TotalScore.Home,
return "", err // result.Away.Name + " " + result.Scores.TotalScore.Away,
} // }, " - ")
awayScore, err := strconv.Atoi(result.Scores.TotalScore.Away) // }
if err != nil {
return "", err
}
if homeScore > awayScore { // // FormatBaseballScore formats the Baseball score in a readable format
return result.Home.Name, nil // func FormatBaseballScore(result *BaseballResultResponse) string {
} else if awayScore > homeScore { // return strings.Join([]string{
return result.Away.Name, nil // result.Home.Name + " " + result.Scores.TotalScore.Home,
} // result.Away.Name + " " + result.Scores.TotalScore.Away,
return "Draw", nil // }, " - ")
} // }
// FormatNFLScore formats the NFL score in a readable format
func FormatNFLScore(result *NFLResultResponse) string {
return strings.Join([]string{
result.Home.Name + " " + result.Scores.TotalScore.Home,
result.Away.Name + " " + result.Scores.TotalScore.Away,
}, " - ")
}
// FormatRugbyScore formats the Rugby score in a readable format
func FormatRugbyScore(result *RugbyResultResponse) string {
return strings.Join([]string{
result.Home.Name + " " + result.Scores.TotalScore.Home,
result.Away.Name + " " + result.Scores.TotalScore.Away,
}, " - ")
}
// FormatBaseballScore formats the Baseball score in a readable format
func FormatBaseballScore(result *BaseballResultResponse) string {
return strings.Join([]string{
result.Home.Name + " " + result.Scores.TotalScore.Home,
result.Away.Name + " " + result.Scores.TotalScore.Away,
}, " - ")
}

View File

@ -7,7 +7,6 @@ import (
"io" "io"
"log" "log"
"net/http" "net/http"
"slices"
"strconv" "strconv"
"sync" "sync"
"time" "time"
@ -189,8 +188,8 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
source string source string
}{ }{
{"https://api.b365api.com/v1/bet365/upcoming?sport_id=%d&token=%s&page=%d", "bet365"}, {"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"}, // {"https://api.b365api.com/v1/betfair/sb/upcoming?sport_id=%d&token=%s&page=%d", "betfair"},
{"https://api.b365api.com/v1/1xbet/upcoming?sport_id=%d&token=%s&page=%d", "1xbet"}, // {"https://api.b365api.com/v1/1xbet/upcoming?sport_id=%d&token=%s&page=%d", "1xbet"},
} }
for _, url := range urls { for _, url := range urls {
@ -207,16 +206,23 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
} }
func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, source string) { func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, source string) {
sportIDs := []int{1, 18, 17} sportIDs := []int{1, 18, 17, 3, 83, 15, 12, 19, 8, 16, 91}
// TODO: Add the league skipping again when we have dynamic leagues
// b, err := os.OpenFile("logs/skipped_leagues.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
// if err != nil {
// log.Printf("❌ Failed to open leagues file %v", err)
// return
// }
for _, sportID := range sportIDs {
var totalPages int = 1 var totalPages int = 1
var page int = 0 var page int = 0
var limit int = 100 var limit int = 100
var count int = 0 var count int = 0
for _, sportID := range sportIDs { log.Printf("Sport ID %d", sportID)
for page <= totalPages { for page <= totalPages {
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("https://api.b365api.com/v1/bet365/upcoming?sport_id=%d&token=%s&page=%d", sportID, s.token, page)
log.Printf("📡 Fetching data for event data page %d", page) log.Printf("📡 Fetching data for sport %d at page %d", sportID, 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)
@ -240,17 +246,21 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, sour
// continue // continue
// } // }
leagueID, err := strconv.ParseInt(ev.League.ID, 10, 64) // leagueID, err := strconv.ParseInt(ev.League.ID, 10, 64)
if err != nil { // if err != nil {
log.Printf("❌ Invalid league id, leagueID %v", ev.League.ID) // log.Printf("❌ Invalid league id, leagueID %v", ev.League.ID)
continue // continue
} // }
if !slices.Contains(domain.SupportedLeagues, leagueID) { // if !slices.Contains(domain.SupportedLeagues, leagueID) {
// fmt.Printf("⚠️ Skipping league %s (%d) as it is not supported\n", ev.League.Name, leagueID) // // fmt.Printf("⚠️ Skipping league %s (%d) as it is not supported\n", ev.League.Name, leagueID)
skippedLeague = append(skippedLeague, ev.League.Name) // _, err = fmt.Fprintf(b, "Skipped league %s (%d) in sport %d\n", ev.League.Name, leagueID, sportID)
continue // if err != nil {
} // fmt.Printf(" Error while logging skipped league")
// }
// skippedLeague = append(skippedLeague, ev.League.Name)
// continue
// }
event := domain.UpcomingEvent{ event := domain.UpcomingEvent{
ID: ev.ID, ID: ev.ID,
@ -282,7 +292,7 @@ func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, sour
} }
log.Printf("⚠️ Skipped leagues %v", len(skippedLeague)) log.Printf("⚠️ Skipped leagues %v", len(skippedLeague))
// log.Printf("⚠️ Total pages %v", data.Pager.Total) log.Printf("⚠️ Total pages %v", data.Pager.Total/data.Pager.PerPage)
totalPages = data.Pager.Total / data.Pager.PerPage totalPages = data.Pager.Total / data.Pager.PerPage
if count >= limit { if count >= limit {

View File

@ -98,6 +98,46 @@ func (s *ServiceImpl) FetchNonLiveOdds(ctx context.Context) error {
s.logger.Error("Error while inserting ice hockey odd") s.logger.Error("Error while inserting ice hockey odd")
errs = append(errs, err) errs = append(errs, err)
} }
case domain.CRICKET:
if err := s.parseCricket(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting cricket odd")
errs = append(errs, err)
}
case domain.VOLLEYBALL:
if err := s.parseVolleyball(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting volleyball odd")
errs = append(errs, err)
}
case domain.DARTS:
if err := s.parseDarts(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting darts odd")
errs = append(errs, err)
}
case domain.FUTSAL:
if err := s.parseFutsal(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting futsal odd")
errs = append(errs, err)
}
case domain.AMERICAN_FOOTBALL:
if err := s.parseAmericanFootball(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting american football odd")
errs = append(errs, err)
}
case domain.RUGBY_LEAGUE:
if err := s.parseRugbyLeague(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting rugby league odd")
errs = append(errs, err)
}
case domain.RUGBY_UNION:
if err := s.parseRugbyUnion(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting rugby union odd")
errs = append(errs, err)
}
case domain.BASEBALL:
if err := s.parseBaseball(ctx, oddsData.Results[0]); err != nil {
s.logger.Error("Error while inserting baseball odd")
errs = append(errs, err)
}
} }
// result := oddsData.Results[0] // result := oddsData.Results[0]
@ -223,6 +263,332 @@ func (s *ServiceImpl) parseIceHockey(ctx context.Context, res json.RawMessage) e
return nil return nil
} }
func (s *ServiceImpl) parseCricket(ctx context.Context, res json.RawMessage) error {
var cricketRes domain.CricketOddsResponse
if err := json.Unmarshal(res, &cricketRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if cricketRes.EventID == "" && cricketRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"1st_over": cricketRes.Main,
"innings_1": cricketRes.First_Innings,
"main": cricketRes.Main,
"match": cricketRes.Match,
"player": cricketRes.Player,
"team": cricketRes.Team,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, cricketRes.EventID, cricketRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
for _, section := range cricketRes.Others {
if err := s.storeSection(ctx, cricketRes.EventID, cricketRes.FI, "others", section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) parseVolleyball(ctx context.Context, res json.RawMessage) error {
var volleyballRes domain.VolleyballOddsResponse
if err := json.Unmarshal(res, &volleyballRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if volleyballRes.EventID == "" && volleyballRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"main": volleyballRes.Main,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, volleyballRes.EventID, volleyballRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
for _, section := range volleyballRes.Others {
if err := s.storeSection(ctx, volleyballRes.EventID, volleyballRes.FI, "others", section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) parseDarts(ctx context.Context, res json.RawMessage) error {
var dartsRes domain.DartsOddsResponse
if err := json.Unmarshal(res, &dartsRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if dartsRes.EventID == "" && dartsRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"180s": dartsRes.OneEightys,
"extra": dartsRes.Extra,
"leg": dartsRes.Leg,
"main": dartsRes.Main,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, dartsRes.EventID, dartsRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
for _, section := range dartsRes.Others {
if err := s.storeSection(ctx, dartsRes.EventID, dartsRes.FI, "others", section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) parseFutsal(ctx context.Context, res json.RawMessage) error {
var futsalRes domain.FutsalOddsResponse
if err := json.Unmarshal(res, &futsalRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if futsalRes.EventID == "" && futsalRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"main": futsalRes.Main,
"score": futsalRes.Score,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, futsalRes.EventID, futsalRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
for _, section := range futsalRes.Others {
if err := s.storeSection(ctx, futsalRes.EventID, futsalRes.FI, "others", section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) parseAmericanFootball(ctx context.Context, res json.RawMessage) error {
var americanFootballRes domain.AmericanFootballOddsResponse
if err := json.Unmarshal(res, &americanFootballRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if americanFootballRes.EventID == "" && americanFootballRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"half_props": americanFootballRes.HalfProps,
"main": americanFootballRes.Main,
"quarter_props": americanFootballRes.QuarterProps,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, americanFootballRes.EventID, americanFootballRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
for _, section := range americanFootballRes.Others {
if err := s.storeSection(ctx, americanFootballRes.EventID, americanFootballRes.FI, "others", section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) parseRugbyLeague(ctx context.Context, res json.RawMessage) error {
var rugbyLeagueRes domain.RugbyLeagueOddsResponse
if err := json.Unmarshal(res, &rugbyLeagueRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if rugbyLeagueRes.EventID == "" && rugbyLeagueRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"10minute": rugbyLeagueRes.TenMinute,
"main": rugbyLeagueRes.Main,
"main_2": rugbyLeagueRes.Main2,
"player": rugbyLeagueRes.Player,
"Score": rugbyLeagueRes.Score,
"Team": rugbyLeagueRes.Team,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, rugbyLeagueRes.EventID, rugbyLeagueRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
for _, section := range rugbyLeagueRes.Others {
if err := s.storeSection(ctx, rugbyLeagueRes.EventID, rugbyLeagueRes.FI, "others", section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) parseRugbyUnion(ctx context.Context, res json.RawMessage) error {
var rugbyUnionRes domain.RugbyUnionOddsResponse
if err := json.Unmarshal(res, &rugbyUnionRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if rugbyUnionRes.EventID == "" && rugbyUnionRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"main": rugbyUnionRes.Main,
"main_2": rugbyUnionRes.Main2,
"player": rugbyUnionRes.Player,
"Score": rugbyUnionRes.Score,
"Team": rugbyUnionRes.Team,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, rugbyUnionRes.EventID, rugbyUnionRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
for _, section := range rugbyUnionRes.Others {
if err := s.storeSection(ctx, rugbyUnionRes.EventID, rugbyUnionRes.FI, "others", section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) parseBaseball(ctx context.Context, res json.RawMessage) error {
var baseballRes domain.BaseballOddsResponse
if err := json.Unmarshal(res, &baseballRes); err != nil {
s.logger.Error("Failed to unmarshal ice hockey result", "error", err)
return err
}
if baseballRes.EventID == "" && baseballRes.FI == "" {
s.logger.Error("Skipping result with no valid Event ID")
return fmt.Errorf("Skipping result with no valid Event ID")
}
sections := map[string]domain.OddsSection{
"main": baseballRes.Main,
"mani_props": baseballRes.MainProps,
}
var errs []error
for oddCategory, section := range sections {
if err := s.storeSection(ctx, baseballRes.EventID, baseballRes.FI, oddCategory, section); err != nil {
s.logger.Error("Skipping result with no valid Event ID")
errs = append(errs, err)
continue
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}
return nil
}
func (s *ServiceImpl) storeSection(ctx context.Context, eventID, fi, sectionName string, section domain.OddsSection) error { func (s *ServiceImpl) storeSection(ctx context.Context, eventID, fi, sectionName string, section domain.OddsSection) error {
if len(section.Sp) == 0 { if len(section.Sp) == 0 {
return nil return nil

View File

@ -429,7 +429,7 @@ func evaluateGameLines(outcome domain.BetOutcome, score struct{ Home, Away int }
case "Money Line": case "Money Line":
return evaluateMoneyLine(outcome, score) return evaluateMoneyLine(outcome, score)
case "Spread", "Line": case "Spread", "Line", "Run Line":
// Since Spread betting is essentially the same thing // Since Spread betting is essentially the same thing
return evaluateAsianHandicap(outcome, score) return evaluateAsianHandicap(outcome, score)
case "Total": case "Total":
@ -985,36 +985,6 @@ func evaluateTiedAfterRegulation(outcome domain.BetOutcome, scores []struct{ Hom
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", outcome.OddName) return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", outcome.OddName)
} }
func evaluateRugbyOutcome(outcome domain.BetOutcome, result *domain.RugbyResultResponse) (domain.OutcomeStatus, error) {
finalScore := parseSS(result.SS)
switch outcome.MarketName {
case "Money Line":
return evaluateRugbyMoneyLine(outcome, finalScore)
case "Spread":
return evaluateRugbySpread(outcome, finalScore)
case "Total Points":
return evaluateRugbyTotalPoints(outcome, finalScore)
default:
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported rugby market: %s", outcome.MarketName)
}
}
func evaluateBaseballOutcome(outcome domain.BetOutcome, result *domain.BaseballResultResponse) (domain.OutcomeStatus, error) {
finalScore := parseSS(result.SS)
switch outcome.MarketName {
case "Money Line":
return evaluateBaseballMoneyLine(outcome, finalScore)
case "Spread":
return evaluateBaseballSpread(outcome, finalScore)
case "Total Runs":
return evaluateBaseballTotalRuns(outcome, finalScore)
default:
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported baseball market: %s", outcome.MarketName)
}
}
func evaluateVolleyballGamelines(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) { func evaluateVolleyballGamelines(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
switch outcome.OddName { switch outcome.OddName {
case "Total": case "Total":
@ -1023,3 +993,16 @@ func evaluateVolleyballGamelines(outcome domain.BetOutcome, score struct{ Home,
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid odd name: %s", outcome.OddName) return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid odd name: %s", outcome.OddName)
} }
} }
func evaluateGameBettingTwoWay(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
switch outcome.OddName {
case "Handicap":
return evaluateAsianHandicap(outcome, score)
case "Total":
return evaluateTotalOverUnder(outcome, score)
case "To Win":
return evaluateFullTimeResult(outcome, score)
default:
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid odd name: %s", outcome.OddName)
}
}

View File

@ -161,71 +161,6 @@ func (s *Service) FetchAndProcessResults(ctx context.Context) error {
return nil return nil
} }
// func (s *Service) FetchAndStoreResult(ctx context.Context, eventID string) error {
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%s", s.config.Bet365Token, eventID)
// res, err := s.client.Get(url)
// if err != nil {
// s.logger.Error("Failed to fetch result", "event_id", eventID, "error", err)
// return fmt.Errorf("failed to fetch result: %w", err)
// }
// defer res.Body.Close()
// if res.StatusCode != http.StatusOK {
// s.logger.Error("Unexpected status code", "event_id", eventID, "status_code", res.StatusCode)
// return fmt.Errorf("unexpected status code: %d", res.StatusCode)
// }
// var apiResp domain.BaseResultResponse
// if err := json.NewDecoder(res.Body).Decode(&apiResp); err != nil {
// s.logger.Error("Failed to decode result", "event_id", eventID, "error", err)
// return fmt.Errorf("failed to decode result: %w", err)
// }
// if apiResp.Success != 1 || len(apiResp.Results) == 0 {
// s.logger.Error("Invalid API response", "event_id", eventID)
// return fmt.Errorf("no result returned from API")
// }
// r := apiResp.Results[0]
// if r.TimeStatus != "3" {
// s.logger.Warn("Match not yet completed", "event_id", eventID)
// return fmt.Errorf("match not yet completed")
// }
// eventIDInt, err := strconv.ParseInt(eventID, 10, 64)
// if err != nil {
// s.logger.Error("Failed to parse event_id", "event_id", eventID, "error", err)
// return fmt.Errorf("failed to parse event_id: %w", err)
// }
// halfScore := ""
// if r.Scores.FirstHalf.Home != "" {
// halfScore = fmt.Sprintf("%s-%s", r.Scores.FirstHalf.Home, r.Scores.FirstHalf.Away)
// }
// result := domain.Result{
// EventID: eventIDInt,
// Status: domain.OUTCOME_STATUS_PENDING,
// Score: r.SS,
// FullTimeScore: r.SS,
// HalfTimeScore: halfScore,
// SS: r.SS,
// Scores: make(map[string]domain.Score),
// }
// for k, v := range map[string]domain.Score{
// "1": r.Scores.FirstHalf,
// "2": r.Scores.SecondHalf,
// } {
// result.Scores[k] = domain.Score{
// Home: v.Home,
// Away: v.Away,
// }
// }
// return s.repo.InsertResult(ctx, result)
// }
func (s *Service) fetchResult(ctx context.Context, eventID, oddID, marketID, sportID int64, outcome domain.BetOutcome) (domain.CreateResult, error) { func (s *Service) fetchResult(ctx context.Context, eventID, oddID, marketID, sportID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%d", s.config.Bet365Token, eventID) // url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%d", s.config.Bet365Token, eventID)
url := fmt.Sprintf("https://api.b365api.com/v1/event/view?token=%s&event_id=%d", s.config.Bet365Token, eventID) url := fmt.Sprintf("https://api.b365api.com/v1/event/view?token=%s&event_id=%d", s.config.Bet365Token, eventID)
@ -598,21 +533,7 @@ func (s *Service) parseNFL(resultRes json.RawMessage, eventID, oddID, marketID i
return domain.CreateResult{}, fmt.Errorf("match not yet completed") return domain.CreateResult{}, fmt.Errorf("match not yet completed")
} }
finalScore := parseSS(nflResp.SS) status, err := s.evaluateNFLOutcome(outcome, nflResp)
var status domain.OutcomeStatus
var err error
switch outcome.MarketName {
case "Money Line":
status, err = evaluateNFLMoneyLine(outcome, finalScore)
case "Spread":
status, err = evaluateNFLSpread(outcome, finalScore)
case "Total Points":
status, err = evaluateNFLTotalPoints(outcome, finalScore)
default:
return domain.CreateResult{}, fmt.Errorf("unsupported market: %s", outcome.MarketName)
}
if err != nil { if err != nil {
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err) s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
@ -639,7 +560,7 @@ func (s *Service) parseRugbyUnion(resultRes json.RawMessage, eventID, oddID, mar
s.logger.Warn("Match not yet completed", "event_id", eventID) s.logger.Warn("Match not yet completed", "event_id", eventID)
return domain.CreateResult{}, fmt.Errorf("match not yet completed") return domain.CreateResult{}, fmt.Errorf("match not yet completed")
} }
status, err := evaluateRugbyOutcome(outcome, &rugbyResp) status, err := s.evaluateRugbyOutcome(outcome, rugbyResp)
if err != nil { if err != nil {
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err) s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
return domain.CreateResult{}, err return domain.CreateResult{}, err
@ -664,7 +585,7 @@ func (s *Service) parseRugbyLeague(resultRes json.RawMessage, eventID, oddID, ma
s.logger.Warn("Match not yet completed", "event_id", eventID) s.logger.Warn("Match not yet completed", "event_id", eventID)
return domain.CreateResult{}, fmt.Errorf("match not yet completed") return domain.CreateResult{}, fmt.Errorf("match not yet completed")
} }
status, err := evaluateRugbyOutcome(outcome, &rugbyResp) status, err := s.evaluateRugbyOutcome(outcome, rugbyResp)
if err != nil { if err != nil {
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err) s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
return domain.CreateResult{}, err return domain.CreateResult{}, err
@ -689,7 +610,7 @@ func (s *Service) parseBaseball(resultRes json.RawMessage, eventID, oddID, marke
s.logger.Warn("Match not yet completed", "event_id", eventID) s.logger.Warn("Match not yet completed", "event_id", eventID)
return domain.CreateResult{}, fmt.Errorf("match not yet completed") return domain.CreateResult{}, fmt.Errorf("match not yet completed")
} }
status, err := evaluateBaseballOutcome(outcome, &baseballResp) status, err := s.evaluateBaseballOutcome(outcome, baseballResp)
if err != nil { if err != nil {
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err) s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
return domain.CreateResult{}, err return domain.CreateResult{}, err
@ -986,21 +907,51 @@ func (s *Service) evaluateFutsalOutcome(outcome domain.BetOutcome, res domain.Fu
return domain.OUTCOME_STATUS_PENDING, nil return domain.OUTCOME_STATUS_PENDING, nil
} }
func (s *Service) evaluateNFLOutcome(outcome domain.BetOutcome, finalScore struct{ Home, Away int }) (domain.OutcomeStatus, error) { func (s *Service) evaluateNFLOutcome(outcome domain.BetOutcome, res domain.NFLResultResponse) (domain.OutcomeStatus, error) {
if !domain.SupportedMarkets[outcome.MarketID] { if !domain.SupportedMarkets[outcome.MarketID] {
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName) s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName) return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
} }
finalScore := parseSS(res.SS)
switch outcome.MarketID { switch outcome.MarketID {
case int64(domain.AMERICAN_FOOTBALL_MONEY_LINE): case int64(domain.AMERICAN_FOOTBALL_GAME_LINES):
return evaluateNFLMoneyLine(outcome, finalScore) return evaluateGameLines(outcome, finalScore)
case int64(domain.AMERICAN_FOOTBALL_SPREAD):
return evaluateNFLSpread(outcome, finalScore)
case int64(domain.AMERICAN_FOOTBALL_TOTAL_POINTS):
return evaluateNFLTotalPoints(outcome, finalScore)
default: default:
s.logger.Warn("Market type not implemented", "market_name", outcome.MarketName) s.logger.Warn("Market type not implemented", "market_name", outcome.MarketName)
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("market type not implemented: %s", outcome.MarketName) return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("market type not implemented: %s", outcome.MarketName)
} }
} }
func (s *Service) evaluateRugbyOutcome(outcome domain.BetOutcome, result domain.RugbyResultResponse) (domain.OutcomeStatus, error) {
if !domain.SupportedMarkets[outcome.MarketID] {
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
}
finalScore := parseSS(result.SS)
switch outcome.MarketID {
case int64(domain.RUGBY_L_GAME_BETTING_2_WAY):
return evaluateGameBettingTwoWay(outcome, finalScore)
default:
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported rugby market: %s", outcome.MarketName)
}
}
func (s *Service) evaluateBaseballOutcome(outcome domain.BetOutcome, res domain.BaseballResultResponse) (domain.OutcomeStatus, error) {
if !domain.SupportedMarkets[outcome.MarketID] {
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
}
finalScore := parseSS(res.SS)
switch outcome.MarketID {
case int64(domain.BASEBALL_GAME_LINES):
return evaluateGameLines(outcome, finalScore)
default:
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported baseball market: %s", outcome.MarketName)
}
}

View File

@ -1,189 +1,189 @@
package services package services
import ( // import (
"encoding/json" // "encoding/json"
"fmt" // "fmt"
"time" // "time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" // "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
) // )
// ResultCheckerService handles the checking of game results // // ResultCheckerService handles the checking of game results
type ResultCheckerService struct { // type ResultCheckerService struct {
// Add any dependencies here (e.g., repositories, external APIs) // // Add any dependencies here (e.g., repositories, external APIs)
} // }
// NewResultCheckerService creates a new instance of ResultCheckerService // // NewResultCheckerService creates a new instance of ResultCheckerService
func NewResultCheckerService() *ResultCheckerService { // func NewResultCheckerService() *ResultCheckerService {
return &ResultCheckerService{} // return &ResultCheckerService{}
} // }
// CheckNFLResult checks the result of an NFL game // // CheckNFLResult checks the result of an NFL game
func (s *ResultCheckerService) CheckNFLResult(data json.RawMessage) (*domain.Result, error) { // func (s *ResultCheckerService) CheckNFLResult(data json.RawMessage) (*domain.Result, error) {
nflResult, err := domain.ParseNFLResult(data) // nflResult, err := domain.ParseNFLResult(data)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to parse NFL result: %w", err) // return nil, fmt.Errorf("failed to parse NFL result: %w", err)
} // }
winner, err := domain.GetNFLWinner(nflResult) // winner, err := domain.GetNFLWinner(nflResult)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to determine NFL winner: %w", err) // return nil, fmt.Errorf("failed to determine NFL winner: %w", err)
} // }
score := domain.FormatNFLScore(nflResult) // score := domain.FormatNFLScore(nflResult)
return &domain.Result{ // return &domain.Result{
Status: determineOutcomeStatus(winner, nflResult.Home.Name, nflResult.Away.Name), // Status: determineOutcomeStatus(winner, nflResult.Home.Name, nflResult.Away.Name),
Score: score, // Score: score,
FullTimeScore: score, // FullTimeScore: score,
SS: nflResult.SS, // SS: nflResult.SS,
Scores: map[string]domain.Score{ // Scores: map[string]domain.Score{
"1": nflResult.Scores.FirstQuarter, // "1": nflResult.Scores.FirstQuarter,
"2": nflResult.Scores.SecondQuarter, // "2": nflResult.Scores.SecondQuarter,
"3": nflResult.Scores.ThirdQuarter, // "3": nflResult.Scores.ThirdQuarter,
"4": nflResult.Scores.FourthQuarter, // "4": nflResult.Scores.FourthQuarter,
"5": nflResult.Scores.Overtime, // "5": nflResult.Scores.Overtime,
"7": nflResult.Scores.TotalScore, // "7": nflResult.Scores.TotalScore,
}, // },
CreatedAt: time.Now(), // CreatedAt: time.Now(),
UpdatedAt: time.Now(), // UpdatedAt: time.Now(),
}, nil // }, nil
} // }
// determineOutcomeStatus determines the outcome status based on the winner and teams // // determineOutcomeStatus determines the outcome status based on the winner and teams
func determineOutcomeStatus(winner, homeTeam, awayTeam string) domain.OutcomeStatus { // func determineOutcomeStatus(winner, homeTeam, awayTeam string) domain.OutcomeStatus {
if winner == "Draw" { // if winner == "Draw" {
return domain.OUTCOME_STATUS_VOID // return domain.OUTCOME_STATUS_VOID
} // }
if winner == homeTeam { // if winner == homeTeam {
return domain.OUTCOME_STATUS_WIN // return domain.OUTCOME_STATUS_WIN
} // }
if winner == awayTeam { // if winner == awayTeam {
return domain.OUTCOME_STATUS_LOSS // return domain.OUTCOME_STATUS_LOSS
} // }
return domain.OUTCOME_STATUS_PENDING // return domain.OUTCOME_STATUS_PENDING
} // }
// CheckRugbyResult checks the result of a Rugby game // // CheckRugbyResult checks the result of a Rugby game
func (s *ResultCheckerService) CheckRugbyResult(data json.RawMessage) (*domain.Result, error) { // func (s *ResultCheckerService) CheckRugbyResult(data json.RawMessage) (*domain.Result, error) {
rugbyResult, err := domain.ParseRugbyResult(data) // rugbyResult, err := domain.ParseRugbyResult(data)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to parse Rugby result: %w", err) // return nil, fmt.Errorf("failed to parse Rugby result: %w", err)
} // }
winner, err := domain.GetRugbyWinner(rugbyResult) // winner, err := domain.GetRugbyWinner(rugbyResult)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to determine Rugby winner: %w", err) // return nil, fmt.Errorf("failed to determine Rugby winner: %w", err)
} // }
score := domain.FormatRugbyScore(rugbyResult) // score := domain.FormatRugbyScore(rugbyResult)
return &domain.Result{ // return &domain.Result{
Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), // Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name),
Score: score, // Score: score,
FullTimeScore: score, // FullTimeScore: score,
SS: rugbyResult.SS, // SS: rugbyResult.SS,
Scores: map[string]domain.Score{ // Scores: map[string]domain.Score{
"1": rugbyResult.Scores.FirstHalf, // "1": rugbyResult.Scores.FirstHalf,
"2": rugbyResult.Scores.SecondHalf, // "2": rugbyResult.Scores.SecondHalf,
"7": rugbyResult.Scores.TotalScore, // "7": rugbyResult.Scores.TotalScore,
}, // },
CreatedAt: time.Now(), // CreatedAt: time.Now(),
UpdatedAt: time.Now(), // UpdatedAt: time.Now(),
}, nil // }, nil
} // }
// CheckBaseballResult checks the result of a Baseball game // // CheckBaseballResult checks the result of a Baseball game
func (s *ResultCheckerService) CheckBaseballResult(data json.RawMessage) (*domain.Result, error) { // func (s *ResultCheckerService) CheckBaseballResult(data json.RawMessage) (*domain.Result, error) {
baseballResult, err := domain.ParseBaseballResult(data) // baseballResult, err := domain.ParseBaseballResult(data)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to parse Baseball result: %w", err) // return nil, fmt.Errorf("failed to parse Baseball result: %w", err)
} // }
winner, err := domain.GetBaseballWinner(baseballResult) // winner, err := domain.GetBaseballWinner(baseballResult)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to determine Baseball winner: %w", err) // return nil, fmt.Errorf("failed to determine Baseball winner: %w", err)
} // }
score := domain.FormatBaseballScore(baseballResult) // score := domain.FormatBaseballScore(baseballResult)
return &domain.Result{ // return &domain.Result{
Status: determineOutcomeStatus(winner, baseballResult.Home.Name, baseballResult.Away.Name), // Status: determineOutcomeStatus(winner, baseballResult.Home.Name, baseballResult.Away.Name),
Score: score, // Score: score,
FullTimeScore: score, // FullTimeScore: score,
SS: baseballResult.SS, // SS: baseballResult.SS,
Scores: map[string]domain.Score{ // Scores: map[string]domain.Score{
"1": baseballResult.Scores.FirstInning, // "1": baseballResult.Scores.FirstInning,
"2": baseballResult.Scores.SecondInning, // "2": baseballResult.Scores.SecondInning,
"3": baseballResult.Scores.ThirdInning, // "3": baseballResult.Scores.ThirdInning,
"4": baseballResult.Scores.FourthInning, // "4": baseballResult.Scores.FourthInning,
"5": baseballResult.Scores.FifthInning, // "5": baseballResult.Scores.FifthInning,
"6": baseballResult.Scores.SixthInning, // "6": baseballResult.Scores.SixthInning,
"7": baseballResult.Scores.SeventhInning, // "7": baseballResult.Scores.SeventhInning,
"8": baseballResult.Scores.EighthInning, // "8": baseballResult.Scores.EighthInning,
"9": baseballResult.Scores.NinthInning, // "9": baseballResult.Scores.NinthInning,
"10": baseballResult.Scores.ExtraInnings, // "10": baseballResult.Scores.ExtraInnings,
"T": baseballResult.Scores.TotalScore, // "T": baseballResult.Scores.TotalScore,
}, // },
CreatedAt: time.Now(), // CreatedAt: time.Now(),
UpdatedAt: time.Now(), // UpdatedAt: time.Now(),
}, nil // }, nil
} // }
// CheckRugbyUnionResult checks the result of a Rugby Union game // // CheckRugbyUnionResult checks the result of a Rugby Union game
func (s *ResultCheckerService) CheckRugbyUnionResult(data json.RawMessage) (*domain.Result, error) { // func (s *ResultCheckerService) CheckRugbyUnionResult(data json.RawMessage) (*domain.Result, error) {
rugbyResult, err := domain.ParseRugbyUnionResult(data) // rugbyResult, err := domain.ParseRugbyUnionResult(data)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to parse Rugby Union result: %w", err) // return nil, fmt.Errorf("failed to parse Rugby Union result: %w", err)
} // }
winner, err := domain.GetRugbyWinner(rugbyResult) // winner, err := domain.GetRugbyWinner(rugbyResult)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to determine Rugby Union winner: %w", err) // return nil, fmt.Errorf("failed to determine Rugby Union winner: %w", err)
} // }
score := domain.FormatRugbyScore(rugbyResult) // score := domain.FormatRugbyScore(rugbyResult)
return &domain.Result{ // return &domain.Result{
Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), // Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name),
Score: score, // Score: score,
FullTimeScore: score, // FullTimeScore: score,
SS: rugbyResult.SS, // SS: rugbyResult.SS,
Scores: map[string]domain.Score{ // Scores: map[string]domain.Score{
"1": rugbyResult.Scores.FirstHalf, // "1": rugbyResult.Scores.FirstHalf,
"2": rugbyResult.Scores.SecondHalf, // "2": rugbyResult.Scores.SecondHalf,
"7": rugbyResult.Scores.TotalScore, // "7": rugbyResult.Scores.TotalScore,
}, // },
CreatedAt: time.Now(), // CreatedAt: time.Now(),
UpdatedAt: time.Now(), // UpdatedAt: time.Now(),
}, nil // }, nil
} // }
// CheckRugbyLeagueResult checks the result of a Rugby League game // // CheckRugbyLeagueResult checks the result of a Rugby League game
func (s *ResultCheckerService) CheckRugbyLeagueResult(data json.RawMessage) (*domain.Result, error) { // func (s *ResultCheckerService) CheckRugbyLeagueResult(data json.RawMessage) (*domain.Result, error) {
rugbyResult, err := domain.ParseRugbyLeagueResult(data) // rugbyResult, err := domain.ParseRugbyLeagueResult(data)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to parse Rugby League result: %w", err) // return nil, fmt.Errorf("failed to parse Rugby League result: %w", err)
} // }
winner, err := domain.GetRugbyWinner(rugbyResult) // winner, err := domain.GetRugbyWinner(rugbyResult)
if err != nil { // if err != nil {
return nil, fmt.Errorf("failed to determine Rugby League winner: %w", err) // return nil, fmt.Errorf("failed to determine Rugby League winner: %w", err)
} // }
score := domain.FormatRugbyScore(rugbyResult) // score := domain.FormatRugbyScore(rugbyResult)
return &domain.Result{ // return &domain.Result{
Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), // Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name),
Score: score, // Score: score,
FullTimeScore: score, // FullTimeScore: score,
SS: rugbyResult.SS, // SS: rugbyResult.SS,
Scores: map[string]domain.Score{ // Scores: map[string]domain.Score{
"1": rugbyResult.Scores.FirstHalf, // "1": rugbyResult.Scores.FirstHalf,
"2": rugbyResult.Scores.SecondHalf, // "2": rugbyResult.Scores.SecondHalf,
"7": rugbyResult.Scores.TotalScore, // "7": rugbyResult.Scores.TotalScore,
}, // },
CreatedAt: time.Now(), // CreatedAt: time.Now(),
UpdatedAt: time.Now(), // UpdatedAt: time.Now(),
}, nil // }, nil
} // }

View File

@ -21,22 +21,22 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
spec string spec string
task func() task func()
}{ }{
// { {
// spec: "0 0 * * * *", // Every 1 hour spec: "0 0 * * * *", // Every 1 hour
// task: func() { task: func() {
// if err := eventService.FetchUpcomingEvents(context.Background()); err != nil { if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
// log.Printf("FetchUpcomingEvents error: %v", err) log.Printf("FetchUpcomingEvents error: %v", err)
// } }
// }, },
// }, },
// { {
// spec: "0 */15 * * * *", // Every 15 minutes spec: "0 */15 * * * *", // Every 15 minutes
// task: func() { task: func() {
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil { if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
// log.Printf("FetchNonLiveOdds error: %v", err) log.Printf("FetchNonLiveOdds error: %v", err)
// } }
// }, },
// }, },
{ {
spec: "0 */15 * * * *", // Every 15 Minutes spec: "0 */15 * * * *", // Every 15 Minutes
task: func() { task: func() {
@ -52,7 +52,7 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S
} }
for _, job := range schedule { for _, job := range schedule {
// job.task() job.task()
if _, err := c.AddFunc(job.spec, job.task); err != nil { if _, err := c.AddFunc(job.spec, job.task); err != nil {
log.Fatalf("Failed to schedule cron job: %v", err) log.Fatalf("Failed to schedule cron job: %v", err)
} }

View File

@ -82,7 +82,7 @@ func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID) rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
if err != nil { if err != nil {
h.logger.Error("failed to fetch raw odds", "error", err) // h.logger.Error("failed to fetch raw odds", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
} }

View File

@ -54,11 +54,10 @@ db-up:
.PHONY: db-down .PHONY: db-down
db-down: db-down:
@docker volume rm fortunebet-backend_postgres_data
@docker compose down @docker compose down
@docker volume rm fortunebet-backend_postgres_data
postgres: postgres:
@docker exec -it fortunebet-backend-postgres-1 psql -U root -d gh @docker exec -it fortunebet-backend-postgres-1 psql -U root -d gh
.PHONY: sqlc-gen .PHONY: sqlc-gen
sqlc-gen: sqlc-gen:
@sqlc generate @sqlc generate