This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
* Spor Toto API response types
|
||||
* Source: https://sportotov2.iddaa.com/SporToto
|
||||
*/
|
||||
export interface SporTotoApiEvent {
|
||||
eventNo: number;
|
||||
eventName: string; // "Blackpool-Burton Albion"
|
||||
competitionName: string; // "İN1"
|
||||
eventDate: string; // "2026-03-28T18:00:00"
|
||||
result: string | null;
|
||||
winner: string | null;
|
||||
}
|
||||
|
||||
export interface SporTotoApiDividend {
|
||||
winnerCount15?: number;
|
||||
dividend15?: number;
|
||||
winnerCount14?: number;
|
||||
dividend14?: number;
|
||||
winnerCount13?: number;
|
||||
dividend13?: number;
|
||||
winnerCount12?: number;
|
||||
dividend12?: number;
|
||||
}
|
||||
|
||||
export interface SporTotoApiResponse {
|
||||
isSuccess: boolean;
|
||||
data: {
|
||||
payinBeginDate: string;
|
||||
payinEndDate: string;
|
||||
gameCycleNo: number;
|
||||
dividends: SporTotoApiDividend | null;
|
||||
events: SporTotoApiEvent[];
|
||||
programName: string;
|
||||
nextDrawExpectedWins: number | null;
|
||||
} | null;
|
||||
message: string;
|
||||
error: string | null;
|
||||
info: string | null;
|
||||
dateTime: string | null;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class TotoFetcherService {
|
||||
private readonly logger = new Logger(TotoFetcherService.name);
|
||||
private readonly apiUrl = 'https://sportotov2.iddaa.com/SporToto';
|
||||
|
||||
/**
|
||||
* Fetch current bulletin from Spor Toto API
|
||||
*/
|
||||
async fetchCurrentBulletin(): Promise<SporTotoApiResponse | null> {
|
||||
try {
|
||||
this.logger.log('Fetching current Spor Toto bulletin...');
|
||||
const response = await axios.get<SporTotoApiResponse>(this.apiUrl, {
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'User-Agent': 'SuggestBet/1.0',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.data?.isSuccess || !response.data?.data) {
|
||||
this.logger.warn(
|
||||
'Spor Toto API returned unsuccessful response',
|
||||
response.data?.message,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Fetched bulletin: Cycle ${response.data.data.gameCycleNo} — ${response.data.data.programName} (${response.data.data.events.length} events)`,
|
||||
);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
this.logger.error(
|
||||
`Spor Toto API error: ${error.message}`,
|
||||
error.response?.status,
|
||||
);
|
||||
} else {
|
||||
this.logger.error('Spor Toto fetch failed', error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse "Blackpool-Burton Albion" → { home: "Blackpool", away: "Burton Albion" }
|
||||
*/
|
||||
parseEventName(eventName: string): {
|
||||
homeTeam: string;
|
||||
awayTeam: string;
|
||||
} {
|
||||
const parts = eventName.split('-');
|
||||
if (parts.length >= 2) {
|
||||
return {
|
||||
homeTeam: parts[0].trim(),
|
||||
awayTeam: parts.slice(1).join('-').trim(),
|
||||
};
|
||||
}
|
||||
return { homeTeam: eventName, awayTeam: '' };
|
||||
}
|
||||
|
||||
/**
|
||||
* Map API result/winner to TotoMatchResult enum value
|
||||
* API returns: "1" (HOME), "0" (DRAW), "2" (AWAY)
|
||||
*/
|
||||
mapResultToEnum(winner: string | null): 'HOME' | 'DRAW' | 'AWAY' | null {
|
||||
if (!winner) return null;
|
||||
switch (winner) {
|
||||
case '1':
|
||||
return 'HOME';
|
||||
case '0':
|
||||
case 'X':
|
||||
return 'DRAW';
|
||||
case '2':
|
||||
return 'AWAY';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user