From decfb8fb61e8ba97319202f62681a7fbaa166305 Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Tue, 2 Jun 2026 22:49:15 +0700 Subject: [PATCH] [CommandCode error: {"type":"server_error","message":"Service temporarily unavailable. Please try again shortly.","statusCode":503,"isRetryable":true}] --- .../modules/ai-moderation/textCacheStore.ts | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/services/discord-gateway/src/modules/ai-moderation/textCacheStore.ts b/services/discord-gateway/src/modules/ai-moderation/textCacheStore.ts index 78b7bf5..616add7 100644 --- a/services/discord-gateway/src/modules/ai-moderation/textCacheStore.ts +++ b/services/discord-gateway/src/modules/ai-moderation/textCacheStore.ts @@ -239,3 +239,57 @@ export async function upsertCachedMediaAnalysis( ); } } + +// --------------------------------------------------------------------------- +// Perceptual hash helpers for image deduplication +// --------------------------------------------------------------------------- + +/** + * Generate a deterministic cache key for a perceptual hash. + * The phash value is a string like "a1b2c3d4e5f6..." from the imghash library. + */ +export function makePhashCacheKey(phash: string): string { + return `phash:${phash.slice(0, 16)}`; +} + +/** + * Look up a cached media analysis by perceptual hash. + * Returns the cached analysis string or null if not found/expired. + */ +export async function getCachedMediaByPhash( + phash: string, +): Promise { + const cacheKey = makePhashCacheKey(phash); + return getCachedMediaAnalysis(cacheKey); +} + +/** + * Store a media analysis result keyed by perceptual hash. + */ +export async function upsertCachedMediaByPhash( + phash: string, + analysisResult: string, + source: "vision_llm", + expiresAt: number, +): Promise { + const cacheKey = makePhashCacheKey(phash); + return upsertCachedMediaAnalysis(cacheKey, analysisResult, source, expiresAt); +} + +/** + * Compute perceptual hash from image buffer using imghash. + * Returns a hexadecimal string representation of the hash. + * Returns null if hashing fails (e.g., invalid image data). + */ +export async function computeImagePhash( + buffer: Buffer, +): Promise { + try { + // Dynamic import to avoid issues if imghash native bindings aren't available + const imghash = await import("imghash"); + const hash = await imghash.hash(buffer); + return hash; + } catch { + return null; + } +}