Files
onexbet/team.go
2026-07-21 03:55:57 +03:00

476 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}