Skip to content

Commit

Permalink
feat: Prefix Command Management (#85)
Browse files Browse the repository at this point in the history
Co-authored-by: ExampleWasTaken <[email protected]>
  • Loading branch information
pdellaert and ExampleWasTaken authored Oct 28, 2024
1 parent 55cfd0e commit e5f5a12
Show file tree
Hide file tree
Showing 45 changed files with 5,464 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ HEARTBEAT_INTERVAL=300

# Set the interval in seconds for the birthday handler to be run, 0 to disable
BIRTHDAY_INTERVAL=1800

# Set the interval in seconds for the in memory cache to be refreshed, 1800 is the default
CACHE_REFRESH_INTERVAL=1800
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Update <small>_ October 2024</small>

- feat: Prefix Command Management (28/10/2024)
- fix: role assignment typo for server announcements (22/10/2024)

Update <small>_ August 2024</small>
Expand Down
2 changes: 2 additions & 0 deletions config/production.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"1163130801131634868",
"1021464464928809022"
],
"prefixCommandPrefix": ".",
"prefixCommandPermissionDelay": 10000,
"roleAssignmentIds": [
{
"group": "interestedIn",
Expand Down
2 changes: 2 additions & 0 deletions config/staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
"1163130801131634868",
"1021464464928809022"
],
"prefixCommandPrefix": ".",
"prefixCommandPermissionDelay": 10000,
"roleAssignmentIds": [
{
"group": "interestedIn",
Expand Down
521 changes: 521 additions & 0 deletions docs/prefix-commands.md

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@hokify/agenda": "^6.0.0",
"@octokit/request": "^8.1.1",
"bad-words": "^3.0.4",
"cache-manager": "^5.7.6",
"config": "^3.3.9",
"discord.js": "^14.11.0",
"jsdom": "^23.2.0",
Expand Down
8 changes: 8 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import commandTable from './moderation/commandTable';
import listRoleUsers from './moderation/listRoleUsers';
import clearMessages from './moderation/clearMessages';
import locate from './utils/locate/locate';
import prefixCommands from './moderation/prefixCommands/prefixCommands';
import prefixCommandPermissions from './moderation/prefixCommands/prefixCommandPermissions';
import prefixCommandCacheUpdate from './moderation/prefixCommands/prefixCommandCacheUpdate';
import prefixHelp from './utils/prefixHelp';

const commandArray: SlashCommand[] = [
ping,
Expand Down Expand Up @@ -65,6 +69,10 @@ const commandArray: SlashCommand[] = [
listRoleUsers,
clearMessages,
locate,
prefixCommands,
prefixCommandPermissions,
prefixCommandCacheUpdate,
prefixHelp,
];

export default commandArray;
98 changes: 98 additions & 0 deletions src/commands/moderation/prefixCommands/functions/addCategory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
import { constantsConfig, getConn, PrefixCommandCategory, Logger, makeEmbed, loadSinglePrefixCommandCategoryToCache } from '../../../../lib';

const noConnEmbed = makeEmbed({
title: 'Prefix Commands - Add Category - No Connection',
description: 'Could not connect to the database. Unable to add the prefix command category.',
color: Colors.Red,
});

const failedEmbed = (category: string) => makeEmbed({
title: 'Prefix Commands - Add Category - Failed',
description: `Failed to add the prefix command category ${category}.`,
color: Colors.Red,
});

const alreadyExistsEmbed = (category: string) => makeEmbed({
title: 'Prefix Commands - Add Category - Already exists',
description: `The prefix command category ${category} already exists. Not adding again.`,
color: Colors.Red,
});

const successEmbed = (category: string) => makeEmbed({
title: `Prefix command category ${category} was added successfully.`,
color: Colors.Green,
});

const modLogEmbed = (moderator: User, category: string, emoji: string, categoryId: string) => makeEmbed({
title: 'Prefix command category added',
fields: [
{
name: 'Category',
value: category,
},
{
name: 'Moderator',
value: `${moderator}`,
},
{
name: 'Emoji',
value: emoji,
},
],
footer: { text: `Category ID: ${categoryId}` },
color: Colors.Green,
});

const noModLogs = makeEmbed({
title: 'Prefix Commands - Add Category - No Mod Log',
description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
color: Colors.Red,
});

export async function handleAddPrefixCommandCategory(interaction: ChatInputCommandInteraction<'cached'>) {
await interaction.deferReply({ ephemeral: true });

const conn = getConn();
if (!conn) {
await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
return;
}

const name = interaction.options.getString('name')!;
const emoji = interaction.options.getString('emoji') || '';
const moderator = interaction.user;

//Check if the mod logs channel exists
let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
if (!modLogsChannel || !modLogsChannel.isTextBased()) {
modLogsChannel = null;
await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
}

const existingCategory = await PrefixCommandCategory.findOne({ name });

if (!existingCategory) {
const prefixCommandCategory = new PrefixCommandCategory({
name,
emoji,
});
try {
await prefixCommandCategory.save();
await loadSinglePrefixCommandCategoryToCache(prefixCommandCategory);
await interaction.followUp({ embeds: [successEmbed(name)], ephemeral: true });
if (modLogsChannel) {
try {
await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, emoji, prefixCommandCategory.id)] });
} catch (error) {
Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
}
}
} catch (error) {
Logger.error(`Failed to add a prefix command category ${name}: ${error}`);
await interaction.followUp({ embeds: [failedEmbed(name)], ephemeral: true });
}
} else {
await interaction.followUp({ embeds: [alreadyExistsEmbed(name)], ephemeral: true });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, refreshSinglePrefixCommandCache } from '../../../../lib';

const noConnEmbed = makeEmbed({
title: 'Prefix Commands - Add Channel - No Connection',
description: 'Could not connect to the database. Unable to add the prefix command channel.',
color: Colors.Red,
});

const noCommandEmbed = (command: string) => makeEmbed({
title: 'Prefix Commands - Add Channel - No Command',
description: `Failed to add the prefix command channel for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
});

const failedEmbed = (command: string, channel: string) => makeEmbed({
title: 'Prefix Commands - Add Channel - Failed',
description: `Failed to add the prefix command channel <#${channel}> for command ${command}.`,
color: Colors.Red,
});

const alreadyExistsEmbed = (command: string, channel: string) => makeEmbed({
title: 'Prefix Commands - Add Channel - Already exists',
description: `A prefix command channel <#${channel}> for command ${command} already exists. Not adding again.`,
color: Colors.Red,
});

const successEmbed = (command: string, channel: string) => makeEmbed({
title: `Prefix command channel <#${channel}> added for command ${command}.`,
color: Colors.Green,
});

const modLogEmbed = (moderator: User, command: string, channel: string) => makeEmbed({
title: 'Add prefix command channel permission',
fields: [
{
name: 'Command',
value: command,
},
{
name: 'Channel',
value: `<#${channel}>`,
},
{
name: 'Moderator',
value: `${moderator}`,
},
],
color: Colors.Green,
});

const noModLogs = makeEmbed({
title: 'Prefix Commands - Add Channel - No Mod Log',
description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
color: Colors.Red,
});

export async function handleAddPrefixCommandChannelPermission(interaction: ChatInputCommandInteraction<'cached'>) {
await interaction.deferReply({ ephemeral: true });

const conn = getConn();
if (!conn) {
await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
return;
}

const command = interaction.options.getString('command')!;
const channel = interaction.options.getChannel('channel')!;
const moderator = interaction.user;

//Check if the mod logs channel exists
let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
if (!modLogsChannel || !modLogsChannel.isTextBased()) {
modLogsChannel = null;
await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
}

let foundCommands = await PrefixCommand.find({ name: command });
if (!foundCommands || foundCommands.length > 1) {
foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
}
if (!foundCommands || foundCommands.length > 1) {
await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
return;
}
const [foundCommand] = foundCommands;
const { id: channelId } = channel;

const existingChannelPermission = foundCommand.permissions.channels?.includes(channelId);
if (!existingChannelPermission) {
if (!foundCommand.permissions.channels) {
foundCommand.permissions.channels = [];
}
foundCommand.permissions.channels.push(channelId);
try {
await foundCommand.save();
await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
await interaction.followUp({ embeds: [successEmbed(command, channelId)], ephemeral: true });
if (modLogsChannel) {
try {
await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, channelId)] });
} catch (error) {
Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
}
}
} catch (error) {
Logger.error(`Failed to add prefix command channel <#${channel}> for command ${command}: ${error}`);
await interaction.followUp({ embeds: [failedEmbed(command, channelId)], ephemeral: true });
}
} else {
await interaction.followUp({ embeds: [alreadyExistsEmbed(command, channelId)], ephemeral: true });
}
}
Loading

0 comments on commit e5f5a12

Please sign in to comment.