import { createClient } from "redis"; import { isProductionEnvironment } from "@/lib/constants"; import { ChatbotError } from "@/lib/errors"; const MAX_MESSAGES = 10; const TTL_SECONDS = 60 * 60; let client: ReturnType | null = null; function getClient() { if (!client && process.env.REDIS_URL) { client = createClient({ url: process.env.REDIS_URL }); client.on("error", () => undefined); client.connect().catch(() => { client = null; }); } return client; } export async function checkIpRateLimit(ip: string | undefined) { if (!isProductionEnvironment || !ip) { return; } const redis = getClient(); if (!redis?.isReady) { return; } try { const key = `ip-rate-limit:${ip}`; const [count] = await redis .multi() .incr(key) .expire(key, TTL_SECONDS, "NX") .exec(); if (typeof count === "number" && count > MAX_MESSAGES) { throw new ChatbotError("rate_limit:chat"); } } catch (error) { if (error instanceof ChatbotError) { throw error; } } }