262 lines
7.1 KiB
TypeScript
262 lines
7.1 KiB
TypeScript
/**
|
|
* Role Command
|
|
* Manage user roles (for officers)
|
|
*/
|
|
|
|
import {
|
|
SlashCommandBuilder,
|
|
EmbedBuilder,
|
|
type ChatInputCommandInteraction,
|
|
} from 'discord.js';
|
|
import type { Command } from '../../types/index.ts';
|
|
import { PermissionLevel } from '../../types/index.ts';
|
|
import type { EllyClient } from '../../client/EllyClient.ts';
|
|
|
|
export const roleCommand: Command = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('role')
|
|
.setDescription('Manage user roles')
|
|
.addSubcommand((sub) =>
|
|
sub
|
|
.setName('add')
|
|
.setDescription('Add a role to a user')
|
|
.addUserOption((opt) =>
|
|
opt.setName('user').setDescription('User to add role to').setRequired(true)
|
|
)
|
|
.addRoleOption((opt) =>
|
|
opt.setName('role').setDescription('Role to add').setRequired(true)
|
|
)
|
|
)
|
|
.addSubcommand((sub) =>
|
|
sub
|
|
.setName('remove')
|
|
.setDescription('Remove a role from a user')
|
|
.addUserOption((opt) =>
|
|
opt.setName('user').setDescription('User to remove role from').setRequired(true)
|
|
)
|
|
.addRoleOption((opt) =>
|
|
opt.setName('role').setDescription('Role to remove').setRequired(true)
|
|
)
|
|
)
|
|
.addSubcommand((sub) =>
|
|
sub
|
|
.setName('list')
|
|
.setDescription('List manageable roles')
|
|
),
|
|
|
|
permission: PermissionLevel.Officer,
|
|
cooldown: 3,
|
|
|
|
async execute(interaction: ChatInputCommandInteraction): Promise<void> {
|
|
const client = interaction.client as EllyClient;
|
|
const subcommand = interaction.options.getSubcommand();
|
|
|
|
switch (subcommand) {
|
|
case 'add':
|
|
await handleAdd(interaction, client);
|
|
break;
|
|
case 'remove':
|
|
await handleRemove(interaction, client);
|
|
break;
|
|
case 'list':
|
|
await handleList(interaction, client);
|
|
break;
|
|
}
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Handle adding a role
|
|
*/
|
|
async function handleAdd(
|
|
interaction: ChatInputCommandInteraction,
|
|
client: EllyClient
|
|
): Promise<void> {
|
|
const targetUser = interaction.options.getUser('user', true);
|
|
const role = interaction.options.getRole('role', true);
|
|
|
|
// Check if role is manageable
|
|
const manageableIds = client.config.roles.manageable?.ids ?? [];
|
|
if (!manageableIds.includes(role.id)) {
|
|
await interaction.reply({
|
|
content: `❌ The role **${role.name}** is not in the list of manageable roles.`,
|
|
ephemeral: true,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const member = interaction.guild?.members.cache.get(targetUser.id);
|
|
if (!member) {
|
|
await interaction.reply({
|
|
content: '❌ User not found in this server.',
|
|
ephemeral: true,
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Check if user already has the role
|
|
if (member.roles.cache.has(role.id)) {
|
|
await interaction.reply({
|
|
content: `❌ ${targetUser.tag} already has the **${role.name}** role.`,
|
|
ephemeral: true,
|
|
});
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await member.roles.add(role.id);
|
|
|
|
await interaction.reply({
|
|
embeds: [
|
|
new EmbedBuilder()
|
|
.setColor(client.config.colors.success)
|
|
.setTitle('✅ Role Added')
|
|
.setDescription(`Added **${role.name}** to ${targetUser.tag}`)
|
|
.setFooter({ text: `By ${interaction.user.tag}` })
|
|
.setTimestamp(),
|
|
],
|
|
});
|
|
|
|
// Log to development channel
|
|
await logRoleChange(client, interaction, targetUser.tag, role.name, 'added');
|
|
} catch (error) {
|
|
await interaction.reply({
|
|
content: `❌ Failed to add role. Make sure I have the required permissions.`,
|
|
ephemeral: true,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle removing a role
|
|
*/
|
|
async function handleRemove(
|
|
interaction: ChatInputCommandInteraction,
|
|
client: EllyClient
|
|
): Promise<void> {
|
|
const targetUser = interaction.options.getUser('user', true);
|
|
const role = interaction.options.getRole('role', true);
|
|
|
|
// Check if role is manageable
|
|
const manageableIds = client.config.roles.manageable?.ids ?? [];
|
|
if (!manageableIds.includes(role.id)) {
|
|
await interaction.reply({
|
|
content: `❌ The role **${role.name}** is not in the list of manageable roles.`,
|
|
ephemeral: true,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const member = interaction.guild?.members.cache.get(targetUser.id);
|
|
if (!member) {
|
|
await interaction.reply({
|
|
content: '❌ User not found in this server.',
|
|
ephemeral: true,
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Check if user has the role
|
|
if (!member.roles.cache.has(role.id)) {
|
|
await interaction.reply({
|
|
content: `❌ ${targetUser.tag} doesn't have the **${role.name}** role.`,
|
|
ephemeral: true,
|
|
});
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await member.roles.remove(role.id);
|
|
|
|
await interaction.reply({
|
|
embeds: [
|
|
new EmbedBuilder()
|
|
.setColor(client.config.colors.warning)
|
|
.setTitle('✅ Role Removed')
|
|
.setDescription(`Removed **${role.name}** from ${targetUser.tag}`)
|
|
.setFooter({ text: `By ${interaction.user.tag}` })
|
|
.setTimestamp(),
|
|
],
|
|
});
|
|
|
|
// Log to development channel
|
|
await logRoleChange(client, interaction, targetUser.tag, role.name, 'removed');
|
|
} catch (error) {
|
|
await interaction.reply({
|
|
content: `❌ Failed to remove role. Make sure I have the required permissions.`,
|
|
ephemeral: true,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle listing manageable roles
|
|
*/
|
|
async function handleList(
|
|
interaction: ChatInputCommandInteraction,
|
|
client: EllyClient
|
|
): Promise<void> {
|
|
const manageableIds = client.config.roles.manageable?.ids ?? [];
|
|
|
|
if (manageableIds.length === 0) {
|
|
await interaction.reply({
|
|
content: '📭 No manageable roles configured.',
|
|
ephemeral: true,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const roles = manageableIds
|
|
.map((id) => interaction.guild?.roles.cache.get(id))
|
|
.filter((r) => r !== undefined)
|
|
.map((r) => `• <@&${r!.id}> (\`${r!.id}\`)`);
|
|
|
|
await interaction.reply({
|
|
embeds: [
|
|
new EmbedBuilder()
|
|
.setColor(client.config.colors.primary)
|
|
.setTitle('📋 Manageable Roles')
|
|
.setDescription(roles.join('\n') || 'No roles found')
|
|
.setFooter({ text: `${roles.length} roles can be managed` })
|
|
.setTimestamp(),
|
|
],
|
|
ephemeral: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log role change to development channel
|
|
*/
|
|
async function logRoleChange(
|
|
client: EllyClient,
|
|
interaction: ChatInputCommandInteraction,
|
|
targetTag: string,
|
|
roleName: string,
|
|
action: 'added' | 'removed'
|
|
): Promise<void> {
|
|
try {
|
|
const logChannelName = client.config.channels.developmentLogs;
|
|
const logChannel = interaction.guild?.channels.cache.find(
|
|
(c) => c.name === logChannelName && c.isTextBased()
|
|
);
|
|
|
|
if (logChannel && logChannel.isTextBased()) {
|
|
await logChannel.send({
|
|
embeds: [
|
|
new EmbedBuilder()
|
|
.setColor(action === 'added' ? 0x57f287 : 0xfee75c)
|
|
.setTitle(`📝 Role ${action === 'added' ? 'Added' : 'Removed'}`)
|
|
.addFields(
|
|
{ name: 'User', value: targetTag, inline: true },
|
|
{ name: 'Role', value: roleName, inline: true },
|
|
{ name: 'By', value: interaction.user.tag, inline: true }
|
|
)
|
|
.setTimestamp(),
|
|
],
|
|
});
|
|
}
|
|
} catch {
|
|
// Ignore logging errors
|
|
}
|
|
}
|