Added Warn and Ban Commands, Added Logging, and Much More

This commit is contained in:
Ahmad 2025-02-23 21:39:49 -05:00
parent d89de72e08
commit 86adac3f08
No known key found for this signature in database
GPG key ID: 8FD8A93530D182BF
33 changed files with 2200 additions and 204 deletions

View file

@ -0,0 +1,87 @@
import { AuditLogEvent, Events, GuildChannel } from 'discord.js';
import logAction from '../util/logging/logAction.js';
import { Event } from '../types/EventTypes.js';
export const channelCreate = {
name: Events.ChannelCreate,
execute: async (channel: GuildChannel) => {
try {
const { guild } = channel;
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.ChannelCreate,
limit: 1,
});
const executor = auditLogs.entries.first()?.executor;
const moderator = executor
? await guild.members.fetch(executor.id)
: undefined;
await logAction({
guild,
action: 'channelCreate',
channel,
moderator,
});
} catch (error) {
console.error('Error handling channel create:', error);
}
},
};
export const channelDelete = {
name: Events.ChannelDelete,
execute: async (channel: GuildChannel) => {
try {
const { guild } = channel;
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.ChannelDelete,
limit: 1,
});
const executor = auditLogs.entries.first()?.executor;
const moderator = executor
? await guild.members.fetch(executor.id)
: undefined;
await logAction({
guild,
action: 'channelDelete',
channel,
moderator,
});
} catch (error) {
console.error('Error handling channel delete:', error);
}
},
};
export const channelUpdate = {
name: Events.ChannelUpdate,
execute: async (oldChannel: GuildChannel, newChannel: GuildChannel) => {
try {
const { guild } = newChannel;
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.ChannelUpdate,
limit: 1,
});
const executor = auditLogs.entries.first()?.executor;
const moderator = executor
? await guild.members.fetch(executor.id)
: undefined;
await logAction({
guild,
action: 'channelUpdate',
channel: newChannel,
moderator,
oldName: oldChannel.name,
newName: newChannel.name,
oldPermissions: oldChannel.permissionOverwrites.cache.first()?.allow,
newPermissions: newChannel.permissionOverwrites.cache.first()?.allow,
});
} catch (error) {
console.error('Error handling channel update:', error);
}
},
};
export default [channelCreate, channelDelete, channelUpdate];

View file

@ -0,0 +1,38 @@
import { Events, Interaction } from 'discord.js';
import { ExtendedClient } from '../structures/ExtendedClient.js';
export default {
name: Events.InteractionCreate,
execute: async (interaction: Interaction) => {
if (!interaction.isCommand()) return;
const client = interaction.client as ExtendedClient;
const command = client.commands.get(interaction.commandName);
if (!command) {
console.error(
`No command matching ${interaction.commandName} was found.`,
);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({
content: 'There was an error while executing this command!',
flags: ['Ephemeral'],
});
} else {
await interaction.reply({
content: 'There was an error while executing this command!',
flags: ['Ephemeral'],
});
}
}
},
};

147
src/events/memberEvents.ts Normal file
View file

