fix: add error handling to analytics getTopics query and fix mascot tooltip positioning

This commit is contained in:
MythEclipse
2026-06-03 19:50:26 +07:00
parent 3c130bf813
commit 4e12394168
2 changed files with 57 additions and 52 deletions
@@ -315,11 +315,12 @@ export class AnalyticsRepository {
const pool = getPool(); const pool = getPool();
const filter = buildTimeFilter(guildId, channelId, hours); const filter = buildTimeFilter(guildId, channelId, hours);
try {
const { rows } = await pool.query( const { rows } = await pool.query(
` `
WITH word_list AS ( WITH word_list AS (
SELECT SELECT
LOWER(TRIM(BOTH '.,!?;:\"'()[]{}' FROM word)) AS word, LOWER(TRIM(BOTH '.,!?;:\"()[]{}' FROM word)) AS word,
ai_moderation_score ai_moderation_score
FROM messages, FROM messages,
LATERAL regexp_split_to_table(content, E'\\\\s+') AS word LATERAL regexp_split_to_table(content, E'\\\\s+') AS word
@@ -327,12 +328,9 @@ export class AnalyticsRepository {
AND content IS NOT NULL AND content IS NOT NULL
AND content != '' AND content != ''
AND LENGTH(TRIM(BOTH '.,!?;:\"()[]{}' FROM word)) >= 3 AND LENGTH(TRIM(BOTH '.,!?;:\"()[]{}' FROM word)) >= 3
-- Skip sticker & custom emoji (<:name:id> or <a:name:id>) AND word !~ '^<.+:\\d+>$'
AND word !~ '^<a?:.+:\\d+>$'
-- Skip URLs
AND word !~ '^https?://' AND word !~ '^https?://'
AND word !~ '^discord\\.(gg|app|com)' AND word !~ '^discord\\.(gg|app|com)'
-- Skip common Discord embed artifacts
AND word !~ '^cdn\\.discord' AND word !~ '^cdn\\.discord'
) )
SELECT SELECT
@@ -365,6 +363,13 @@ export class AnalyticsRepository {
count: Number(r.count ?? 0), count: Number(r.count ?? 0),
score: Number(r.score ?? 0), score: Number(r.score ?? 0),
})); }));
} catch (error) {
logger.error(
{ error: error instanceof Error ? error.message : String(error), guildId },
"getTopics query failed — returning empty",
);
return [];
}
} }
// ── New endpoints ───────────────────────────────────────────────────────── // ── New endpoints ─────────────────────────────────────────────────────────
+4 -4
View File
@@ -116,7 +116,7 @@ export function Sidebar({
initial={{ opacity: 0, x: -8, y: 6, scale: 0.96 }} initial={{ opacity: 0, x: -8, y: 6, scale: 0.96 }}
animate={{ opacity: 1, x: 0, y: 0, scale: 1 }} animate={{ opacity: 1, x: 0, y: 0, scale: 1 }}
transition={{ type: "spring", stiffness: 280, damping: 24 }} transition={{ type: "spring", stiffness: 280, damping: 24 }}
className="pointer-events-none absolute bottom-full left-1/2 z-[9999] mb-3 w-64 -translate-x-1/2" className="pointer-events-none fixed bottom-[100px] left-[72px] z-[9999] w-64"
> >
<div className="relative rounded-2xl border border-sky-200/80 bg-white/95 px-4 py-3 text-left shadow-xl shadow-sky-100/70 backdrop-blur-md"> <div className="relative rounded-2xl border border-sky-200/80 bg-white/95 px-4 py-3 text-left shadow-xl shadow-sky-100/70 backdrop-blur-md">
<p className="text-[11px] font-semibold uppercase tracking-wide text-primary/70"> <p className="text-[11px] font-semibold uppercase tracking-wide text-primary/70">
@@ -126,10 +126,10 @@ export function Sidebar({
Halo! Saya mascot mu. Klik aku kalau mau tanya soal obrolan Halo! Saya mascot mu. Klik aku kalau mau tanya soal obrolan
atau moderasi atau moderasi
</p> </p>
{/* Outer: border layer — triangle pointing down at center */} {/* Outer: border layer — triangle pointing left at center-right */}
<div className="absolute -bottom-[13px] left-1/2 z-10 h-[21px] w-[21px] -translate-x-1/2 bg-sky-200/80 [clip-path:polygon(0_0,100%_0,50%_100%)]" /> <div className="absolute -left-[13px] top-1/2 z-10 h-[21px] w-[21px] -translate-y-1/2 bg-sky-200/80 [clip-path:polygon(0_50%,100%_0,100%_100%)]" />
{/* Inner: fill layer — matches bubble bg */} {/* Inner: fill layer — matches bubble bg */}
<div className="absolute -bottom-3 left-1/2 z-20 h-5 w-5 -translate-x-1/2 bg-white/95 [clip-path:polygon(0_0,100%_0,50%_100%)]" /> <div className="absolute -left-3 top-1/2 z-20 h-5 w-5 -translate-y-1/2 bg-white/95 [clip-path:polygon(0_50%,100%_0,100%_100%)]" />
</div> </div>
</motion.div> </motion.div>
)} )}