134 lines
3.6 KiB
Go
134 lines
3.6 KiB
Go
package odds
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
|
|
)
|
|
|
|
type ServiceImpl struct {
|
|
token string
|
|
store *repository.Store
|
|
}
|
|
|
|
func New(token string, store *repository.Store) *ServiceImpl {
|
|
return &ServiceImpl{token: token, store: store}
|
|
}
|
|
|
|
func (s *ServiceImpl) FetchNonLiveOdds(ctx context.Context) error {
|
|
eventIDs, err := s.store.GetAllUpcomingEvents(ctx)
|
|
if err != nil {
|
|
log.Printf("❌ Failed to fetch upcoming event IDs: %v", err)
|
|
return err
|
|
}
|
|
|
|
for _, event := range eventIDs {
|
|
eventID := event.ID
|
|
prematchURL := "https://api.b365api.com/v3/bet365/prematch?token=" + s.token + "&FI=" + eventID
|
|
log.Printf("📡 Fetching prematch odds for event ID: %s", eventID)
|
|
resp, err := http.Get(prematchURL)
|
|
if err != nil {
|
|
log.Printf("❌ Failed to fetch prematch odds for event %s: %v", eventID, err)
|
|
continue
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
var oddsData struct {
|
|
Success int `json:"success"`
|
|
Results []struct {
|
|
EventID string `json:"event_id"`
|
|
FI string `json:"FI"`
|
|
Main OddsSection `json:"main"`
|
|
} `json:"results"`
|
|
}
|
|
if err := json.Unmarshal(body, &oddsData); err != nil || oddsData.Success != 1 || len(oddsData.Results) == 0 {
|
|
log.Printf("❌ Invalid prematch data for event %s", eventID)
|
|
continue
|
|
}
|
|
|
|
result := oddsData.Results[0]
|
|
finalID := result.EventID
|
|
if finalID == "" {
|
|
finalID = result.FI
|
|
}
|
|
if finalID == "" {
|
|
log.Printf("⚠️ Skipping event %s with no valid ID", eventID)
|
|
continue
|
|
}
|
|
|
|
s.storeSection(ctx, finalID, result.FI, "main", result.Main)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *ServiceImpl) storeSection(ctx context.Context, eventID, fi, sectionName string, section OddsSection) {
|
|
if len(section.Sp) == 0 {
|
|
return
|
|
}
|
|
|
|
updatedAtUnix, _ := strconv.ParseInt(section.UpdatedAt, 10, 64)
|
|
updatedAt := time.Unix(updatedAtUnix, 0)
|
|
|
|
for marketType, market := range section.Sp {
|
|
if len(market.Odds) == 0 {
|
|
continue
|
|
}
|
|
|
|
marketRecord := domain.Market{
|
|
EventID: eventID,
|
|
FI: fi,
|
|
MarketCategory: sectionName,
|
|
MarketType: marketType,
|
|
MarketName: market.Name,
|
|
MarketID: market.ID,
|
|
UpdatedAt: updatedAt,
|
|
Odds: market.Odds,
|
|
}
|
|
|
|
_ = s.store.SaveNonLiveMarket(ctx, marketRecord)
|
|
}
|
|
}
|
|
|
|
type OddsMarket struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Odds []json.RawMessage `json:"odds"`
|
|
Header string `json:"header,omitempty"`
|
|
Handicap string `json:"handicap,omitempty"`
|
|
}
|
|
|
|
type OddsSection struct {
|
|
UpdatedAt string `json:"updated_at"`
|
|
Sp map[string]OddsMarket `json:"sp"`
|
|
}
|
|
|
|
func (s *ServiceImpl) GetPrematchOdds(ctx context.Context, eventID string) ([]domain.Odd, error) {
|
|
return s.store.GetPrematchOdds(ctx, eventID)
|
|
}
|
|
|
|
func (s *ServiceImpl) GetALLPrematchOdds(ctx context.Context) ([]domain.Odd, error) {
|
|
return s.store.GetALLPrematchOdds(ctx)
|
|
}
|
|
|
|
func (s *ServiceImpl) GetRawOddsByMarketID(ctx context.Context, marketID string, upcomingID string) ([]domain.RawOddsByMarketID, error) {
|
|
rows, err := s.store.GetRawOddsByMarketID(ctx, marketID, upcomingID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return []domain.RawOddsByMarketID{rows}, nil
|
|
}
|
|
|
|
func (s *ServiceImpl) GetPrematchOddsByUpcomingID(ctx context.Context, upcomingID string, limit, offset int32) ([]domain.Odd, error) {
|
|
return s.store.GetPrematchOddsByUpcomingID(ctx, upcomingID, limit, offset)
|
|
}
|