- Converted all .js files to .ts - Added TypeScript configuration (tsconfig.json) - Added ESLint and Prettier configuration - Updated package.json dependencies - Modified Docker and application configurations
68 lines
3.5 KiB
TypeScript
68 lines
3.5 KiB
TypeScript
import {
|
|
SlashCommandBuilder,
|
|
ChatInputCommandInteraction, // Import the specific interaction type
|
|
GuildMember // Import GuildMember type
|
|
} from 'discord.js';
|
|
import logger from '../utils/logger'; // Use default import
|
|
import { BotClient } from '../index'; // Import the BotClient interface
|
|
// No need to import Player explicitly if we just check connection
|
|
|
|
export default { // Use export default for ES Modules
|
|
data: new SlashCommandBuilder()
|
|
.setName('leave')
|
|
.setDescription('Leaves the current voice channel'),
|
|
async execute(interaction: ChatInputCommandInteraction, client: BotClient) { // Add types
|
|
// Ensure command is run in a guild
|
|
if (!interaction.guildId || !interaction.guild) {
|
|
return interaction.reply({ content: 'This command can only be used in a server.', ephemeral: true }).catch(() => {});
|
|
}
|
|
// Ensure interaction.member is a GuildMember (optional, but good practice)
|
|
if (!(interaction.member instanceof GuildMember)) {
|
|
return interaction.reply({ content: 'Could not verify your membership.', ephemeral: true }).catch(() => {});
|
|
}
|
|
|
|
// Use ephemeral deferral
|
|
await interaction.deferReply({ ephemeral: true });
|
|
|
|
// Get the Shoukaku instance
|
|
const shoukaku = client.shoukaku;
|
|
if (!shoukaku) {
|
|
logger.error('Shoukaku instance not found on client object!');
|
|
return interaction.editReply('The music player is not ready yet.');
|
|
}
|
|
|
|
// Check if a connection exists for this guild
|
|
const connection = shoukaku.connections.get(interaction.guildId);
|
|
if (!connection || !connection.channelId) {
|
|
return interaction.editReply('I am not currently in a voice channel!');
|
|
}
|
|
|
|
// Optional: Check if the user is in the same channel as the bot
|
|
// const memberVoiceChannelId = interaction.member.voice.channelId;
|
|
// if (memberVoiceChannelId !== connection.channelId) {
|
|
// return interaction.editReply('You need to be in the same voice channel as me to make me leave!');
|
|
// }
|
|
|
|
try {
|
|
const channelId = connection.channelId; // Get channel ID from connection
|
|
const channel = await client.channels.fetch(channelId).catch(() => null); // Fetch channel for name
|
|
const channelName = channel && channel.isVoiceBased() ? channel.name : `ID: ${channelId}`; // Get channel name if possible
|
|
|
|
// Use Shoukaku's leave method - this destroys player and connection
|
|
await shoukaku.leaveVoiceChannel(interaction.guildId);
|
|
|
|
logger.info(`Left voice channel ${channelName} in guild ${interaction.guild.name} (${interaction.guildId}) by user ${interaction.user.tag}`);
|
|
await interaction.editReply(`Left ${channelName}.`);
|
|
|
|
} catch (error: unknown) { // Type error as unknown
|
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
logger.error(`Error leaving voice channel for guild ${interaction.guildId}: ${errorMessage}`, error);
|
|
// Attempt to reply even if leave failed partially
|
|
await interaction.editReply('An error occurred while trying to leave the voice channel.').catch((e: unknown) => { // Type catch error
|
|
const replyErrorMsg = e instanceof Error ? e.message : String(e);
|
|
logger.error(`Failed to send error reply for leave command: ${replyErrorMsg}`);
|
|
});
|
|
}
|
|
},
|
|
};
|