Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum OptionKey {
TAG_PREFIX
MAX_TAGS_PER_MESSAGE
DAYS_TO_KEEP_TAGS
DAYS_TO_KEEP_USER_BOT_MESSAGES
}

// Options for the bot, stored in the database.
Expand Down
2 changes: 2 additions & 0 deletions src/common/events/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { readyEvent } from '@/features/ready/index.js';
import type { DiscordEvent } from './types.js';
import archiveChannels from '@/features/archive-channels/index.js';
import { tagReceivedEvent } from '@/features/tags/tag-received.js';
import { reactionAddEvent } from '@/features/reactions/index.js';

export const events: DiscordEvent[] = [
readyEvent,
Expand All @@ -13,4 +14,5 @@ export const events: DiscordEvent[] = [
interactionCreateEvent,
archiveChannels,
tagReceivedEvent,
reactionAddEvent,
].flat();
38 changes: 38 additions & 0 deletions src/features/reactions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createEvent } from '@/common/events/create-event.js';
import {
Events,
MessageReaction,
PartialMessageReaction,
PartialUser,
User,
} from 'discord.js';
import { removeUserBotMessage } from './remove-user-bot-message.js';

export type ReactionAddEvent = {
reaction: MessageReaction | PartialMessageReaction;
user: User | PartialUser;
};

const handlers = [removeUserBotMessage];

export const reactionAddEvent = createEvent(
{
name: Events.MessageReactionAdd,
},
async (reaction, user, details) => {
if (user.bot) {
return;
}
try {
if (reaction.partial) {
await reaction.fetch();
}
} catch {
return;
}

for (const handler of handlers) {
await handler(reaction, user, details);
}
}
);
45 changes: 45 additions & 0 deletions src/features/reactions/remove-user-bot-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { ClientEvents, Events, GuildMember } from 'discord.js';
import { UserBotMessagesService } from '@/services/user-bot-messages/user-bot-messages-service.js';

const DELETE_EMOJIS = ['🗑️', '❌'];

export const removeUserBotMessage: (
...args: ClientEvents[Events.MessageReactionAdd]
) => Promise<void> | void = async (reaction, user) => {
if (
reaction.emoji.name === null ||
!DELETE_EMOJIS.includes(reaction.emoji.name)
) {
return;
}

if (reaction.message.author?.id !== user.client.user.id) {
return;
}

const guild = reaction.message.guild;
if (guild === null) {
return;
}

let member: GuildMember;
try {
member =
guild.members.cache.get(user.id) ?? (await guild.members.fetch(user.id));
} catch {
return;
}

try {
const deleted = await UserBotMessagesService.deleteUserBotMessage({
messageId: reaction.message.id,
user: member,
});

if (deleted) {
await reaction.message.delete();
}
} catch {
return;
}
};
Comment thread
hmd-ali marked this conversation as resolved.
3 changes: 3 additions & 0 deletions src/features/ready/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { fetchAndCachePublicChannelsMessages } from '@/util/cache.js';
import { syncGuidesToChannel } from '@/util/post-guides.js';
import { leaveIfNotAllowedServer } from '@/util/server-guard.js';
import { syncArchiveCategoryChannels } from '../archive-channels/util.js';
import { UserBotMessagesService } from '@/services/user-bot-messages/user-bot-messages-service.js';

export const readyEvent = createEvent(
{
Expand Down Expand Up @@ -71,5 +72,7 @@ export const readyEvent = createEvent(
error
);
}

void UserBotMessagesService.startExpiredMessageCleanup();
}
);
5 changes: 5 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const OptionsDefaults = {
type: 'number',
displayName: 'Days to Keep Tags',
},
[OptionKey.DAYS_TO_KEEP_USER_BOT_MESSAGES]: {
value: '7',
type: 'number',
displayName: 'Days to Keep User Bot Messages',
},
} as const satisfies Record<OptionKey, OptionValue>;

export type OptionTypeOf<K extends OptionKey> =
Expand Down
9 changes: 6 additions & 3 deletions src/services/user-bot-messages/user-bot-messages-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { GuildMember } from 'discord.js';
import { prisma } from '@/db/prisma.js';
import { isStaff } from '@/util/permissions.js';
import { DAY } from '@/constants/time.js';

const CLEANUP_INTERVAL_MS = 60 * 60 * 1000; // every hour
import { getBotOption } from '@/options.js';
import { OptionKey } from '@/generated/prisma/enums.js';

export const UserBotMessagesService = {
async deleteUserBotMessage({
Expand Down Expand Up @@ -65,6 +65,9 @@ export const UserBotMessagesService = {
};

void cleanup();
setInterval(cleanup, CLEANUP_INTERVAL_MS);
const daysToKeep = getBotOption(
OptionKey.DAYS_TO_KEEP_USER_BOT_MESSAGES
).value;
setInterval(cleanup, daysToKeep * DAY);
},
};
Loading