@ -0,0 +1,147 @@
import { Events, GuildMember } from 'discord.js';
import { updateMember, setMembers } from '../db/db.js';
import { generateMemberBanner } from '../util/helpers.js';
import { loadConfig } from '../util/configLoader.js';
import logAction from '../util/logging/logAction.js';
export const memberJoin = {
name: Events.GuildMemberAdd,
execute: async (member: GuildMember) => {
const { guild } = member;
const config = loadConfig();
const welcomeChannel = guild.channels.cache.get(config.channels.welcome);
if (!welcomeChannel?.isTextBased()) {
console.error('Welcome channel not found or is not a text channel');
return;
}
try {
const members = await guild.members.fetch();
const nonBotMembers = members.filter((m) => !m.user.bot);
await setMembers(nonBotMembers);
if (!member.user.bot) {
const attachment = await generateMemberBanner({
member,
width: 1024,
height: 450,
});
await Promise.all([
welcomeChannel.send({
content: `Welcome to ${guild.name}, ${member}!`,
files: [attachment],
}),
member.send({
content: `Welcome to ${guild.name}, we hope you enjoy your stay!`,
files: [attachment],
}),
updateMember({
discordId: member.user.id,
currentlyInServer: true,
}),
member.roles.add(config.roles.joinRoles),
logAction({
guild,
action: 'memberJoin',
member,
}),
]);
}
} catch (error) {
console.error('Error handling new member:', error);
}
},
};
export const memberLeave = {
name: Events.GuildMemberRemove,
execute: async (member: GuildMember) => {
const { guild } = member;
try {
await Promise.all([
updateMember({
discordId: member.user.id,
currentlyInServer: false,
}),
logAction({
guild,
action: 'memberLeave',
member,
}),
]);
} catch (error) {
console.error('Error handling member leave:', error);
}
},
};
export const memberUpdate = {
name: Events.GuildMemberUpdate,
execute: async (oldMember: GuildMember, newMember: GuildMember) => {
const { guild } = newMember;
try {
if (oldMember.user.username !== newMember.user.username) {
await updateMember({
discordId: newMember.user.id,
discordUsername: newMember.user.username,
});
await logAction({
guild,
action: 'memberUsernameUpdate',
member: newMember,
oldValue: oldMember.user.username,
newValue: newMember.user.username,
});
}
if (oldMember.nickname !== newMember.nickname) {
await logAction({
guild,
action: 'memberNicknameUpdate',
member: newMember,
oldValue: oldMember.nickname ?? oldMember.user.username,
newValue: newMember.nickname ?? newMember.user.username,
});
}
const addedRoles = newMember.roles.cache.filter(
(role) => !oldMember.roles.cache.has(role.id),
);
const removedRoles = oldMember.roles.cache.filter(
(role) => !newMember.roles.cache.has(role.id),
);
if (addedRoles.size > 0) {
for (const role of addedRoles.values()) {
await logAction({
guild,
action: 'roleAdd',
member: newMember,
role,
});
}
}
if (removedRoles.size > 0) {
for (const role of removedRoles.values()) {
await logAction({
guild,
action: 'roleRemove',
member: newMember,
role,
});
}
}
} catch (error) {
console.error('Error handling member update:', error);
}
},
};
export default [memberJoin, memberLeave, memberUpdate];

View file

@ -0,0 +1,58 @@
import { AuditLogEvent, Events, Message } from 'discord.js';
import logAction from '../util/logging/logAction.js';
export const messageDelete = {
name: Events.MessageDelete,
execute: async (message: Message) => {
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 = {
name: Events.MessageUpdate,
execute: async (oldMessage: Message, 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 default [messageDelete, messageUpdate];

9
src/events/ready.ts Normal file
View file

@ -0,0 +1,9 @@
import { Client, Events } from 'discord.js';
export default {
name: Events.ClientReady,
once: true,
execute: async (client: Client) => {
console.log(`Ready! Logged in as ${client.user?.tag}`);
},
};

93
src/events/roleEvents.ts Normal file
View file

@ -0,0 +1,93 @@
import { AuditLogEvent, Events, Role } from 'discord.js';
import logAction from '../util/logging/logAction.js';
const convertRoleProperties = (role: Role) => ({
name: role.name,
color: role.hexColor,
hoist: role.hoist,
mentionable: role.mentionable,
});
export const roleCreate = {
name: Events.GuildRoleCreate,
execute: async (role: Role) => {
try {
const { guild } = role;
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.RoleCreate,
limit: 1,
});
const executor = auditLogs.entries.first()?.executor;
const moderator = executor
? await guild.members.fetch(executor.id)
: undefined;
await logAction({
guild,
action: 'roleCreate',
role,
moderator,
});
} catch (error) {
console.error('Error handling role create:', error);
}
},
};
export const roleDelete = {
name: Events.GuildRoleDelete,
execute: async (role: Role) => {
try {
const { guild } = role;
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.RoleDelete,
limit: 1,
});
const executor = auditLogs.entries.first()?.executor;
const moderator = executor
? await guild.members.fetch(executor.id)
: undefined;
await logAction({
guild,
action: 'roleDelete',
role,
moderator,
});
} catch (error) {
console.error('Error handling role delete:', error);
}
},
};
export const roleUpdate = {
name: Events.GuildRoleUpdate,
execute: async (oldRole: Role, newRole: Role) => {
try {
const { guild } = newRole;
const auditLogs = await guild.fetchAuditLogs({
type: AuditLogEvent.RoleUpdate,
limit: 1,
});
const executor = auditLogs.entries.first()?.executor;
const moderator = executor
? await guild.members.fetch(executor.id)
: undefined;
await logAction({
guild,
action: 'roleUpdate',
role: newRole,
oldRole: convertRoleProperties(oldRole),
newRole: convertRoleProperties(newRole),
moderator,
oldPermissions: oldRole.permissions,
newPermissions: newRole.permissions,
});
} catch (error) {
console.error('Error handling role update:', error);
}
},
};
export default [roleCreate, roleDelete, roleUpdate];