const base = 'https://euw1.api.riotgames.com' const api_key = process.env.RIOT_API_KEY const sleep_minutes = 12 import { MongoClient } from 'mongodb' import champion_stat from './champion_stat' main() async function main() { // Check if we're in development mode with pre-loaded data if (process.env.NODE_ENV === 'development' && process.env.USE_IMPORTED_DATA === 'true') { console.log('MatchCollector - Development mode with pre-loaded data') await runWithPreloadedData() return } // Original production mode console.log('MatchCollector - Hello !') const client = await connectToDatabase() const [latestPatch, latestPatchTime] = await fetchLatestPatchDate(client) console.log( 'Connected to database, latest patch ' + latestPatch + ' was epoch: ' + latestPatchTime ) const alreadySeenGameList = await alreadySeenGames(client, latestPatch) console.log('We already have ' + alreadySeenGameList.length + ' matches for this patch !') console.log('Using RIOT_API_KEY: ' + api_key) if (api_key != null && api_key != undefined && api_key != '') { const challengerLeague = await fetchChallengerLeague() console.log('ChallengerLeague: got ' + challengerLeague.entries.length + ' entries') const gameList = [] let i = 0 for (const challenger of challengerLeague.entries) { console.log('Entry ' + i + '/' + challengerLeague.entries.length + ' ...') const puuid = challenger.puuid const challengerGameList = await summonerGameList(puuid, latestPatchTime) for (const game of challengerGameList) { if (!gameList.includes(game) && !alreadySeenGameList.includes(game)) { gameList.push(game) } } i++ } console.log('Games: got ' + gameList.length + ' entries') i = 0 for (const game of gameList) { console.log('Entry ' + i + '/' + gameList.length + ' ...') const gameMatch = await match(game) const gameTimeline = await matchTimeline(game) gameMatch.timeline = gameTimeline await saveMatch(client, gameMatch, latestPatch) i++ } } console.log('Generating stats...') await champion_stat.makeChampionsStats(client, latestPatch) console.log('All done. Closing client.') await client.close() } async function handleRateLimit(url: URL): Promise { let response = await fetch(url) if (response.status == 429) { await new Promise(resolve => setTimeout(resolve, sleep_minutes * 60 * 1000)) response = await handleRateLimit(url) } return response } function handleError(response: Response) { if (!response.ok) { console.log( 'Error during fetch(' + response.url + '): STATUS ' + response.status + ' (' + response.statusText + ')' ) process.exit(1) } } async function connectToDatabase() { // Create a MongoClient with a MongoClientOptions object to set the Stable API version let uri = `mongodb://${process.env.MONGO_USER}:${process.env.MONGO_PASS}@${process.env.MONGO_HOST}` if ( process.env.MONGO_URI != undefined && process.env.MONGO_URI != null && process.env.MONGO_URI != '' ) { uri = process.env.MONGO_URI } const client = new MongoClient(uri) await client.connect() return client } async function fetchLatestPatchDate(client) { const database = client.db('patches') const patches = database.collection('patches') const latestPatch = await patches.find().limit(1).sort({ date: -1 }).next() return [latestPatch.patch, Math.floor(latestPatch.date.valueOf() / 1000)] } async function fetchChallengerLeague() { const queue = 'RANKED_SOLO_5x5' const endpoint = `/lol/league/v4/challengerleagues/by-queue/${queue}` const url = `${base}${endpoint}?api_key=${api_key}` const challengerLeagueResponse = await handleRateLimit(new URL(url)) handleError(challengerLeagueResponse) const challengerLeague = await challengerLeagueResponse.json() return challengerLeague } async function summonerGameList(puuid, startTime) { const base = 'https://europe.api.riotgames.com' const endpoint = `/lol/match/v5/matches/by-puuid/${puuid}/ids` const url = `${base}${endpoint}?queue=420&type=ranked&startTime=${startTime}&api_key=${api_key}` const gameListResponse = await handleRateLimit(new URL(url)) handleError(gameListResponse) const gameList = await gameListResponse.json() return gameList } async function match(matchId) { const base = 'https://europe.api.riotgames.com' const endpoint = `/lol/match/v5/matches/${matchId}` const url = `${base}${endpoint}?api_key=${api_key}` const matchResponse = await handleRateLimit(new URL(url)) handleError(matchResponse) const match = await matchResponse.json() return match } async function matchTimeline(matchId) { const base = 'https://europe.api.riotgames.com' const endpoint = `/lol/match/v5/matches/${matchId}/timeline` const url = `${base}${endpoint}?api_key=${api_key}` const timelineResponse = await handleRateLimit(new URL(url)) handleError(timelineResponse) const timeline = await timelineResponse.json() return timeline } async function alreadySeenGames(client, latestPatch) { const database = client.db('matches') const matches = database.collection(latestPatch) const alreadySeen = await matches.distinct('metadata.matchId') return alreadySeen } async function saveMatch(client, match, latestPatch) { const database = client.db('matches') const matches = database.collection(latestPatch) await matches.insertOne(match) } /** * Development mode function that generates stats from pre-loaded data */ async function runWithPreloadedData() { console.log('Using pre-loaded match data for development') const client = await connectToDatabase() try { const [latestPatch] = await fetchLatestPatchDate(client) console.log(`Latest patch: ${latestPatch}`) // Check if we have matches for this patch const matchesDb = client.db('matches') const collections = await matchesDb.listCollections().toArray() const patchCollections = collections.map(c => c.name).filter(name => name === latestPatch) if (patchCollections.length === 0) { console.error(`❌ No match data found for patch ${latestPatch}`) console.log('💡 Please run the data import script first:') console.log(' node dev/scripts/setup-db.js') return } console.log(`Found ${patchCollections.length} match collection(s)`) // Generate stats for each patch with data for (const patch of patchCollections) { console.log(`Generating stats for patch ${patch}...`) await champion_stat.makeChampionsStats(client, patch) console.log(`Stats generated for patch ${patch}`) } console.log('🎉 All stats generated successfully!') console.log('🚀 Your development database is ready for frontend testing!') } catch (error) { console.error('❌ Error in development mode:', error) throw error } finally { await client.close() } }