From c0680537dbccf37fe97302e7d2a39c7dcae744a3 Mon Sep 17 00:00:00 2001 From: Samuel Tariku Date: Sat, 31 May 2025 20:34:10 +0300 Subject: [PATCH] fix: event and odd fetching for all sports --- internal/domain/league.go | 31 +- internal/domain/oddres.go | 73 +++++ internal/domain/resultres.go | 165 ++++++++++ internal/domain/sportmarket.go | 54 ++-- internal/domain/sports_result.go | 383 +++++++---------------- internal/services/event/service.go | 50 +-- internal/services/odds/service.go | 366 ++++++++++++++++++++++ internal/services/result/eval.go | 45 +-- internal/services/result/service.go | 131 +++----- internal/services/result_checker.go | 326 +++++++++---------- internal/web_server/cron.go | 34 +- internal/web_server/handlers/prematch.go | 2 +- makefile | 3 +- 13 files changed, 1030 insertions(+), 633 deletions(-) diff --git a/internal/domain/league.go b/internal/domain/league.go index a4a9cc2..fbe4bd0 100644 --- a/internal/domain/league.go +++ b/internal/domain/league.go @@ -14,6 +14,13 @@ var SupportedLeagues = []int64{ 10047168, // US MLS 10044469, // Ethiopian Premier 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 10042103, //France Cup @@ -22,18 +29,38 @@ var SupportedLeagues = []int64{ 10041187, //Kenya Super League 10041315, //Italian Serie A 10041391, //Netherlands Eredivisie + 10036538, //Spain Segunda + 10041058, //Denmark Superligaen + 10077480, //Women’s 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 173998768, //NBA 10041830, //NBA 10049984, //WNBA 10037165, //German Bundesliga - 10036608, //Italian Lega 1 - 10040795, //EuroLeague + 10036608, //Italian Lega 1 + 10040795, //EuroLeague + 10084178, //Kenya Premier League + 10043548, //International Women // Ice Hockey 10037477, //NHL 10037447, //AHL + 10074238, // AIHL 10069385, //IIHF World Championship + // Cricket + } diff --git a/internal/domain/oddres.go b/internal/domain/oddres.go index 48540f0..5b4a39f 100644 --- a/internal/domain/oddres.go +++ b/internal/domain/oddres.go @@ -49,3 +49,76 @@ type IceHockeyOddsResponse struct { FirstPeriod OddsSection `json:"1st_period"` 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"` +} diff --git a/internal/domain/resultres.go b/internal/domain/resultres.go index 493c0c9..7c92367 100644 --- a/internal/domain/resultres.go +++ b/internal/domain/resultres.go @@ -290,3 +290,168 @@ type FutsalResultResponse struct { ConfirmedAt string `json:"confirmed_at"` 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"` +} diff --git a/internal/domain/sportmarket.go b/internal/domain/sportmarket.go index b5b7845..11756f0 100644 --- a/internal/domain/sportmarket.go +++ b/internal/domain/sportmarket.go @@ -171,32 +171,28 @@ type AmericanFootballMarket int64 const ( // Main - AMERICAN_FOOTBALL_MONEY_LINE AmericanFootballMarket = 170001 - AMERICAN_FOOTBALL_SPREAD AmericanFootballMarket = 170002 - AMERICAN_FOOTBALL_TOTAL_POINTS AmericanFootballMarket = 170003 + AMERICAN_FOOTBALL_GAME_LINES AmericanFootballMarket = 1441 ) -type RugbyMarket int64 +type RugbyLeagueMarket int64 const ( // Main - RUGBY_MONEY_LINE RugbyMarket = 180001 - RUGBY_SPREAD RugbyMarket = 180002 - RUGBY_TOTAL_POINTS RugbyMarket = 180003 - RUGBY_HANDICAP RugbyMarket = 180004 - RUGBY_FIRST_HALF RugbyMarket = 180005 - RUGBY_SECOND_HALF RugbyMarket = 180006 + RUGBY_L_GAME_BETTING_2_WAY RugbyLeagueMarket = 190006 +) + +type RugbyUnionMarket int64 + +const ( + // Main + RUGBY_U_GAME_BETTING_2_WAY RugbyLeagueMarket = 80007 ) type BaseballMarket int64 const ( // Main - BASEBALL_MONEY_LINE BaseballMarket = 190001 - BASEBALL_SPREAD BaseballMarket = 190002 - BASEBALL_TOTAL_RUNS BaseballMarket = 190003 - BASEBALL_FIRST_INNING BaseballMarket = 190004 - BASEBALL_FIRST_5_INNINGS BaseballMarket = 190005 + BASEBALL_GAME_LINES BaseballMarket = 1096 ) // 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_DOUBLE_RESULT): 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_TEAM_TOTALS): 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_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_TEAM_TOTALS): true, 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_QUARTER_CORRECT_SCORE): 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_BOTH_TEAMS_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, // American Football Markets - int64(AMERICAN_FOOTBALL_MONEY_LINE): true, - int64(AMERICAN_FOOTBALL_SPREAD): true, - int64(AMERICAN_FOOTBALL_TOTAL_POINTS): true, + int64(AMERICAN_FOOTBALL_GAME_LINES): true, - // Rugby Markets - int64(RUGBY_MONEY_LINE): true, - int64(RUGBY_SPREAD): true, - int64(RUGBY_TOTAL_POINTS): true, - int64(RUGBY_HANDICAP): true, - int64(RUGBY_FIRST_HALF): true, - int64(RUGBY_SECOND_HALF): true, + // Rugby League Markets + int64(RUGBY_L_GAME_BETTING_2_WAY): true, + + // Ruby Union Markets + int64(RUGBY_U_GAME_BETTING_2_WAY): true, // Baseball Markets - int64(BASEBALL_MONEY_LINE): true, - int64(BASEBALL_SPREAD): true, - int64(BASEBALL_TOTAL_RUNS): true, - int64(BASEBALL_FIRST_INNING): true, - int64(BASEBALL_FIRST_5_INNINGS): true, + int64(BASEBALL_GAME_LINES): true, } diff --git a/internal/domain/sports_result.go b/internal/domain/sports_result.go index 16bceb1..c29a402 100644 --- a/internal/domain/sports_result.go +++ b/internal/domain/sports_result.go @@ -1,290 +1,125 @@ package domain -import ( - "encoding/json" - "strconv" - "strings" -) +// import ( +// "encoding/json" +// "strconv" +// "strings" +// ) -// 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"` -} +// // ParseNFLResult parses NFL result from raw JSON data +// func ParseNFLResult(data json.RawMessage) (*NFLResultResponse, error) { +// var result NFLResultResponse +// if err := json.Unmarshal(data, &result); err != nil { +// return nil, err +// } +// return &result, nil +// } -// 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"` -} +// // ParseRugbyResult parses Rugby result from raw JSON data +// func ParseRugbyResult(data json.RawMessage) (*RugbyResultResponse, error) { +// var result RugbyResultResponse +// if err := json.Unmarshal(data, &result); err != nil { +// return nil, err +// } +// return &result, nil +// } -// 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"` -} +// // ParseRugbyUnionResult parses Rugby Union result from raw JSON data +// func ParseRugbyUnionResult(data json.RawMessage) (*RugbyResultResponse, error) { +// return ParseRugbyResult(data) +// } -// ParseNFLResult parses NFL result from raw JSON data -func ParseNFLResult(data json.RawMessage) (*NFLResultResponse, error) { - var result NFLResultResponse - if err := json.Unmarshal(data, &result); err != nil { - return nil, err - } - return &result, nil -} +// // ParseRugbyLeagueResult parses Rugby League result from raw JSON data +// func ParseRugbyLeagueResult(data json.RawMessage) (*RugbyResultResponse, error) { +// return ParseRugbyResult(data) +// } -// ParseRugbyResult parses Rugby result from raw JSON data -func ParseRugbyResult(data json.RawMessage) (*RugbyResultResponse, error) { - var result RugbyResultResponse - if err := json.Unmarshal(data, &result); err != nil { - return nil, err - } - return &result, nil -} +// // ParseBaseballResult parses Baseball result from raw JSON data +// func ParseBaseballResult(data json.RawMessage) (*BaseballResultResponse, error) { +// var result BaseballResultResponse +// if err := json.Unmarshal(data, &result); err != nil { +// return nil, err +// } +// return &result, nil +// } -// ParseRugbyUnionResult parses Rugby Union result from raw JSON data -func ParseRugbyUnionResult(data json.RawMessage) (*RugbyResultResponse, error) { - return ParseRugbyResult(data) -} +// // GetNFLWinner determines the winner of an NFL game +// func GetNFLWinner(result *NFLResultResponse) (string, error) { +// 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 -func ParseRugbyLeagueResult(data json.RawMessage) (*RugbyResultResponse, error) { - return ParseRugbyResult(data) -} +// if homeScore > awayScore { +// return result.Home.Name, nil +// } else if awayScore > homeScore { +// return result.Away.Name, nil +// } +// return "Draw", nil +// } -// ParseBaseballResult parses Baseball result from raw JSON data -func ParseBaseballResult(data json.RawMessage) (*BaseballResultResponse, error) { - var result BaseballResultResponse - if err := json.Unmarshal(data, &result); err != nil { - return nil, err - } - return &result, nil -} +// // GetRugbyWinner determines the winner of a Rugby game +// func GetRugbyWinner(result *RugbyResultResponse) (string, error) { +// 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 +// } -// GetNFLWinner determines the winner of an NFL game -func GetNFLWinner(result *NFLResultResponse) (string, error) { - 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 - } +// if homeScore > awayScore { +// return result.Home.Name, nil +// } else if awayScore > homeScore { +// return result.Away.Name, nil +// } +// return "Draw", nil +// } - if homeScore > awayScore { - return result.Home.Name, nil - } else if awayScore > homeScore { - return result.Away.Name, nil - } - return "Draw", nil -} +// // GetBaseballWinner determines the winner of a Baseball game +// func GetBaseballWinner(result *BaseballResultResponse) (string, error) { +// 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 +// } -// GetRugbyWinner determines the winner of a Rugby game -func GetRugbyWinner(result *RugbyResultResponse) (string, error) { - 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 - } +// if homeScore > awayScore { +// return result.Home.Name, nil +// } else if awayScore > homeScore { +// return result.Away.Name, nil +// } +// return "Draw", nil +// } - if homeScore > awayScore { - return result.Home.Name, nil - } else if awayScore > homeScore { - return result.Away.Name, nil - } - 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, +// }, " - ") +// } -// GetBaseballWinner determines the winner of a Baseball game -func GetBaseballWinner(result *BaseballResultResponse) (string, error) { - 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 - } +// // 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, +// }, " - ") +// } - if homeScore > awayScore { - return result.Home.Name, nil - } else if awayScore > homeScore { - return result.Away.Name, nil - } - 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, - }, " - ") -} +// // 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, +// }, " - ") +// } diff --git a/internal/services/event/service.go b/internal/services/event/service.go index b24a8ec..4959b15 100644 --- a/internal/services/event/service.go +++ b/internal/services/event/service.go @@ -7,7 +7,6 @@ import ( "io" "log" "net/http" - "slices" "strconv" "sync" "time" @@ -189,8 +188,8 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error { 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"}, - {"https://api.b365api.com/v1/1xbet/upcoming?sport_id=%d&token=%s&page=%d", "1xbet"}, + // {"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"}, } 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) { - sportIDs := []int{1, 18, 17} - var totalPages int = 1 - var page int = 0 - var limit int = 100 - var count int = 0 + 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 page int = 0 + var limit int = 100 + var count int = 0 + log.Printf("Sport ID %d", sportID) for page <= totalPages { page = page + 1 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) if err != nil { 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 // } - leagueID, err := strconv.ParseInt(ev.League.ID, 10, 64) - if err != nil { - log.Printf("❌ Invalid league id, leagueID %v", ev.League.ID) - continue - } + // leagueID, err := strconv.ParseInt(ev.League.ID, 10, 64) + // if err != nil { + // log.Printf("❌ Invalid league id, leagueID %v", ev.League.ID) + // continue + // } - if !slices.Contains(domain.SupportedLeagues, leagueID) { - // fmt.Printf("⚠️ Skipping league %s (%d) as it is not supported\n", ev.League.Name, leagueID) - skippedLeague = append(skippedLeague, ev.League.Name) - continue - } + // if !slices.Contains(domain.SupportedLeagues, leagueID) { + // // fmt.Printf("⚠️ Skipping league %s (%d) as it is not supported\n", ev.League.Name, leagueID) + // _, err = fmt.Fprintf(b, "Skipped league %s (%d) in sport %d\n", ev.League.Name, leagueID, sportID) + // if err != nil { + // fmt.Printf(" Error while logging skipped league") + // } + // skippedLeague = append(skippedLeague, ev.League.Name) + // continue + // } event := domain.UpcomingEvent{ 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("⚠️ Total pages %v", data.Pager.Total) + log.Printf("⚠️ Total pages %v", data.Pager.Total/data.Pager.PerPage) totalPages = data.Pager.Total / data.Pager.PerPage if count >= limit { diff --git a/internal/services/odds/service.go b/internal/services/odds/service.go index 36f3a8a..335c2d0 100644 --- a/internal/services/odds/service.go +++ b/internal/services/odds/service.go @@ -98,6 +98,46 @@ func (s *ServiceImpl) FetchNonLiveOdds(ctx context.Context) error { s.logger.Error("Error while inserting ice hockey odd") 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] @@ -223,6 +263,332 @@ func (s *ServiceImpl) parseIceHockey(ctx context.Context, res json.RawMessage) e 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 { if len(section.Sp) == 0 { return nil diff --git a/internal/services/result/eval.go b/internal/services/result/eval.go index 218659c..7352812 100644 --- a/internal/services/result/eval.go +++ b/internal/services/result/eval.go @@ -429,7 +429,7 @@ func evaluateGameLines(outcome domain.BetOutcome, score struct{ Home, Away int } case "Money Line": return evaluateMoneyLine(outcome, score) - case "Spread", "Line": + case "Spread", "Line", "Run Line": // Since Spread betting is essentially the same thing return evaluateAsianHandicap(outcome, score) 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) } -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) { switch outcome.OddName { 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) } } + +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) + } +} diff --git a/internal/services/result/service.go b/internal/services/result/service.go index bc73535..acc996e 100644 --- a/internal/services/result/service.go +++ b/internal/services/result/service.go @@ -161,71 +161,6 @@ func (s *Service) FetchAndProcessResults(ctx context.Context) error { 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) { // 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) @@ -598,21 +533,7 @@ func (s *Service) parseNFL(resultRes json.RawMessage, eventID, oddID, marketID i return domain.CreateResult{}, fmt.Errorf("match not yet completed") } - finalScore := parseSS(nflResp.SS) - - 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) - } + status, err := s.evaluateNFLOutcome(outcome, nflResp) if err != nil { 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) return domain.CreateResult{}, fmt.Errorf("match not yet completed") } - status, err := evaluateRugbyOutcome(outcome, &rugbyResp) + status, err := s.evaluateRugbyOutcome(outcome, rugbyResp) if err != nil { s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", 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) return domain.CreateResult{}, fmt.Errorf("match not yet completed") } - status, err := evaluateRugbyOutcome(outcome, &rugbyResp) + status, err := s.evaluateRugbyOutcome(outcome, rugbyResp) if err != nil { s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", 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) return domain.CreateResult{}, fmt.Errorf("match not yet completed") } - status, err := evaluateBaseballOutcome(outcome, &baseballResp) + status, err := s.evaluateBaseballOutcome(outcome, baseballResp) if err != nil { s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", 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 } -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] { 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.AMERICAN_FOOTBALL_MONEY_LINE): - return evaluateNFLMoneyLine(outcome, finalScore) - case int64(domain.AMERICAN_FOOTBALL_SPREAD): - return evaluateNFLSpread(outcome, finalScore) - case int64(domain.AMERICAN_FOOTBALL_TOTAL_POINTS): - return evaluateNFLTotalPoints(outcome, finalScore) + case int64(domain.AMERICAN_FOOTBALL_GAME_LINES): + return evaluateGameLines(outcome, finalScore) default: 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) } } + +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) + } +} diff --git a/internal/services/result_checker.go b/internal/services/result_checker.go index 59d4b1c..b16ffe1 100644 --- a/internal/services/result_checker.go +++ b/internal/services/result_checker.go @@ -1,189 +1,189 @@ package services -import ( - "encoding/json" - "fmt" - "time" +// import ( +// "encoding/json" +// "fmt" +// "time" - "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" -) +// "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" +// ) -// ResultCheckerService handles the checking of game results -type ResultCheckerService struct { - // Add any dependencies here (e.g., repositories, external APIs) -} +// // ResultCheckerService handles the checking of game results +// type ResultCheckerService struct { +// // Add any dependencies here (e.g., repositories, external APIs) +// } -// NewResultCheckerService creates a new instance of ResultCheckerService -func NewResultCheckerService() *ResultCheckerService { - return &ResultCheckerService{} -} +// // NewResultCheckerService creates a new instance of ResultCheckerService +// func NewResultCheckerService() *ResultCheckerService { +// return &ResultCheckerService{} +// } -// CheckNFLResult checks the result of an NFL game -func (s *ResultCheckerService) CheckNFLResult(data json.RawMessage) (*domain.Result, error) { - nflResult, err := domain.ParseNFLResult(data) - if err != nil { - return nil, fmt.Errorf("failed to parse NFL result: %w", err) - } +// // CheckNFLResult checks the result of an NFL game +// func (s *ResultCheckerService) CheckNFLResult(data json.RawMessage) (*domain.Result, error) { +// nflResult, err := domain.ParseNFLResult(data) +// if err != nil { +// return nil, fmt.Errorf("failed to parse NFL result: %w", err) +// } - winner, err := domain.GetNFLWinner(nflResult) - if err != nil { - return nil, fmt.Errorf("failed to determine NFL winner: %w", err) - } +// winner, err := domain.GetNFLWinner(nflResult) +// if err != nil { +// return nil, fmt.Errorf("failed to determine NFL winner: %w", err) +// } - score := domain.FormatNFLScore(nflResult) +// score := domain.FormatNFLScore(nflResult) - return &domain.Result{ - Status: determineOutcomeStatus(winner, nflResult.Home.Name, nflResult.Away.Name), - Score: score, - FullTimeScore: score, - SS: nflResult.SS, - Scores: map[string]domain.Score{ - "1": nflResult.Scores.FirstQuarter, - "2": nflResult.Scores.SecondQuarter, - "3": nflResult.Scores.ThirdQuarter, - "4": nflResult.Scores.FourthQuarter, - "5": nflResult.Scores.Overtime, - "7": nflResult.Scores.TotalScore, - }, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, nil -} +// return &domain.Result{ +// Status: determineOutcomeStatus(winner, nflResult.Home.Name, nflResult.Away.Name), +// Score: score, +// FullTimeScore: score, +// SS: nflResult.SS, +// Scores: map[string]domain.Score{ +// "1": nflResult.Scores.FirstQuarter, +// "2": nflResult.Scores.SecondQuarter, +// "3": nflResult.Scores.ThirdQuarter, +// "4": nflResult.Scores.FourthQuarter, +// "5": nflResult.Scores.Overtime, +// "7": nflResult.Scores.TotalScore, +// }, +// CreatedAt: time.Now(), +// UpdatedAt: time.Now(), +// }, nil +// } -// determineOutcomeStatus determines the outcome status based on the winner and teams -func determineOutcomeStatus(winner, homeTeam, awayTeam string) domain.OutcomeStatus { - if winner == "Draw" { - return domain.OUTCOME_STATUS_VOID - } - if winner == homeTeam { - return domain.OUTCOME_STATUS_WIN - } - if winner == awayTeam { - return domain.OUTCOME_STATUS_LOSS - } - return domain.OUTCOME_STATUS_PENDING -} +// // determineOutcomeStatus determines the outcome status based on the winner and teams +// func determineOutcomeStatus(winner, homeTeam, awayTeam string) domain.OutcomeStatus { +// if winner == "Draw" { +// return domain.OUTCOME_STATUS_VOID +// } +// if winner == homeTeam { +// return domain.OUTCOME_STATUS_WIN +// } +// if winner == awayTeam { +// return domain.OUTCOME_STATUS_LOSS +// } +// return domain.OUTCOME_STATUS_PENDING +// } -// CheckRugbyResult checks the result of a Rugby game -func (s *ResultCheckerService) CheckRugbyResult(data json.RawMessage) (*domain.Result, error) { - rugbyResult, err := domain.ParseRugbyResult(data) - if err != nil { - return nil, fmt.Errorf("failed to parse Rugby result: %w", err) - } +// // CheckRugbyResult checks the result of a Rugby game +// func (s *ResultCheckerService) CheckRugbyResult(data json.RawMessage) (*domain.Result, error) { +// rugbyResult, err := domain.ParseRugbyResult(data) +// if err != nil { +// return nil, fmt.Errorf("failed to parse Rugby result: %w", err) +// } - winner, err := domain.GetRugbyWinner(rugbyResult) - if err != nil { - return nil, fmt.Errorf("failed to determine Rugby winner: %w", err) - } +// winner, err := domain.GetRugbyWinner(rugbyResult) +// if err != nil { +// return nil, fmt.Errorf("failed to determine Rugby winner: %w", err) +// } - score := domain.FormatRugbyScore(rugbyResult) +// score := domain.FormatRugbyScore(rugbyResult) - return &domain.Result{ - Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), - Score: score, - FullTimeScore: score, - SS: rugbyResult.SS, - Scores: map[string]domain.Score{ - "1": rugbyResult.Scores.FirstHalf, - "2": rugbyResult.Scores.SecondHalf, - "7": rugbyResult.Scores.TotalScore, - }, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, nil -} +// return &domain.Result{ +// Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), +// Score: score, +// FullTimeScore: score, +// SS: rugbyResult.SS, +// Scores: map[string]domain.Score{ +// "1": rugbyResult.Scores.FirstHalf, +// "2": rugbyResult.Scores.SecondHalf, +// "7": rugbyResult.Scores.TotalScore, +// }, +// CreatedAt: time.Now(), +// UpdatedAt: time.Now(), +// }, nil +// } -// CheckBaseballResult checks the result of a Baseball game -func (s *ResultCheckerService) CheckBaseballResult(data json.RawMessage) (*domain.Result, error) { - baseballResult, err := domain.ParseBaseballResult(data) - if err != nil { - return nil, fmt.Errorf("failed to parse Baseball result: %w", err) - } +// // CheckBaseballResult checks the result of a Baseball game +// func (s *ResultCheckerService) CheckBaseballResult(data json.RawMessage) (*domain.Result, error) { +// baseballResult, err := domain.ParseBaseballResult(data) +// if err != nil { +// return nil, fmt.Errorf("failed to parse Baseball result: %w", err) +// } - winner, err := domain.GetBaseballWinner(baseballResult) - if err != nil { - return nil, fmt.Errorf("failed to determine Baseball winner: %w", err) - } +// winner, err := domain.GetBaseballWinner(baseballResult) +// if err != nil { +// return nil, fmt.Errorf("failed to determine Baseball winner: %w", err) +// } - score := domain.FormatBaseballScore(baseballResult) +// score := domain.FormatBaseballScore(baseballResult) - return &domain.Result{ - Status: determineOutcomeStatus(winner, baseballResult.Home.Name, baseballResult.Away.Name), - Score: score, - FullTimeScore: score, - SS: baseballResult.SS, - Scores: map[string]domain.Score{ - "1": baseballResult.Scores.FirstInning, - "2": baseballResult.Scores.SecondInning, - "3": baseballResult.Scores.ThirdInning, - "4": baseballResult.Scores.FourthInning, - "5": baseballResult.Scores.FifthInning, - "6": baseballResult.Scores.SixthInning, - "7": baseballResult.Scores.SeventhInning, - "8": baseballResult.Scores.EighthInning, - "9": baseballResult.Scores.NinthInning, - "10": baseballResult.Scores.ExtraInnings, - "T": baseballResult.Scores.TotalScore, - }, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, nil -} +// return &domain.Result{ +// Status: determineOutcomeStatus(winner, baseballResult.Home.Name, baseballResult.Away.Name), +// Score: score, +// FullTimeScore: score, +// SS: baseballResult.SS, +// Scores: map[string]domain.Score{ +// "1": baseballResult.Scores.FirstInning, +// "2": baseballResult.Scores.SecondInning, +// "3": baseballResult.Scores.ThirdInning, +// "4": baseballResult.Scores.FourthInning, +// "5": baseballResult.Scores.FifthInning, +// "6": baseballResult.Scores.SixthInning, +// "7": baseballResult.Scores.SeventhInning, +// "8": baseballResult.Scores.EighthInning, +// "9": baseballResult.Scores.NinthInning, +// "10": baseballResult.Scores.ExtraInnings, +// "T": baseballResult.Scores.TotalScore, +// }, +// CreatedAt: time.Now(), +// UpdatedAt: time.Now(), +// }, nil +// } -// CheckRugbyUnionResult checks the result of a Rugby Union game -func (s *ResultCheckerService) CheckRugbyUnionResult(data json.RawMessage) (*domain.Result, error) { - rugbyResult, err := domain.ParseRugbyUnionResult(data) - if err != nil { - return nil, fmt.Errorf("failed to parse Rugby Union result: %w", err) - } +// // CheckRugbyUnionResult checks the result of a Rugby Union game +// func (s *ResultCheckerService) CheckRugbyUnionResult(data json.RawMessage) (*domain.Result, error) { +// rugbyResult, err := domain.ParseRugbyUnionResult(data) +// if err != nil { +// return nil, fmt.Errorf("failed to parse Rugby Union result: %w", err) +// } - winner, err := domain.GetRugbyWinner(rugbyResult) - if err != nil { - return nil, fmt.Errorf("failed to determine Rugby Union winner: %w", err) - } +// winner, err := domain.GetRugbyWinner(rugbyResult) +// if err != nil { +// return nil, fmt.Errorf("failed to determine Rugby Union winner: %w", err) +// } - score := domain.FormatRugbyScore(rugbyResult) +// score := domain.FormatRugbyScore(rugbyResult) - return &domain.Result{ - Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), - Score: score, - FullTimeScore: score, - SS: rugbyResult.SS, - Scores: map[string]domain.Score{ - "1": rugbyResult.Scores.FirstHalf, - "2": rugbyResult.Scores.SecondHalf, - "7": rugbyResult.Scores.TotalScore, - }, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, nil -} +// return &domain.Result{ +// Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), +// Score: score, +// FullTimeScore: score, +// SS: rugbyResult.SS, +// Scores: map[string]domain.Score{ +// "1": rugbyResult.Scores.FirstHalf, +// "2": rugbyResult.Scores.SecondHalf, +// "7": rugbyResult.Scores.TotalScore, +// }, +// CreatedAt: time.Now(), +// UpdatedAt: time.Now(), +// }, nil +// } -// CheckRugbyLeagueResult checks the result of a Rugby League game -func (s *ResultCheckerService) CheckRugbyLeagueResult(data json.RawMessage) (*domain.Result, error) { - rugbyResult, err := domain.ParseRugbyLeagueResult(data) - if err != nil { - return nil, fmt.Errorf("failed to parse Rugby League result: %w", err) - } +// // CheckRugbyLeagueResult checks the result of a Rugby League game +// func (s *ResultCheckerService) CheckRugbyLeagueResult(data json.RawMessage) (*domain.Result, error) { +// rugbyResult, err := domain.ParseRugbyLeagueResult(data) +// if err != nil { +// return nil, fmt.Errorf("failed to parse Rugby League result: %w", err) +// } - winner, err := domain.GetRugbyWinner(rugbyResult) - if err != nil { - return nil, fmt.Errorf("failed to determine Rugby League winner: %w", err) - } +// winner, err := domain.GetRugbyWinner(rugbyResult) +// if err != nil { +// return nil, fmt.Errorf("failed to determine Rugby League winner: %w", err) +// } - score := domain.FormatRugbyScore(rugbyResult) +// score := domain.FormatRugbyScore(rugbyResult) - return &domain.Result{ - Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), - Score: score, - FullTimeScore: score, - SS: rugbyResult.SS, - Scores: map[string]domain.Score{ - "1": rugbyResult.Scores.FirstHalf, - "2": rugbyResult.Scores.SecondHalf, - "7": rugbyResult.Scores.TotalScore, - }, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, nil -} +// return &domain.Result{ +// Status: determineOutcomeStatus(winner, rugbyResult.Home.Name, rugbyResult.Away.Name), +// Score: score, +// FullTimeScore: score, +// SS: rugbyResult.SS, +// Scores: map[string]domain.Score{ +// "1": rugbyResult.Scores.FirstHalf, +// "2": rugbyResult.Scores.SecondHalf, +// "7": rugbyResult.Scores.TotalScore, +// }, +// CreatedAt: time.Now(), +// UpdatedAt: time.Now(), +// }, nil +// } diff --git a/internal/web_server/cron.go b/internal/web_server/cron.go index e07a014..a6e41a1 100644 --- a/internal/web_server/cron.go +++ b/internal/web_server/cron.go @@ -21,22 +21,22 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S spec string task func() }{ - // { - // spec: "0 0 * * * *", // Every 1 hour - // task: func() { - // if err := eventService.FetchUpcomingEvents(context.Background()); err != nil { - // log.Printf("FetchUpcomingEvents error: %v", err) - // } - // }, - // }, - // { - // spec: "0 */15 * * * *", // Every 15 minutes - // task: func() { - // if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil { - // log.Printf("FetchNonLiveOdds error: %v", err) - // } - // }, - // }, + { + spec: "0 0 * * * *", // Every 1 hour + task: func() { + if err := eventService.FetchUpcomingEvents(context.Background()); err != nil { + log.Printf("FetchUpcomingEvents error: %v", err) + } + }, + }, + { + spec: "0 */15 * * * *", // Every 15 minutes + task: func() { + if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil { + log.Printf("FetchNonLiveOdds error: %v", err) + } + }, + }, { spec: "0 */15 * * * *", // Every 15 Minutes task: func() { @@ -52,7 +52,7 @@ func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.S } for _, job := range schedule { - // job.task() + job.task() if _, err := c.AddFunc(job.spec, job.task); err != nil { log.Fatalf("Failed to schedule cron job: %v", err) } diff --git a/internal/web_server/handlers/prematch.go b/internal/web_server/handlers/prematch.go index b8d3778..9457e1c 100644 --- a/internal/web_server/handlers/prematch.go +++ b/internal/web_server/handlers/prematch.go @@ -82,7 +82,7 @@ func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error { rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID) 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) } diff --git a/makefile b/makefile index b49fd95..a842d04 100644 --- a/makefile +++ b/makefile @@ -54,11 +54,10 @@ db-up: .PHONY: db-down db-down: - @docker volume rm fortunebet-backend_postgres_data @docker compose down + @docker volume rm fortunebet-backend_postgres_data postgres: @docker exec -it fortunebet-backend-postgres-1 psql -U root -d gh - .PHONY: sqlc-gen sqlc-gen: @sqlc generate \ No newline at end of file