summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/gateway/src/listeners/clientReady/index.ts2
-rw-r--r--packages/gateway/src/listeners/messageCreate/index.ts2
-rw-r--r--packages/gateway/src/listeners/messageStatistics.ts258
3 files changed, 262 insertions, 0 deletions
diff --git a/packages/gateway/src/listeners/clientReady/index.ts b/packages/gateway/src/listeners/clientReady/index.ts
index 8e7f81a..4e8fea7 100644
--- a/packages/gateway/src/listeners/clientReady/index.ts
+++ b/packages/gateway/src/listeners/clientReady/index.ts
@@ -2,11 +2,13 @@ import { Client, Events } from "discord.js";
import { handleVoiceConnection } from "./voiceConnection";
import { handleActivity } from "./activity";
import { handleUmagramCatchup } from "./umagramCatchup";
+import { initializeMessageStatistics } from "../messageStatistics";
export const handleClientReady = (client: Client) => {
client.once(Events.ClientReady, async (readyClient) => {
handleVoiceConnection(readyClient);
handleActivity(readyClient);
+ initializeMessageStatistics();
await handleUmagramCatchup(readyClient);
});
};
diff --git a/packages/gateway/src/listeners/messageCreate/index.ts b/packages/gateway/src/listeners/messageCreate/index.ts
index d736844..197d7c1 100644
--- a/packages/gateway/src/listeners/messageCreate/index.ts
+++ b/packages/gateway/src/listeners/messageCreate/index.ts
@@ -8,9 +8,11 @@ import { handleRoleMentionCooldown } from "./roleMentionCooldown";
import { handleAICommand } from "./aiCommandHandler";
import { handleRandomEyesReaction } from "./randomEyesReaction";
import { handleRoleplayThumbsUpReaction } from "./roleplayThumbsUpReaction";
+import { recordMessageForStatistics } from "../messageStatistics";
export const handleMessageCreate = (client: Client) => {
client.on(Events.MessageCreate, async (message: Message) => {
+ recordMessageForStatistics(message);
await handleRoleplayUmagram(message);
await handleRandomEyesReaction(message);
await handleRoleplayThumbsUpReaction(message);
diff --git a/packages/gateway/src/listeners/messageStatistics.ts b/packages/gateway/src/listeners/messageStatistics.ts
new file mode 100644
index 0000000..27e4278
--- /dev/null
+++ b/packages/gateway/src/listeners/messageStatistics.ts
@@ -0,0 +1,258 @@
+import { Message } from "discord.js";
+import { CENTRAL_GUILD_ID, ROLEPLAY_GUILD_ID } from "../constants";
+
+interface MessageStats {
+ totalMessages: number;
+ totalLength: number;
+ hourlyMessages: Map<number, number>;
+ dailyMessages: Map<string, number>;
+ hourlyChannels: Map<number, Map<string, number>>;
+ dailyChannels: Map<string, Map<string, number>>;
+ startTime: number;
+}
+
+interface GuildStats {
+ [guildId: string]: MessageStats;
+}
+
+class MessageStatisticsTracker {
+ private stats: GuildStats = {
+ [CENTRAL_GUILD_ID]: {
+ totalMessages: 0,
+ totalLength: 0,
+ hourlyMessages: new Map(),
+ dailyMessages: new Map(),
+ hourlyChannels: new Map(),
+ dailyChannels: new Map(),
+ startTime: Date.now(),
+ },
+ [ROLEPLAY_GUILD_ID]: {
+ totalMessages: 0,
+ totalLength: 0,
+ hourlyMessages: new Map(),
+ dailyMessages: new Map(),
+ hourlyChannels: new Map(),
+ dailyChannels: new Map(),
+ startTime: Date.now(),
+ },
+ };
+
+ private logInterval: ReturnType<typeof setTimeout> | null = null;
+
+ constructor() {
+ this.initializeLogging();
+ }
+
+ public recordMessage(message: Message): void {
+ if (!message.content || message.author.bot || !message.guildId) return;
+
+ if (!this.stats[message.guildId]) return;
+
+ const now = new Date();
+ const hour = now.getHours();
+ const date = now.toISOString().split("T")[0];
+ const channelId = message.channelId;
+ const guildStats = this.stats[message.guildId];
+
+ guildStats.totalMessages += 1;
+ guildStats.totalLength += message.content.length;
+
+ const currentHourCount = guildStats.hourlyMessages.get(hour) || 0;
+
+ guildStats.hourlyMessages.set(hour, currentHourCount + 1);
+
+ const currentDayCount = guildStats.dailyMessages.get(date) || 0;
+
+ guildStats.dailyMessages.set(date, currentDayCount + 1);
+
+ if (!guildStats.hourlyChannels.has(hour))
+ guildStats.hourlyChannels.set(hour, new Map());
+
+ const hourlyChannelMap = guildStats.hourlyChannels.get(hour)!;
+ const currentHourlyChannelCount = hourlyChannelMap.get(channelId) || 0;
+
+ hourlyChannelMap.set(channelId, currentHourlyChannelCount + 1);
+
+ if (!guildStats.dailyChannels.has(date))
+ guildStats.dailyChannels.set(date, new Map());
+
+ const dailyChannelMap = guildStats.dailyChannels.get(date)!;
+ const currentDailyChannelCount = dailyChannelMap.get(channelId) || 0;
+
+ dailyChannelMap.set(channelId, currentDailyChannelCount + 1);
+ }
+
+ private calculateAverages(guildId: string): {
+ averageMessagesPerHour: number;
+ averageMessagesPerDay: number;
+ averageMessageLength: number;
+ } {
+ const guildStats = this.stats[guildId];
+ const uptimeHours = (Date.now() - guildStats.startTime) / (1000 * 60 * 60);
+ const uptimeDays = uptimeHours / 24;
+ const averageMessagesPerHour =
+ guildStats.totalMessages / Math.max(uptimeHours, 1);
+ const averageMessagesPerDay =
+ guildStats.totalMessages / Math.max(uptimeDays, 1);
+ const averageMessageLength =
+ guildStats.totalMessages > 0
+ ? guildStats.totalLength / guildStats.totalMessages
+ : 0;
+
+ return {
+ averageMessagesPerHour,
+ averageMessagesPerDay,
+ averageMessageLength,
+ };
+ }
+
+ private getTopChannels(guildId: string): {
+ topHourlyChannels: Array<{ channelId: string; count: number }>;
+ topDailyChannels: Array<{ channelId: string; count: number }>;
+ } {
+ const guildStats = this.stats[guildId];
+ const now = new Date();
+ const currentHour = now.getHours();
+ const currentDate = now.toISOString().split("T")[0];
+ const currentHourChannels =
+ guildStats.hourlyChannels.get(currentHour) || new Map();
+ const topHourlyChannels = Array.from(currentHourChannels.entries())
+ .map(([channelId, count]) => ({ channelId, count }))
+ .sort((a, b) => b.count - a.count)
+ .slice(0, 5);
+ const currentDayChannels =
+ guildStats.dailyChannels.get(currentDate) || new Map();
+ const topDailyChannels = Array.from(currentDayChannels.entries())
+ .map(([channelId, count]) => ({ channelId, count }))
+ .sort((a, b) => b.count - a.count)
+ .slice(0, 5);
+
+ return {
+ topHourlyChannels,
+ topDailyChannels,
+ };
+ }
+
+ private logStatistics(): void {
+ const date = new Date();
+
+ console.log(`Message Statistics Report (${date.toString()}):\n`);
+
+ const centralAverages = this.calculateAverages(CENTRAL_GUILD_ID);
+ const centralStats = this.stats[CENTRAL_GUILD_ID];
+ const centralTopChannels = this.getTopChannels(CENTRAL_GUILD_ID);
+
+ console.log(`Central Guild:`);
+ console.log(` Total Messages: ${centralStats.totalMessages}`);
+ console.log(
+ ` Average Messages per Hour: ${centralAverages.averageMessagesPerHour.toFixed(2)}`,
+ );
+ console.log(
+ ` Average Messages per Day: ${centralAverages.averageMessagesPerDay.toFixed(2)}`,
+ );
+ console.log(
+ ` Average Message Length: ${centralAverages.averageMessageLength.toFixed(2)} characters`,
+ );
+ console.log(
+ ` Uptime: ${((Date.now() - centralStats.startTime) / (1000 * 60 * 60)).toFixed(2)} hours`,
+ );
+
+ if (centralTopChannels.topHourlyChannels.length > 0) {
+ console.log(` Top 5 Channels (This Hour):`);
+ centralTopChannels.topHourlyChannels.forEach((channel, index) => {
+ console.log(
+ ` ${index + 1}. <#${channel.channelId}>: ${channel.count} messages`,
+ );
+ });
+ }
+
+ if (centralTopChannels.topDailyChannels.length > 0) {
+ console.log(` Top 5 Channels (Today):`);
+ centralTopChannels.topDailyChannels.forEach((channel, index) => {
+ console.log(
+ ` ${index + 1}. <#${channel.channelId}>: ${channel.count} messages`,
+ );
+ });
+ }
+
+ console.log();
+
+ const roleplayAverages = this.calculateAverages(ROLEPLAY_GUILD_ID);
+ const roleplayStats = this.stats[ROLEPLAY_GUILD_ID];
+ const roleplayTopChannels = this.getTopChannels(ROLEPLAY_GUILD_ID);
+
+ console.log(`Roleplay Guild:`);
+ console.log(` Total Messages: ${roleplayStats.totalMessages}`);
+ console.log(
+ ` Average Messages per Hour: ${roleplayAverages.averageMessagesPerHour.toFixed(2)}`,
+ );
+ console.log(
+ ` Average Messages per Day: ${roleplayAverages.averageMessagesPerDay.toFixed(2)}`,
+ );
+ console.log(
+ ` Average Message Length: ${roleplayAverages.averageMessageLength.toFixed(2)} characters`,
+ );
+ console.log(
+ ` Uptime: ${((Date.now() - roleplayStats.startTime) / (1000 * 60 * 60)).toFixed(2)} hours`,
+ );
+
+ if (roleplayTopChannels.topHourlyChannels.length > 0) {
+ console.log(` Top 5 Channels (This Hour):`);
+ roleplayTopChannels.topHourlyChannels.forEach((channel, index) => {
+ console.log(
+ ` ${index + 1}. <#${channel.channelId}>: ${channel.count} messages`,
+ );
+ });
+ }
+
+ if (roleplayTopChannels.topDailyChannels.length > 0) {
+ console.log(` Top 5 Channels (Today):`);
+ roleplayTopChannels.topDailyChannels.forEach((channel, index) => {
+ console.log(
+ ` ${index + 1}. <#${channel.channelId}>: ${channel.count} messages`,
+ );
+ });
+ }
+
+ console.log();
+ }
+
+ private initializeLogging(): void {
+ this.logStatistics();
+
+ this.logInterval = setInterval(
+ () => {
+ this.logStatistics();
+ },
+ 12 * 60 * 60 * 1000,
+ );
+ }
+
+ public destroy(): void {
+ if (this.logInterval) {
+ clearInterval(this.logInterval);
+
+ this.logInterval = null;
+ }
+ }
+}
+
+let tracker: MessageStatisticsTracker | null = null;
+
+export const initializeMessageStatistics = (): void => {
+ if (tracker) tracker.destroy();
+
+ tracker = new MessageStatisticsTracker();
+};
+
+export const recordMessageForStatistics = (message: Message): void => {
+ if (tracker) tracker.recordMessage(message);
+};
+
+export const destroyMessageStatistics = (): void => {
+ if (tracker) {
+ tracker.destroy();
+
+ tracker = null;
+ }
+};