Files
wechat-radar/app/api/group/[id]/route.ts
T
2026-05-24 13:42:56 +08:00

83 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { NextRequest, NextResponse } from 'next/server';
import { todayStr } from '@/lib/range';
import { db } from '@/lib/db';
import { listMessagesForDate, getSyncState, listAllSyncedDates } from '@/lib/messages-store';
import { wxSessions } from '@/lib/wx';
export const dynamic = 'force-dynamic';
interface DailyHistoryRow {
date: string;
total: number;
}
export async function GET(
req: NextRequest,
ctx: { params: Promise<{ id: string }> },
) {
const { id } = await ctx.params;
const chatroomId = decodeURIComponent(id);
const url = new URL(req.url);
const date = url.searchParams.get('date') ?? todayStr();
const limit = Math.min(Number(url.searchParams.get('limit') ?? 1000), 5000);
// 拉群名(从 wx sessions
let chatName = chatroomId;
try {
const sessions = await wxSessions(500);
const found = sessions.find((s) => s.username === chatroomId);
if (found) chatName = found.chat;
} catch {}
// 当日消息
const messages = listMessagesForDate(chatroomId, date, limit);
// 当日聚合统计
const total = messages.length;
const senderMap = new Map<string, number>();
const typeMap = new Map<string, number>();
const hours = new Array(24).fill(0) as number[];
for (const m of messages) {
senderMap.set(m.sender, (senderMap.get(m.sender) ?? 0) + 1);
typeMap.set(m.type, (typeMap.get(m.type) ?? 0) + 1);
if (m.timestamp) {
const h = new Date(m.timestamp * 1000).getHours();
if (h >= 0 && h < 24) hours[h]++;
}
}
const stats = {
chat: chatName,
total,
by_hour: hours.map((count, hour) => ({ hour, count })),
by_type: Array.from(typeMap.entries())
.map(([type, count]) => ({ type, count }))
.sort((a, b) => b.count - a.count),
top_senders: Array.from(senderMap.entries())
.map(([sender, count]) => ({ sender, count }))
.sort((a, b) => b.count - a.count)
.slice(0, 20),
};
// 历史日柱图
const dailyHistory = db()
.prepare(
'SELECT date, total FROM daily_stats WHERE chatroom_id = ? ORDER BY date ASC',
)
.all(chatroomId) as DailyHistoryRow[];
// 同步状态
const syncState = getSyncState(chatroomId);
const syncedDates = listAllSyncedDates(chatroomId);
return NextResponse.json({
ok: true,
chatroom_id: chatroomId,
date,
stats,
recent: messages,
daily_history: dailyHistory,
sync_state: syncState ?? null,
synced_dates: syncedDates,
});
}