diff options
| author | Fuwn <[email protected]> | 2025-10-09 14:33:14 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-10-09 14:33:14 -0700 |
| commit | 65c67c9769e8e7efa31fdefddfd6904d3c195d98 (patch) | |
| tree | 2ff1802a1372833912ad99d1b19e1a84eff5392e | |
| parent | feat(gateway:constants): Add Uma personas (diff) | |
| download | umabotdiscord-65c67c9769e8e7efa31fdefddfd6904d3c195d98.tar.xz umabotdiscord-65c67c9769e8e7efa31fdefddfd6904d3c195d98.zip | |
feat(gateway:listeners): Add uma persona reminder system
3 files changed, 174 insertions, 0 deletions
diff --git a/packages/gateway/src/listeners/clientReady/index.ts b/packages/gateway/src/listeners/clientReady/index.ts index 4e8fea7..42fad20 100644 --- a/packages/gateway/src/listeners/clientReady/index.ts +++ b/packages/gateway/src/listeners/clientReady/index.ts @@ -3,12 +3,14 @@ import { handleVoiceConnection } from "./voiceConnection"; import { handleActivity } from "./activity"; import { handleUmagramCatchup } from "./umagramCatchup"; import { initializeMessageStatistics } from "../messageStatistics"; +import { initializePersonaSystem } from "../messageCreate/personaRandomMessage"; export const handleClientReady = (client: Client) => { client.once(Events.ClientReady, async (readyClient) => { handleVoiceConnection(readyClient); handleActivity(readyClient); initializeMessageStatistics(); + initializePersonaSystem(readyClient); await handleUmagramCatchup(readyClient); }); }; diff --git a/packages/gateway/src/listeners/messageCreate/index.ts b/packages/gateway/src/listeners/messageCreate/index.ts index 926fda9..e0f497b 100644 --- a/packages/gateway/src/listeners/messageCreate/index.ts +++ b/packages/gateway/src/listeners/messageCreate/index.ts @@ -10,6 +10,7 @@ import { handleRandomEyesReaction } from "./randomEyesReaction"; import { handleRoleplayThumbsUpReaction } from "./roleplayThumbsUpReaction"; // import { handleBotMentionAutoDelete } from "./botMentionAutoDelete"; import { recordMessageForStatistics } from "../messageStatistics"; +import { handlePersonaRandomMessage } from "./personaRandomMessage"; export const handleMessageCreate = (client: Client) => { client.on(Events.MessageCreate, async (message: Message) => { @@ -17,6 +18,7 @@ export const handleMessageCreate = (client: Client) => { await handleRoleplayUmagram(message); await handleRandomEyesReaction(message); await handleRoleplayThumbsUpReaction(message); + await handlePersonaRandomMessage(message); // handleBotMentionAutoDelete(message); if (message.guildId !== CENTRAL_GUILD_ID) return; diff --git a/packages/gateway/src/listeners/messageCreate/personaRandomMessage.ts b/packages/gateway/src/listeners/messageCreate/personaRandomMessage.ts new file mode 100644 index 0000000..e27ee9e --- /dev/null +++ b/packages/gateway/src/listeners/messageCreate/personaRandomMessage.ts @@ -0,0 +1,170 @@ +import { Message, WebhookClient, Client } from "discord.js"; +import { UMA_PERSONAS } from "../../constants"; + +const TARGET_CHANNEL_ID = "1410333697701314791"; +const MESSAGE_THRESHOLD = 250; +const PERSONA_MESSAGES = [ + "Hi, everyone! {username} here! I want to make sure everyone knows that this channel is for NSFW content **only**! I really don't want to have to get rid of this channel for good ....", + "Hey there! It's {username}! Just a friendly reminder: this channel is strictly for NSFW content. Please keep it that way, or I might have to remove this channel permanently ....", + "Hello everyone! {username} speaking! This channel is meant for NSFW content exclusively. I'd hate to see this channel disappear because of rule violations ....", + "Hi all! {username} here with an important reminder! This channel is for NSFW content **only**! Let's keep it that way, or I'll have no choice but to remove this channel ....", + "Hey! {username} checking in! Just wanted to remind everyone that this channel is strictly for NSFW content. I really don't want to have to delete this channel ....", + "Hello! It's {username}! Please remember that this channel is for NSFW content only. I'd prefer not to have to permanently get rid of this channel ....", + "Hi everyone! {username} here! This channel is exclusively for NSFW content. Keep it clean, or I might have to remove this channel for good ....", + "Hey there! {username} speaking! Just a quick reminder that this channel is for NSFW content **only**! I don't want to have to delete this channel ....", + "Hello all! {username} here! This channel is strictly for NSFW content only. Please respect that, or I'll have no choice but to remove this channel ....", + "Hi! {username} checking in! Remember, this channel is for NSFW content exclusively. I really don't want to have to get rid of this channel permanently ....", +]; + +interface PersonaMessageTracker { + messageCount: number; + lastRandomMessageTime: number; + isActive: boolean; +} + +class PersonaRandomMessageSystem { + private tracker: PersonaMessageTracker = { + messageCount: 0, + lastRandomMessageTime: 0, + isActive: false, + }; + private webhookClient: WebhookClient | null = null; + private client: Client | null = null; + + constructor() { + // + } + + public setClient(client: Client) { + this.client = client; + + this.sendPrimerMessage(); + } + + private async initializeWebhook() { + if (!this.client) return; + + try { + const channel = this.client.channels.cache.get(TARGET_CHANNEL_ID); + + if (channel && "createWebhook" in channel) { + const webhook = await channel.createWebhook({ + name: "Uma Persona", + avatar: UMA_PERSONAS[0].avatar, + }); + + this.webhookClient = new WebhookClient({ url: webhook.url }); + } + } catch (error) { + console.error("Failed to create persona webhook:", error); + } + } + + private async sendPrimerMessage() { + try { + await this.initializeWebhook(); + + if (!this.webhookClient) { + console.error("Failed to create webhook for primer message"); + + return; + } + + const randomPersona = + UMA_PERSONAS[Math.floor(Math.random() * UMA_PERSONAS.length)]; + const randomMessage = + PERSONA_MESSAGES[Math.floor(Math.random() * PERSONA_MESSAGES.length)]; + const formattedMessage = randomMessage.replace( + "{username}", + randomPersona.name, + ); + + await this.webhookClient.edit({ + name: randomPersona.name, + avatar: randomPersona.avatar, + }); + await this.webhookClient.send(formattedMessage); + } catch (error) { + console.error("Failed to send primer persona message:", error); + } + } + + public async handleMessage(message: Message): Promise<void> { + if (!this.client) this.setClient(message.client); + + if (message.channelId !== TARGET_CHANNEL_ID) return; + + if (message.author.bot) return; + + if (!this.webhookClient) await this.initializeWebhook(); + + this.tracker.messageCount++; + + const now = Date.now(); + const timeSinceLastMessage = now - this.tracker.lastRandomMessageTime; + const isChannelActive = timeSinceLastMessage < 5 * 60 * 1000; + + if ( + this.tracker.messageCount >= MESSAGE_THRESHOLD && + isChannelActive && + this.webhookClient + ) + await this.sendRandomPersonaMessage(message); + } + + private async sendRandomPersonaMessage( + triggerMessage: Message /* eslint-disable-line @typescript-eslint/no-unused-vars, no-unused-vars */, + ): Promise<void> { + try { + const randomPersona = + UMA_PERSONAS[Math.floor(Math.random() * UMA_PERSONAS.length)]; + const randomMessage = + PERSONA_MESSAGES[Math.floor(Math.random() * PERSONA_MESSAGES.length)]; + const formattedMessage = randomMessage.replace( + "{username}", + randomPersona.name, + ); + + if (this.webhookClient) + await this.webhookClient.edit({ + name: randomPersona.name, + avatar: randomPersona.avatar, + }); + + await this.webhookClient?.send(formattedMessage); + + this.tracker.messageCount = 0; + this.tracker.lastRandomMessageTime = Date.now(); + } catch (error) { + console.error("Failed to send persona message:", error); + } + } + + public destroy(): void { + this.webhookClient?.destroy(); + } +} + +let personaSystem: PersonaRandomMessageSystem | null = null; + +export const initializePersonaSystem = (client?: Client): void => { + if (!personaSystem) { + personaSystem = new PersonaRandomMessageSystem(); + + if (client) personaSystem.setClient(client); + } +}; + +export const handlePersonaRandomMessage = async ( + message: Message, +): Promise<void> => { + if (personaSystem) await personaSystem.handleMessage(message); +}; + +export const destroyPersonaSystem = (): void => { + if (personaSystem) { + personaSystem.destroy(); + + personaSystem = null; + } +}; |