Skip to content

Commit e9d0bc0

Browse files
committed
feat: add paginated match retrieval and combined match detail fetch
- add getMatchlistByPuuidAll with 100-size pagination and Riot query filters - add getMatchTimelineById for Match-V5 timeline payloads - add getMatchesWithDetailsByPuuid with configurable pacing for rate-limit safety - update endpoint test script to cover timeline and combined list/detail flows - document new RiotAPI match methods, query params, and pacing options
1 parent 0c06de1 commit e9d0bc0

3 files changed

Lines changed: 128 additions & 2 deletions

File tree

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,22 @@ fetchStaticData();
101101
- `getAccountByRiotId(riotId, [tagLine], [region])`: Fetch account by Riot ID (e.g., `Timmsy#BRUV`).
102102
- `getSummonerByPuuid(puuid, [region])`: Get summoner data by PUUID.
103103
- `getMatchlistByPuuid(puuid, [options], [region])`: Get match history (options: `{ start, count }`).
104-
- `getMatchById(matchId, [region])`: Get match details.
104+
- `getMatchById(matchId, [region])`: Get full match payload (`metadata` + `info`) by match ID.
105+
- `getMatchTimelineById(matchId, [region])`: Get timeline payload by match ID.
106+
- `getMatchlistByPuuidAll(puuid, [options], [region], [pacing])`: Fetch all match IDs in pages of 100.
107+
- `getMatchesWithDetailsByPuuid(puuid, [options], [region], [pacing])`: Fetch all match IDs and their match payloads.
108+
109+
`options` supports Riot Match-V5 query params:
110+
- `startTime` (epoch seconds)
111+
- `endTime` (epoch seconds)
112+
- `queue` (int)
113+
- `type` (string)
114+
- `start` (int, default `0`)
115+
- `count` (int, `0-100`, single-page method only)
116+
117+
`pacing` helps respect rate limits on multi-request methods:
118+
- `getMatchlistByPuuidAll`: `{ delayMs, maxMatches }`
119+
- `getMatchesWithDetailsByPuuid`: `{ pageDelayMs, detailDelayMs, maxMatches }`
105120

106121
### DataDragon
107122

