| 48 | } |
| 49 | |
| 50 | private checkRateLimit(userId: string, endpoint: string): boolean { |
| 51 | const key = `${userId}:${endpoint}`; |
| 52 | const now = Date.now(); |
| 53 | const limit = endpoint === "search" ? HubServer.RATE_LIMIT_SEARCH : HubServer.RATE_LIMIT_DEFAULT; |
| 54 | const bucket = this.rateBuckets.get(key); |
| 55 | if (!bucket || now - bucket.windowStart > HubServer.RATE_WINDOW_MS) { |
| 56 | this.rateBuckets.set(key, { count: 1, windowStart: now }); |
| 57 | return true; |
| 58 | } |
| 59 | bucket.count++; |
| 60 | return bucket.count <= limit; |
| 61 | } |
| 62 | |
| 63 | async start(): Promise<string> { |
| 64 | if (!this.teamToken) { |