UNPKG

samira

Version:

A TypeScript library for League of Legends API calls

187 lines 6.18 kB
"use strict"; /** * Rate limiter utility for Riot Games API * Handles rate limiting for different API endpoints */ Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_RATE_LIMITS = exports.RateLimiter = void 0; exports.createRateLimiter = createRateLimiter; class RateLimiter { constructor(config) { this.config = config; this.state = { lastRequestTime: 0, requestCount: 0, windowStartTime: Date.now(), dailyRequestCount: 0, dailyWindowStart: Date.now(), secondWindowStart: Date.now(), requestsInLastSecond: 0, }; } /** * Check if a request can be made */ canMakeRequest() { const now = Date.now(); // Check daily limit if (this.config.requestsPerDay) { if (this.state.dailyRequestCount >= this.config.requestsPerDay) { return false; } } // Check per-second limit if (now - this.state.secondWindowStart < 1000) { // Within the same second window if (this.state.requestsInLastSecond >= this.config.requestsPerSecond) { return false; } } else { // New second window, reset counter this.state.secondWindowStart = now; this.state.requestsInLastSecond = 0; } // Check per-two-minutes limit if (now - this.state.windowStartTime < 120000) { if (this.state.requestCount >= this.config.requestsPerTwoMinutes) { return false; } } else { // Reset window - only reset if we're actually starting a new window this.state.requestCount = 0; this.state.windowStartTime = now; } return true; } /** * Update window state without resetting (called internally) */ updateWindowState() { const now = Date.now(); // Only reset if we're actually outside the current window if (now - this.state.windowStartTime >= 120000) { this.state.requestCount = 0; this.state.windowStartTime = now; } // Update per-second window if (now - this.state.secondWindowStart >= 1000) { this.state.secondWindowStart = now; this.state.requestsInLastSecond = 0; } // Update daily window if (this.config.requestsPerDay) { const dayStart = new Date(now).setHours(0, 0, 0, 0); if (this.state.dailyWindowStart !== dayStart) { this.state.dailyRequestCount = 0; this.state.dailyWindowStart = dayStart; } } } /** * Record a request being made */ recordRequest() { const now = Date.now(); // Update window state first this.updateWindowState(); this.state.lastRequestTime = now; this.state.requestCount++; this.state.requestsInLastSecond++; if (this.config.requestsPerDay) { this.state.dailyRequestCount++; } } /** * Get the delay needed before the next request can be made */ getDelayUntilNextRequest() { const now = Date.now(); // Check per-second limit let delayForSecondLimit = 0; if (now - this.state.secondWindowStart < 1000) { if (this.state.requestsInLastSecond >= this.config.requestsPerSecond) { // Wait until next second window delayForSecondLimit = 1000 - (now - this.state.secondWindowStart); } } // Check per-two-minutes limit const timeInWindow = now - this.state.windowStartTime; const remainingRequests = this.config.requestsPerTwoMinutes - this.state.requestCount; let delayForTwoMinuteLimit = 0; if (remainingRequests <= 0) { delayForTwoMinuteLimit = 120000 - timeInWindow; } return Math.max(delayForSecondLimit, delayForTwoMinuteLimit); } /** * Wait until a request can be made */ async waitForNextRequest() { const delay = this.getDelayUntilNextRequest(); if (delay > 0) { await new Promise((resolve) => setTimeout(resolve, delay)); } } /** * Get current rate limit status */ getStatus() { // Update window state before returning status this.updateWindowState(); return { canMakeRequest: this.canMakeRequest(), delayUntilNext: this.getDelayUntilNextRequest(), requestsInWindow: this.state.requestCount, dailyRequests: this.state.dailyRequestCount, }; } /** * Reset the rate limiter state */ reset() { this.state = { lastRequestTime: 0, requestCount: 0, windowStartTime: Date.now(), dailyRequestCount: 0, dailyWindowStart: Date.now(), secondWindowStart: Date.now(), requestsInLastSecond: 0, }; } } exports.RateLimiter = RateLimiter; /** * Default rate limit configurations for different API endpoints */ exports.DEFAULT_RATE_LIMITS = { // Standard endpoints (20 requests per second, 100 requests per 2 minutes) default: { requestsPerSecond: 20, requestsPerTwoMinutes: 100, }, // Match endpoints (100 requests per second, 2000 requests per 2 minutes) match: { requestsPerSecond: 100, requestsPerTwoMinutes: 2000, }, // Spectator endpoints (20 requests per second, 100 requests per 2 minutes) spectator: { requestsPerSecond: 20, requestsPerTwoMinutes: 100, }, // Status endpoints (20 requests per second, 100 requests per 2 minutes) status: { requestsPerSecond: 20, requestsPerTwoMinutes: 100, }, }; /** * Create a rate limiter for a specific endpoint type */ function createRateLimiter(endpointType = 'default') { return new RateLimiter(exports.DEFAULT_RATE_LIMITS[endpointType]); } //# sourceMappingURL=rateLimiter.js.map