219 lines
6.9 KiB
TypeScript
219 lines
6.9 KiB
TypeScript
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<Response> {
|
|
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()
|
|
}
|
|
}
|