1st
This commit is contained in:
248
parser.go
Executable file
248
parser.go
Executable file
@@ -0,0 +1,248 @@
|
||||
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}
|
||||
|
||||
<a href="live/Football/2084034-FIFA-20-Italian-Cup/240767941-Fiorentina-Paulo-Milan-Arta/" class="c-events__name">
|
||||
|
||||
*/
|
||||
|
||||
// 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"`
|
||||
}
|
||||
Reference in New Issue
Block a user