package onexbet import ( "fmt" "strings" ) type organizer struct { Name string `json:"name"` Sport string `json:"sport"` } type teamName struct { Name string `json:"name"` } // служебная структура для парсинга списка live матчей type liveMatch struct { StartDate string `json:"startDate"` URL string `json:"url"` Organizer organizer `json:"organizer"` HomeTeam teamName `json:"homeTeam"` AwayTeam teamName `json:"awayTeam"` } // служебная структура для статистики: удары, угловые, атаки... type keyValue struct { Key string Value string } // служебная структура для коэффициентов/параметров type rawMarket struct { OffersList [][]rawOffer `json:"E"` // Массив массивов! MarketType int `json:"G"` } type rawOffer struct { Price float64 `json:"C"` Param float64 `json:"P"` // 2.5 Side int `json:"T"` // 1 X 2, over/under IsBlocked bool `json:"B"` // означает что цена заблокирована (иконка замка) } func getMatchIDFromURL(url string) string { // формат ссылки live/Football/2084034-FIFA-20-Italian-Cup/240767941-Fiorentina-Paulo-Milan-Arta/ // matchID - 240767941 // Алгоритм: // - разбиваем ссылки на секции по символу '/' // - разбиваем последнюю НЕпустую секцию на части по символу '-' // - первый элемент и будет matchID url = strings.TrimSpace(url) url = strings.TrimSuffix(url, "/") sections := strings.Split(url, "/") last := sections[len(sections)-1] parts := strings.Split(last, "-") return parts[0] } type rawMatchCandidate struct { Sport string `json:"SN"` ChampName string `json:"L"` Home string `json:"O1"` Away string `json:"O2"` StartTime int64 `json:"S"` MatchID string `json:"SGI"` } // служебная структура для парсинга данных live матча type searchResponse struct { Error string ErrorCode int64 Success bool // false, если матч закончен Value []rawMatchCandidate } // Список live матчей /* Live матч. Коэффициенты и т.д. https://1x-bet-ua.com/LiveFeed/GetGameZip?id=240704765&lng=en&cfview=0&isSubGames=true&GroupEvents=true&allEventsGroupSubGames=true&countevents=250&partner=25&marketType=1 Live матч завершен. Ответ: {"Error":null,"ErrorCode":0,"Guid":"","Id":0,"Success":false,"Value":null} */ // https://ua-1x-bet.com/en/live/Football/88637-England-Premier-League/242638344-Leicester-City-Brighton--Hove-Albion/ type liveItem struct { SportName string `json:"SN"` Home string `json:"O1"` Away string `json:"O2"` MatchID int64 `json:"I"` StartTime int64 `json:"S"` ChampName string `json:"L"` // вместе с зоной ZoneName string `json:"CN"` StatsMatchID string `json:"SGI"` // вида 5d02144c286ef2e7bff3015b Stat statAndScore `json:"SC"` } type liveList struct { Success bool Value []liveItem } func getTotal(market rawMarket) (_ Total, err error) { if len(market.OffersList) != 2 { err = fmt.Errorf("Total market must have 2 arrays of offers (Over and Under), not %d", len(market.OffersList)) return } // OVER var over []ParamOffer for _, offer := range market.OffersList[0] { if offer.IsBlocked { continue } over = append(over, ParamOffer{ Price: offer.Price, Param: fmt.Sprintf("%.1f", offer.Param), ParamFloat: offer.Param, }) } // UNDER var under []ParamOffer for _, offer := range market.OffersList[1] { if offer.IsBlocked { continue } under = append(under, ParamOffer{ Price: offer.Price, Param: fmt.Sprintf("%.1f", offer.Param), ParamFloat: offer.Param, }) } return Total{ Over: over, Under: under, }, nil } func getHandicap(market rawMarket) (_ Handicap, err error) { if len(market.OffersList) != 2 { err = fmt.Errorf("Handicap market must have 2 arrays of offers (Home and Away), not %d", len(market.OffersList)) return } // home var home []ParamOffer for _, offer := range market.OffersList[0] { if offer.IsBlocked { continue } home = append(home, ParamOffer{ Price: offer.Price, Param: fmt.Sprintf("%.1f", offer.Param), ParamFloat: offer.Param, }) } // away var away []ParamOffer for _, offer := range market.OffersList[1] { if offer.IsBlocked { continue } away = append(away, ParamOffer{ Price: offer.Price, Param: fmt.Sprintf("%.1f", offer.Param), ParamFloat: offer.Param, }) } return Handicap{ Home: home, Away: away, }, nil } /// live match data // служебная структура для парсинга данных live матча type teamLiveMatchDataEnvelope struct { Error string ErrorCode int64 Success bool // false, если матч закончен Value teamLiveMatchData } // half 1, half 2 type teamSG struct { SubMatchID int `json:"I"` Period int `json:"P"` PeriodName string `json:"PN"` // Опциональное поле (у тенниса нет) SubCategory string `json:"TG"` // yellow cards, etc... // В "Austria. Erste Liga" у матчей half 1 кодируется в нижеуказанных полях // Требует уточнения. // EC int // EGC int // GE []rawMarket } type teamLiveMatchData struct { // список subMatchID для half 1, half 2... // поле есть до лайва вместо SG? BIG []teamSG GE []rawMarket // рынки // периоды и голы; текущее время матча; статистика по ударам, атакам... SC teamStatsAndScore // список subMatchID для half 1, half 2... // коэффициенты можно получить отдельным HTTP-запросом SG []teamSG //StatsMatchID string `json:""SGI` } type teamStatsAndScore struct { CurrentPeriod int `json:"CP"` FullTimeScore scoreStruct `json:"FS"` ScoreByPeriods []periodScore `json:"PS"` CurrentTime int `json:"TS"` // в секундах с начала матча! Stats []keyValue `json:"S"` // статистика удары, угловые, атаки и т.д. } type scoreStruct struct { HomeScore int `json:"S1"` AwayScore int `json:"S2"` } type periodScore struct { Period int `json:"Key"` Score scoreStruct `json:"Value"` }