feat(backend): implement all missing endpoints, real analytics queries, and WebSocket server
- Replace stub analytics.repository.ts with real PostgreSQL queries using pg.Pool - Add /api/guilds, /api/config, /api/auth/login, /api/ui-state (GET/POST) - Add /api/review, /api/recordings, /api/analysis/search - Add /api/messages/:id/reanalyze endpoint - Add /api/analytics/heatmap and /api/analytics/topics - Implement media routes (stub responses, backend has no Discord voice client) - Add WebSocket server at /ws with heartbeat and broadcast functions - Fix analytics route paths to match frontend contract (dual paths for backward compat) - Export getPool() from database module for raw SQL queries - Register all new routers in app.ts Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5a094c926a
commit
9b41eb9c12
@@ -33,28 +33,63 @@ export class AnalyticsService {
|
||||
return analyticsRepository.getDailyTrend(guildId, hours);
|
||||
}
|
||||
|
||||
async getHourlyStats(guildId: string, hours = 24) {
|
||||
async getHourlyStats(guildId: string, channelId?: string, hours = 24) {
|
||||
this.assertMonitorGuild(guildId);
|
||||
logger.debug({ guildId, hours }, "Getting hourly stats");
|
||||
return analyticsRepository.getHourlyStats(guildId, hours);
|
||||
logger.debug({ guildId, channelId, hours }, "Getting hourly stats");
|
||||
return analyticsRepository.getHourlyStats(guildId, channelId, hours);
|
||||
}
|
||||
|
||||
async getTopViolators(guildId: string, limit = 10) {
|
||||
async getTopViolators(
|
||||
guildId: string,
|
||||
channelId?: string,
|
||||
hours = 24,
|
||||
limit = 10,
|
||||
) {
|
||||
this.assertMonitorGuild(guildId);
|
||||
logger.debug({ guildId, limit }, "Getting top violators");
|
||||
return analyticsRepository.getTopViolators(guildId, limit);
|
||||
logger.debug({ guildId, channelId, hours, limit }, "Getting top violators");
|
||||
return analyticsRepository.getTopViolators(
|
||||
guildId,
|
||||
channelId,
|
||||
hours,
|
||||
limit,
|
||||
);
|
||||
}
|
||||
|
||||
async getUserLeaderboard(guildId: string, limit = 10) {
|
||||
async getUserLeaderboard(
|
||||
guildId: string,
|
||||
channelId?: string,
|
||||
hours = 24,
|
||||
limit = 10,
|
||||
) {
|
||||
this.assertMonitorGuild(guildId);
|
||||
logger.debug({ guildId, limit }, "Getting user leaderboard");
|
||||
return analyticsRepository.getUserLeaderboard(guildId, limit);
|
||||
logger.debug(
|
||||
{ guildId, channelId, hours, limit },
|
||||
"Getting user leaderboard",
|
||||
);
|
||||
return analyticsRepository.getUserLeaderboard(
|
||||
guildId,
|
||||
channelId,
|
||||
hours,
|
||||
limit,
|
||||
);
|
||||
}
|
||||
|
||||
async getModerationStats(guildId: string) {
|
||||
async getModerationStats(guildId: string, channelId?: string, hours = 24) {
|
||||
this.assertMonitorGuild(guildId);
|
||||
logger.debug({ guildId }, "Getting moderation stats");
|
||||
return analyticsRepository.getModerationStats(guildId);
|
||||
logger.debug({ guildId, channelId, hours }, "Getting moderation stats");
|
||||
return analyticsRepository.getModerationStats(guildId, channelId, hours);
|
||||
}
|
||||
|
||||
async getHeatmap(guildId: string, channelId?: string, hours = 24) {
|
||||
this.assertMonitorGuild(guildId);
|
||||
logger.debug({ guildId, channelId, hours }, "Getting heatmap");
|
||||
return analyticsRepository.getHeatmap(guildId, channelId, hours);
|
||||
}
|
||||
|
||||
async getTopics(guildId: string, channelId?: string, hours = 24) {
|
||||
this.assertMonitorGuild(guildId);
|
||||
logger.debug({ guildId, channelId, hours }, "Getting topics");
|
||||
return analyticsRepository.getTopics(guildId, channelId, hours);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user