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(let challenger of challengerLeague.entries) { console.log("Entry " + i + "/" + challengerLeague.entries.length + " ...") const puuid = challenger.puuid; const challengerGameList = await summonerGameList(puuid, latestPatchTime); for(let game of challengerGameList) { if(!gameList.includes(game) && !alreadySeenGameList.includes(game)) { gameList.push(game) } } i++; } console.log("Games: got " + gameList.length + " entries"); i = 0; for(let 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(); } }