package onexbet import ( "encoding/json" "fmt" "strconv" "strings" webspider "gordenko.dev/dima/spider" ) // ListLiveMatchesBySport - букмекер возвращает много мусора, типа киберспорта, поэтому метод // champFilter фильтрует разный мусор func ListLiveMatchesBySport(sportID OnexbetSport) (list []LiveMatch, err error) { url := fmt.Sprintf(liveSportURLPattern, sportID) spider, err := webspider.NewSpider(nil) if err != nil { panic(err) } buf, err := spider.Get(url, nil) if err != nil { return } var rawList liveList err = json.Unmarshal(buf, &rawList) if err != nil { return } var champFilter func(string) bool switch sportID { case Football: champFilter = FootballChampFilter case Handball: champFilter = HandballChampFilter case Tennis: champFilter = TennisChampFilter } for _, m := range rawList.Value { m.ChampName = strings.TrimSpace(m.ChampName) if champFilter != nil { if !champFilter(m.ChampName) { continue } } scoreByPeriods := make(map[int]Score) stat := m.Stat for _, p := range stat.ScoreByPeriods { scoreByPeriods[p.Period] = Score{ Home: p.Score.HomeScore, Away: p.Score.AwayScore, } } list = append(list, LiveMatch{ MatchID: fmt.Sprintf("%d", m.MatchID), Home: m.Home, Away: m.Away, StartTime: m.StartTime, ChampName: m.ChampName, SportName: m.SportName, StatsMatchID: m.StatsMatchID, CurrentPeriod: stat.CurrentPeriod, Score: Score{ Home: stat.Score.HomeScore, Away: stat.Score.AwayScore, }, ScoreByPeriods: scoreByPeriods, }) } return } func LoadTeamLiveMatchData(matchID string) (_ TeamLiveMatchData, isMatchFinished bool, err error) { url := fmt.Sprintf(liveMatchURLPattern, matchID) spider, err := webspider.NewSpider(nil) if err != nil { panic(err) } buf, err := spider.Get(url, nil) if err != nil { return } //fmt.Printf("buf: %s\n\n", buf) var env teamLiveMatchDataEnvelope err = json.Unmarshal(buf, &env) if err != nil { err = fmt.Errorf("json.Unmarshal liveMatchDataEnvelope: %s", err) return } if !env.Success { isMatchFinished = true return } data := TeamLiveMatchData{ MatchID: matchID, } // FULL TIME for _, market := range env.Value.GE { switch market.MarketType { case teamMarketWinner3Way: if len(market.OffersList) != 3 { // ВАЖНО! // Встречается такая херня, что принимают ставки только на 1 или 2 исхода. fmt.Printf("1x2 market must have 3 arrays of offers (1, x, 2), not %d", len(market.OffersList)) break } // [ // { // "C": 1.48, // "G": 1, // "T": 1 // 1 // } // ], // [ // { // "C": 6.11, // "G": 1, // "T": 2 // DRAW // } // ], // [ // { // "C": 4.38, // "G": 1, // "T": 3 // 2 // } // ] winner := &Winner3Way{} homeList := market.OffersList[0] if len(homeList) == 1 { winner.Home = homeList[0].Price } drawList := market.OffersList[1] if len(drawList) == 1 { winner.Draw = drawList[0].Price } awayList := market.OffersList[2] if len(awayList) == 1 { winner.Away = awayList[0].Price } data.Winner = winner case teamMarketTotal: data.Total, err = getTotal(market) if err != nil { err = fmt.Errorf("Full Time total football getTotal: %s", err) return } case teamMarketIndividualTotal1: data.IndividualTotalHome, err = getTotal(market) if err != nil { err = fmt.Errorf("Full Time individual total 1 football getTotal: %s", err) return } case teamMarketIndividualTotal2: data.IndividualTotalAway, err = getTotal(market) if err != nil { err = fmt.Errorf("Full Time individual total 2 football getTotal: %s", err) return } } } // Статистика stats := env.Value.SC // Текущее время матча в секундах data.CurrentTime = stats.CurrentTime data.HomeGoals = stats.FullTimeScore.HomeScore data.AwayGoals = stats.FullTimeScore.AwayScore for _, pair := range stats.Stats { switch pair.Key { case "Attacks1": data.HomeAttacks, _ = strconv.Atoi(pair.Value) case "Attacks2": data.AwayAttacks, _ = strconv.Atoi(pair.Value) case "DanAttacks1": data.HomeDangerousAttacks, _ = strconv.Atoi(pair.Value) case "DanAttacks2": data.AwayDangerousAttacks, _ = strconv.Atoi(pair.Value) case "ShotsOn1": data.HomeShotsOnTarget, _ = strconv.Atoi(pair.Value) case "ShotsOn2": data.AwayShotsOnTarget, _ = strconv.Atoi(pair.Value) case "ShotsOff1": data.HomeShotsOffTarget, _ = strconv.Atoi(pair.Value) case "ShotsOff2": data.AwayShotsOffTarget, _ = strconv.Atoi(pair.Value) } } // SubMatchID первого и второго тайма //type teamSubMatchIDs struct { // H1 string // H2 string //} var h1MatchID string //var h2MatchID string //var subMatchIDs teamSubMatchIDs if len(env.Value.BIG) > 0 { //fmt.Printf("\n\nBIG: %v\n\n", env.Value.BIG) // Парсим 1st HALF for _, item := range env.Value.BIG { period := strings.ToLower(strings.TrimSpace(item.PeriodName)) switch period { case "1 half": if item.SubCategory == "" { h1MatchID = strconv.Itoa(item.SubMatchID) } //case "2 half": // if item.SubCategory == "" { // h2MatchID = strconv.Itoa(item.SubMatchID) // } } } } else { //fmt.Printf("\n\nSG: %v\n\n", env.Value.SG) // Парсим 1st HALF for _, item := range env.Value.SG { period := strings.ToLower(strings.TrimSpace(item.PeriodName)) switch period { case "1 half": if item.SubCategory == "" { h1MatchID = strconv.Itoa(item.SubMatchID) } //case "2 half": // if item.SubCategory == "" { // h2MatchID = strconv.Itoa(item.SubMatchID) // } } } } //fmt.Printf("\n\nsubMatchIDs: %v\n\n", subMatchIDs) if h1MatchID != "" { url = fmt.Sprintf(liveMatchURLPattern, h1MatchID) //fmt.Printf("Load sub url: %s", url) buf, err = spider.Get(url, nil) if err != nil { // Не загрузился 1й тайм - ну и хер с ним. Просто логгируем fmt.Printf("Load sub: %s", err) return } var env teamLiveMatchDataEnvelope err = json.Unmarshal(buf, &env) if err != nil { err = fmt.Errorf("json.Unmarshal liveMatchDataEnvelope: %s", err) return } if !env.Success { return } var half Half // for _, market := range env.Value.GE { switch market.MarketType { case teamMarketTotal: //fmt.Printf("h1 total: %v\n\n", market) half.Total, err = getTotal(market) if err != nil { err = fmt.Errorf("1st Half total football getTotal: %s", err) return } case teamMarketIndividualTotal1: //fmt.Printf("h1 total 1: %v\n\n", market) half.IndividualTotalHome, err = getTotal(market) if err != nil { err = fmt.Errorf("1st Half individual total 1 football getTotal: %s", err) return } case teamMarketIndividualTotal2: //fmt.Printf("h1 total 2: %v\n\n", market) half.IndividualTotalAway, err = getTotal(market) if err != nil { err = fmt.Errorf("1st Half individual total 2 football getTotal: %s", err) return } } } data.H1 = half } //fmt.Printf("%s\n\n", buf) return data, false, nil } /* type matchPeriod struct { // Football, Handball: 1 - half 1, 3 - half 2 // Tennis: 11 - 1st set, 12 - 2nd set, 13 - 3rd set Type int Score1 int Score2 int } // Можно получить и доп. статистику, атак, ударов, где periodType - это // 1 - тайм 1, 3 - тайм 2, 100 - весь матч type matchStats struct { Score1 int Score2 int Status int // 1 - line, 2 - inplay, 3 - end //Winner int // в inplay не 0? Periods []matchPeriod } const ( // для гандбола тоже справедливо footballH1 = 1 footballH2 = 3 ) // GetTeamMatchResult - возвращает счет матча, счет по таймам. Подходит для футбола // и гандбола. func GetTeamMatchResult(statsMatchID string) (stats TeamMatchResult, err error) { url := fmt.Sprintf(matchStatsURLPattern, statsMatchID) spider, err := webspider.NewSpider(nil) if err != nil { panic(err) } buf, err := spider.Get(url, nil) if err != nil { return } fmt.Printf("Response: %s\n", buf) var raw matchStats err = json.Unmarshal(buf, &raw) if err != nil { return } //stats.Winner = raw.Winner stats.Status = raw.Status stats.HomeGoals = raw.Score1 stats.AwayGoals = raw.Score2 // tennis stats.Score.Home = raw.Score1 stats.Score.Away = raw.Score2 stats.ScoreByPeriods = make(map[int]Score) for _, period := range raw.Periods { switch period.Type { case footballH1: // fix - позже удалить H1 и H2 stats.H1 = &HalfStats{ HomeGoals: period.Score1, AwayGoals: period.Score2, } stats.ScoreByPeriods[1] = Score{ Home: period.Score1, Away: period.Score2, } case footballH2: // fix - позже удалить H1 и H2 stats.H2 = &HalfStats{ HomeGoals: period.Score1, AwayGoals: period.Score2, } stats.ScoreByPeriods[2] = Score{ Home: period.Score1, Away: period.Score2, } } } return } */ func GetTeamMatchResult(statsMatchID string) (result TeamMatchResult, err error) { url := fmt.Sprintf(matchStatsURLPattern, statsMatchID) spider, err := webspider.NewSpider(nil) if err != nil { panic(err) } buf, err := spider.Get(url, nil) if err != nil { return } //fmt.Printf("%s\n", buf) var tmp matchResult err = json.Unmarshal(buf, &tmp) if err != nil { return } result.Status = tmp.Status result.ScoreByPeriods = make(map[int]PeriodScore) for _, p := range tmp.Periods { periodNumber := periodCode2PeriodNumberMapping[p.Code] if periodNumber == 0 { continue } result.ScoreByPeriods[periodNumber] = PeriodScore{ HomePoints: p.HomePoints, AwayPoints: p.AwayPoints, } result.HomePoints += p.HomePoints result.AwayPoints += p.AwayPoints } return }