endpoints/riot.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2+
13
module.exports = (client, defaultRegion, regionMap) => ({
24
/**
35
* Fetch account data by Riot ID.
@@ -81,4 +83,94 @@ module.exports = (client, defaultRegion, regionMap) => ({
8183
throw this._handleError(error);
8284
}
8385
},
86+
87+
/**
88+
* Fetch match timeline data by match ID.
89+
* @param {string} matchId - Match ID (e.g., "EUW1_1234567890").
90+
* @param {string} [region] - Region code used to resolve shard routing.
91+
* @returns {Promise<object>} Match timeline payload.
92+
*/
93+
async getMatchTimelineById(matchId, region = defaultRegion) {
94+
const shard = regionMap[region].shard;
95+
try {
96+
const response = await client.get(`/lol/match/v5/matches/${matchId}/timeline`, {
97+
baseURL: `https://${shard}`,
98+
});
99+
return response.data;
100+
} catch (error) {
101+
throw this._handleError(error);
102+
}
103+
},
104+
105+
/**
106+
* Fetch all match IDs for a PUUID using Riot's max page size (100).
107+
* @param {string} puuid - Player PUUID.
108+
* @param {object} [options] - Riot filters: startTime, endTime, queue, type, start.
109+
* @param {string} [region] - Region code used to resolve shard routing.
110+
* @param {object} [pacing] - Pacing controls.
111+
* @param {number} [pacing.delayMs=1250] - Delay between page requests.
112+
* @param {number|null} [pacing.maxMatches=null] - Optional cap on total IDs returned.
113+
* @returns {Promise<string[]>} All matched IDs.
114+
*/
115+
async getMatchlistByPuuidAll(puuid, options = {}, region = defaultRegion, pacing = {}) {
116+
const baseStart = Number.isInteger(options.start) ? options.start : 0;
117+
const pageDelayMs = Number.isInteger(pacing.delayMs) ? pacing.delayMs : 1250;
118+
const maxMatches = Number.isInteger(pacing.maxMatches) && pacing.maxMatches >= 0 ? pacing.maxMatches : null;
119+
const filters = {
120+
startTime: options.startTime,
121+
endTime: options.endTime,
122+
queue: options.queue,
123+
type: options.type,
124+
};
125+
126+
let start = baseStart;
127+
const allMatchIds = [];
128+
129+
while (true) {
130+
const remaining = maxMatches === null ? 100 : Math.min(100, maxMatches - allMatchIds.length);
131+
if (remaining <= 0) break;
132+
133+
const page = await this.getMatchlistByPuuid(puuid, { ...filters, start, count: remaining }, region);
134+
allMatchIds.push(...page);
135+
136+
if (page.length < remaining) break;
137+
start += page.length;
138+
if (pageDelayMs > 0) await sleep(pageDelayMs);
139+
}
140+
141+
return allMatchIds;
142+
},
143+
144+
/**
145+
* Fetch match IDs and full match payloads for each ID.
146+
* @param {string} puuid - Player PUUID.
147+
* @param {object} [options] - Riot filters: startTime, endTime, queue, type, start.
148+
* @param {string} [region] - Region code used to resolve shard routing.
149+
* @param {object} [pacing] - Pacing controls.
150+
* @param {number} [pacing.pageDelayMs=1250] - Delay between matchlist page requests.
151+
* @param {number} [pacing.detailDelayMs=1250] - Delay between match detail requests.
152+
* @param {number|null} [pacing.maxMatches=null] - Optional cap on total matches fetched.
153+
* @returns {Promise<{matchIds: string[], matches: object[]}>} IDs and full match payloads.
154+
*/
155+
async getMatchesWithDetailsByPuuid(puuid, options = {}, region = defaultRegion, pacing = {}) {
156+
const pageDelayMs = Number.isInteger(pacing.pageDelayMs) ? pacing.pageDelayMs : 1250;
157+
const detailDelayMs = Number.isInteger(pacing.detailDelayMs) ? pacing.detailDelayMs : 1250;
158+
const maxMatches = Number.isInteger(pacing.maxMatches) && pacing.maxMatches >= 0 ? pacing.maxMatches : null;
159+
const matchIds = await this.getMatchlistByPuuidAll(
160+
puuid,
161+
options,
162+
region,
163+
{ delayMs: pageDelayMs, maxMatches }
164+
);
165+
const matches = [];
166+
167+
for (let i = 0; i < matchIds.length; i += 1) {
168+
matches.push(await this.getMatchById(matchIds[i], region));
169+
if (detailDelayMs > 0 && i < matchIds.length - 1) {
170+
await sleep(detailDelayMs);
171+
}
172+
}
173+
174+
return { matchIds, matches };
175+
},
84176
});

test-endpoints.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,27 @@ async function run() {
2323
if (matchIds.length > 0) {
2424
const match = await riot.getMatchById(matchIds[0]);
2525
console.log('[PASS] getMatchById:', match.metadata.matchId);
26+
27+
const timeline = await riot.getMatchTimelineById(matchIds[0]);
28+
console.log('[PASS] getMatchTimelineById:', timeline.metadata.matchId);
29+
30+
const allMatchIds = await riot.getMatchlistByPuuidAll(
31+
account.puuid,
32+
{ start: 0 },
33+
undefined,
34+
{ maxMatches: 2, delayMs: 0 }
35+
);
36+
console.log('[PASS] getMatchlistByPuuidAll:', allMatchIds.length, 'match ids');
37+
38+
const withDetails = await riot.getMatchesWithDetailsByPuuid(
39+
account.puuid,
40+
{ start: 0 },
41+
undefined,
42+
{ maxMatches: 2, pageDelayMs: 0, detailDelayMs: 0 }
43+
);
44+
console.log('[PASS] getMatchesWithDetailsByPuuid:', withDetails.matches.length, 'matches');
2645
} else {
27-
console.log('[SKIP] getMatchById: no matches returned');
46+
console.log('[SKIP] Match-by-id/timeline/all/details checks: no matches returned');
2847
}
2948
} else if (process.env.RIOT_API_KEY) {
3049
console.log('[SKIP] Riot endpoints: set TEST_RIOT_ID (and TEST_TAG_LINE if needed)');

0 commit comments

Comments
 (0)