mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
Add files via upload
This commit is contained in:
117
src/utils/rateLimit.ts
Normal file
117
src/utils/rateLimit.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* Client-side rate limiting utilities to prevent spam requests
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface RateLimitEntry {
|
||||||
|
count: number
|
||||||
|
resetTime: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const rateLimitStore = new Map<string, RateLimitEntry>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if action is rate limited
|
||||||
|
* @param key Unique key for the action (e.g., 'payment', 'ticket-create')
|
||||||
|
* @param maxRequests Maximum requests allowed in the time window
|
||||||
|
* @param windowMs Time window in milliseconds
|
||||||
|
* @returns true if action is allowed, false if rate limited
|
||||||
|
*/
|
||||||
|
export function checkRateLimit(
|
||||||
|
key: string,
|
||||||
|
maxRequests: number = 3,
|
||||||
|
windowMs: number = 10000
|
||||||
|
): boolean {
|
||||||
|
const now = Date.now()
|
||||||
|
const entry = rateLimitStore.get(key)
|
||||||
|
|
||||||
|
// Clean up expired entry
|
||||||
|
if (entry && now >= entry.resetTime) {
|
||||||
|
rateLimitStore.delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentEntry = rateLimitStore.get(key)
|
||||||
|
|
||||||
|
if (!currentEntry) {
|
||||||
|
// First request - allow and start tracking
|
||||||
|
rateLimitStore.set(key, {
|
||||||
|
count: 1,
|
||||||
|
resetTime: now + windowMs,
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentEntry.count >= maxRequests) {
|
||||||
|
// Rate limit exceeded
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment counter and allow
|
||||||
|
currentEntry.count++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get remaining time until rate limit resets (in seconds)
|
||||||
|
*/
|
||||||
|
export function getRateLimitResetTime(key: string): number {
|
||||||
|
const entry = rateLimitStore.get(key)
|
||||||
|
if (!entry) return 0
|
||||||
|
const remaining = entry.resetTime - Date.now()
|
||||||
|
return remaining > 0 ? Math.ceil(remaining / 1000) : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset rate limit for a key (e.g., after successful action)
|
||||||
|
*/
|
||||||
|
export function resetRateLimit(key: string): void {
|
||||||
|
rateLimitStore.delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debounce function - delays execution until after wait ms have elapsed
|
||||||
|
*/
|
||||||
|
export function debounce<T extends (...args: unknown[]) => unknown>(
|
||||||
|
func: T,
|
||||||
|
wait: number
|
||||||
|
): (...args: Parameters<T>) => void {
|
||||||
|
let timeoutId: ReturnType<typeof setTimeout> | null = null
|
||||||
|
|
||||||
|
return (...args: Parameters<T>) => {
|
||||||
|
if (timeoutId) {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
}
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
func(...args)
|
||||||
|
timeoutId = null
|
||||||
|
}, wait)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throttle function - ensures function is called at most once per limit ms
|
||||||
|
*/
|
||||||
|
export function throttle<T extends (...args: unknown[]) => unknown>(
|
||||||
|
func: T,
|
||||||
|
limit: number
|
||||||
|
): (...args: Parameters<T>) => void {
|
||||||
|
let inThrottle = false
|
||||||
|
|
||||||
|
return (...args: Parameters<T>) => {
|
||||||
|
if (!inThrottle) {
|
||||||
|
func(...args)
|
||||||
|
inThrottle = true
|
||||||
|
setTimeout(() => {
|
||||||
|
inThrottle = false
|
||||||
|
}, limit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rate limit keys for different actions
|
||||||
|
export const RATE_LIMIT_KEYS = {
|
||||||
|
PAYMENT: 'payment',
|
||||||
|
TICKET_CREATE: 'ticket-create',
|
||||||
|
TICKET_REPLY: 'ticket-reply',
|
||||||
|
PROMO_ACTIVATE: 'promo-activate',
|
||||||
|
WHEEL_SPIN: 'wheel-spin',
|
||||||
|
} as const
|
||||||
Reference in New Issue
Block a user