A powerful and extendable Discord bot, with it's own module system :3
thevoid.cafe/projects/voidy
1import { WebhookClient } from "discord.js";
2import { Notification } from "../../../notifications/types";
3import { ChatbotChannel } from "../schemas/ChatbotChannel";
4import { ChatbotRepository, type IChatbotProfile, type IChatbotMessage } from "../schemas/ChatbotRepository";
5
6function processTemplate(content: string): string {
7 return content.replace(/<age>/g, String(Math.floor(Math.random() * 12) + 1));
8}
9
10function pickRandom<T>(arr: T[]): T | undefined {
11 if (arr.length === 0) return undefined;
12 return arr[Math.floor(Math.random() * arr.length)];
13}
14
15function getMessageForProfile(
16 profile: IChatbotProfile,
17 globalMessages: IChatbotMessage[],
18): string | undefined {
19 if (profile.onlySendSpecified) {
20 const msg = pickRandom(profile.messages);
21 return msg?.content;
22 }
23 const msg = pickRandom(globalMessages);
24 return msg?.content;
25}
26
27export default new Notification({
28 id: "chatbot",
29
30 execute: async ({ data }) => {
31 const channelId = data.channelId as string;
32
33 const channelConfig = await ChatbotChannel.findOne({ channelId, enabled: true });
34 if (!channelConfig) return;
35
36 // Resolve repository based on mode
37 let repository;
38 if (channelConfig.mode === "local" && channelConfig.repositoryId) {
39 repository = await ChatbotRepository.findById(channelConfig.repositoryId);
40 } else {
41 repository = await ChatbotRepository.findOne({ scope: "global" });
42 }
43
44 if (!repository || repository.messages.length === 0 || repository.profiles.length === 0) return;
45
46 const profile = pickRandom(repository.profiles);
47 if (!profile) return;
48
49 const content = getMessageForProfile(profile, repository.messages);
50 if (!content) return;
51
52 const webhook = new WebhookClient({
53 id: channelConfig.webhookId,
54 token: channelConfig.webhookToken,
55 });
56
57 try {
58 await webhook.send({
59 content: processTemplate(content),
60 username: profile.name,
61 avatarURL: profile.avatarURL,
62 });
63
64 await ChatbotChannel.updateOne(
65 { channelId },
66 { $set: { lastSentAt: new Date() } },
67 );
68 } finally {
69 webhook.destroy();
70 }
71 },
72});