poixpixel-discord-bot/src/events/messageEvents.ts
Ahmad 2f5c3499e7
feat: add achievement system
Signed-off-by: Ahmad <103906421+ahmadk953@users.noreply.github.com>
2025-04-16 16:52:44 -04:00

165 lines
5.2 KiB
TypeScript

import { AuditLogEvent, Events, Message, PartialMessage } from 'discord.js';
import { Event } from '@/types/EventTypes.js';
import { loadConfig } from '@/util/configLoader.js';
import {
addCountingReactions,
processCountingMessage,
resetCounting,
} from '@/util/countingManager.js';
import logAction from '@/util/logging/logAction.js';
import {
checkAndAssignLevelRoles,
processMessage,
} from '@/util/levelingSystem.js';
import { processLevelUpAchievements } from '@/util/achievementManager.js';
export const messageDelete: Event<typeof Events.MessageDelete> = {
name: Events.MessageDelete,
execute: async (
message: Omit<Partial<Message<boolean> | PartialMessage>, 'channel'>,
) => {
try {
if (!message.guild || message.author?.bot) return;
const { guild } = message;
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.MessageDelete,
limit: 1,
});
const executor = auditLogs.entries.first()?.executor;
const moderator = executor
? await guild.members.fetch(executor.id)
: undefined;
await logAction({
guild,
action: 'messageDelete',
message: message as Message<true>,
moderator,
});
} catch (error) {
console.error('Error handling message delete:', error);
}
},
};
export const messageUpdate: Event<typeof Events.MessageUpdate> = {
name: Events.MessageUpdate,
execute: async (
oldMessage: Omit<Partial<Message<boolean> | PartialMessage>, 'channel'>,
newMessage: Message,
) => {
try {
if (
!oldMessage.guild ||
oldMessage.author?.bot ||
oldMessage.content === newMessage.content
) {
return;
}
await logAction({
guild: oldMessage.guild,
action: 'messageEdit',
message: newMessage as Message<true>,
oldContent: oldMessage.content ?? '',
newContent: newMessage.content ?? '',
});
} catch (error) {
console.error('Error handling message update:', error);
}
},
};
export const messageCreate: Event<typeof Events.MessageCreate> = {
name: Events.MessageCreate,
execute: async (message: Message) => {
try {
if (message.author.bot || !message.guild) return;
const levelResult = await processMessage(message);
const advancementsChannelId = loadConfig().channels.advancements;
const advancementsChannel = message.guild?.channels.cache.get(
advancementsChannelId,
);
if (!advancementsChannel?.isTextBased()) {
console.error(
'Advancements channel not found or is not a text channel',
);
return;
}
if (levelResult?.leveledUp) {
await advancementsChannel.send(
`🎉 Congratulations <@${message.author.id}>! You've leveled up to **Level ${levelResult.newLevel}**!`,
);
const assignedRole = await checkAndAssignLevelRoles(
message.guild,
message.author.id,
levelResult.newLevel,
);
await processLevelUpAchievements(
message.author.id,
levelResult.newLevel,
message.guild,
);
if (assignedRole) {
await advancementsChannel.send(
`<@${message.author.id}> You've earned the <@&${assignedRole}> role!`,
);
}
}
const countingChannelId = loadConfig().channels.counting;
const countingChannel =
message.guild?.channels.cache.get(countingChannelId);
if (!countingChannel || message.channel.id !== countingChannelId) return;
if (!countingChannel.isTextBased()) {
console.error('Counting channel not found or is not a text channel');
return;
}
const result = await processCountingMessage(message);
if (result.isValid) {
await addCountingReactions(message, result.milestoneType || 'normal');
} else {
let errorMessage: string;
switch (result.reason) {
case 'not_a_number':
errorMessage = `${message.author}, that's not a valid number! The count has been reset. The next number should be **1**.`;
break;
case 'too_high':
errorMessage = `${message.author}, too high! The count was **${(result?.expectedCount ?? 0) - 1}** and the next number should have been **${result.expectedCount}**. The count has been reset.`;
break;
case 'too_low':
errorMessage = `${message.author}, too low! The count was **${(result?.expectedCount ?? 0) - 1}** and the next number should have been **${result.expectedCount}**. The count has been reset.`;
break;
case 'same_user':
errorMessage = `${message.author}, you can't count twice in a row! The count has been reset. The next number should be **1**.`;
break;
default:
errorMessage = `${message.author}, something went wrong with the count. The count has been reset. The next number should be **1**.`;
}
await resetCounting();
await countingChannel.send(errorMessage);
await message.react('❌');
}
} catch (error) {
console.error('Error handling message create: ', error);
}
},
};
export default [messageCreate, messageDelete, messageUpdate];