first (part 3: src directory)
Deploy Iddaai Backend / build-and-deploy (push) Successful in 33s

This commit is contained in:
2026-04-16 15:12:27 +03:00
parent 2f0b85a0c7
commit 182f4aae16
125 changed files with 22552 additions and 0 deletions
@@ -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;
}
}
}