diff --git a/bot.log b/bot.log index 151b093..fa61254 100644 --- a/bot.log +++ b/bot.log @@ -1,15 +1,27 @@ -[dotenv@17.3.1] injecting env (2) from .env -- tip: πŸ” encrypt with Dotenvx: https://dotenvx.com +Bot Starting... +[dotenv@17.3.1] injecting env (2) from .env -- tip: βš™οΈ load multiple .env files with { path: ['.env.local', '.env'] } Keep-Alive aktif di port 8080 Bot logged in as XiaoMao#2565 Memulai refresh slash commands... -(node:11444) DeprecationWarning: The ready event has been renamed to clientReady to distinguish it from the gateway READY event and will only emit under that name in v15. Please use clientReady instead. +(node:19382) DeprecationWarning: The ready event has been renamed to clientReady to distinguish it from the gateway READY event and will only emit under that name in v15. Please use clientReady instead. (Use `node --trace-deprecation ...` to show where the warning was created) Berhasil mendaftarkan slash commands! -DisTubeError [FFMPEG_NOT_INSTALLED]: ffmpeg is not installed at 'ffmpeg' path - at checkFFmpeg (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:1786:11) - at QueueManager.create (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:2008:7) +(node:19382) Warning: Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead. +Command /queue diterima dari: rio.xmc +Command /play diterima dari: rio.xmc +/home/ubuntu/executor/workspace/index.js:149 + if (channel) channel.send(`❌ Error: ${e.message.slice(0, 1900)}`); + ^ + +TypeError: Cannot read properties of undefined (reading 'slice') + at DisTube. (/home/ubuntu/executor/workspace/index.js:149:57) + at DisTube.emit (node:events:518:28) + at DisTube.emitError (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:2546:10) + at QueueManager.emitError (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:154:18) + at #handlePlayingError (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:2100:10) + at QueueManager.playSong (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:2147:31) at process.processTicksAndRejections (node:internal/process/task_queues:105:5) - at async DisTube.play (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:2328:50) - at async Client. (/home/ubuntu/executor/workspace/index.js:78:13) { - errorCode: 'FFMPEG_NOT_INSTALLED' -} + at async DisTube.play (/home/ubuntu/executor/workspace/node_modules/distube/dist/index.js:2352:24) + at async Client. (/home/ubuntu/executor/workspace/index.js:86:13) + +Node.js v22.18.0 diff --git a/index.js b/index.js index 526f8ad..f5fab78 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,10 @@ +console.log('Bot Starting...'); const { Client, GatewayIntentBits, EmbedBuilder, PermissionsBitField, REST, Routes, SlashCommandBuilder } = require('discord.js'); const { DisTube } = require('distube'); const { YtDlpPlugin } = require('@distube/yt-dlp'); const { YouTubePlugin } = require('@distube/youtube'); const express = require('express'); -const ffmpeg = require('ffmpeg-static'); require('dotenv').config(); -console.log('FFmpeg Path: ', ffmpeg); // 1. Keep-Alive System const app = express(); @@ -24,7 +23,6 @@ const client = new Client({ // 3. DisTube Setup const distube = new DisTube(client, { - ffmpegPath: ffmpeg, emitNewSongOnly: true, emitAddSongWhenCreatingQueue: false, emitAddListWhenCreatingQueue: false, @@ -64,45 +62,78 @@ const commands = [ client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; - // WAJIB: Defer Reply di baris pertama agar Discord menunggu (antisipasi "application did not respond") - await interaction.deferReply(); + // Force Defer: Baris paling pertama setelah pengecekan command + await interaction.deferReply({ ephemeral: false }); - const { commandName } = interaction; - const voiceChannel = interaction.member.voice.channel; - - if (!voiceChannel) { - return interaction.editReply({ content: 'Kamu harus berada di Voice Channel untuk menggunakan perintah ini!', ephemeral: true }); - } + console.log(`Command /${interaction.commandName} diterima dari: ${interaction.user.tag}`); + // 2. Gunakan Try-Catch: Bungkus semua proses agar bot tidak mati jika error try { + const { commandName } = interaction; + + // 3. Sinkronisasi Voice: Pastikan user ada di voice channel + if (!interaction.member.voice.channel) { + return interaction.editReply('Kamu harus berada di voice channel untuk menggunakan bot ini!'); + } + if (commandName === 'play') { const query = interaction.options.getString('query'); - await distube.play(voiceChannel, query, { + + // Memberikan feedback awal + await interaction.editReply({ content: `πŸ” Sedang mencari lagu: **${query}**...` }); + + // 4. Fix DisTube Play: Pemanggilan profesional dengan parameter lengkap + await distube.play(interaction.member.voice.channel, query, { textChannel: interaction.channel, - member: interaction.member + member: interaction.member, + interaction // Menyertakan interaksi jika diperlukan oleh plugin }); - await interaction.editReply(`πŸ” Sedang mencari dan memutar: **${query}**`); + } else if (commandName === 'skip') { + const queue = distube.getQueue(interaction.guild); + if (!queue) return interaction.editReply('❌ Tidak ada lagu yang sedang diputar!'); + await distube.skip(interaction.guild); - await interaction.editReply('⏭️ Lagu dilewati!'); + await interaction.editReply('⏭️ Lagu berhasil dilewati!'); + } else if (commandName === 'stop') { await distube.stop(interaction.guild); - await interaction.editReply('⏹️ Musik dihentikan dan bot keluar!'); + await interaction.editReply('⏹️ Musik dihentikan dan bot keluar dari voice channel!'); + } else if (commandName === 'pause') { + const queue = distube.getQueue(interaction.guild); + if (!queue) return interaction.editReply('❌ Tidak ada lagu untuk dijeda!'); + distube.pause(interaction.guild); - await interaction.editReply('⏸️ Musik dijeda!'); + await interaction.editReply('⏸️ Musik berhasil dijeda!'); + } else if (commandName === 'resume') { + const queue = distube.getQueue(interaction.guild); + if (!queue) return interaction.editReply('❌ Tidak ada lagu untuk dilanjutkan!'); + distube.resume(interaction.guild); await interaction.editReply('▢️ Musik dilanjutkan!'); + } else if (commandName === 'queue') { const queue = distube.getQueue(interaction.guild); - if (!queue) return interaction.editReply('Antrean kosong!'); - const q = queue.songs.map((song, i) => `${i === 0 ? 'Memutar:' : `${i}.`} ${song.name} - \`${song.formattedDuration}\``).join('\n'); - await interaction.editReply(`🎢 **Antrean Saat Ini:**\n${q.slice(0, 2000)}`); + if (!queue) return interaction.editReply('πŸ“­ Antrean saat ini kosong!'); + + const q = queue.songs + .map((song, i) => `${i === 0 ? '▢️ **Memutar:**' : `**${i}.**`} ${song.name} - \`${song.formattedDuration}\``) + .join('\n'); + + await interaction.editReply(`🎢 **Daftar Antrean:**\n${q.slice(0, 2000)}`); } + } catch (error) { - console.error(error); - await interaction.editReply(`❌ Terjadi kesalahan: ${error.message}`); + console.error('Interaction Error:', error); + + // Cek apakah interaksi sudah di-defer atau di-reply untuk menghindari error tambahan + if (interaction.deferred || interaction.replied) { + await interaction.editReply({ content: `❌ Terjadi kesalahan: ${error.message}` }); + } else { + await interaction.reply({ content: `❌ Terjadi kesalahan fatal: ${error.message}`, ephemeral: true }); + } } }); @@ -115,8 +146,11 @@ distube queue.textChannel.send(`βœ… Menambahkan **${song.name}** ke antrean!`); }) .on('error', (channel, e) => { - if (channel) channel.send(`❌ Error: ${e.message.slice(0, 1900)}`); - console.error(e); + if (channel && channel.send) { + const errorMessage = e && e.message ? e.message.slice(0, 1900) : "Unknown Error"; + channel.send(`❌ Error: ${errorMessage}`).catch(console.error); + } + console.error('DisTube Error:', e); }); // 7. Client Ready & Command Registration @@ -137,4 +171,13 @@ client.once('ready', async () => { } }); +// 8. Global Error Handling (Anti-Crash) +process.on('unhandledRejection', error => { + console.error('Unhandled promise rejection:', error); +}); + +process.on('uncaughtException', error => { + console.error('Uncaught exception:', error); +}); + client.login(process.env.DISCORD_TOKEN); diff --git a/test.log b/test.log new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/test.log @@ -0,0 +1 @@ +test