diff --git a/data/config.json b/data/config.json index 06eb81f..d702284 100644 --- a/data/config.json +++ b/data/config.json @@ -2,6 +2,6 @@ "discord_token": "MTQ3MTkwOTE5Mzg4Njg1OTI5NA.GCEdpc.jMIxPFsquVAhp88x3dO-yWUFI7e1u1r8oIZTcw", "guild_id": "1428530728706117632", "voice_channel_id": "1457687430189682781", - "alarm_time": "15:33", + "alarm_time": "18:55", "last_voice_channel": null } \ No newline at end of file diff --git a/index.js b/index.js index 41883b7..aa82934 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,3 @@ -process.env.FFMPEG_PATH = require('ffmpeg-static'); -require('opusscript'); -require('libsodium-wrappers'); const { Client, GatewayIntentBits, SlashCommandBuilder, Routes } = require('discord.js'); const { joinVoiceChannel, createAudioPlayer, createAudioResource, StreamType, getVoiceConnection } = require('@discordjs/voice'); const fs = require('fs'); @@ -8,8 +5,7 @@ const path = require('path'); const { REST } = require('@discordjs/rest'); // Load Config -const configPath = path.join(__dirname, 'data/config.json'); -const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); +const config = JSON.parse(fs.readFileSync('./data/config.json', 'utf8')); const token = config.discord_token; const client = new Client({ @@ -18,120 +14,109 @@ const client = new Client({ const player = createAudioPlayer(); -// Monitoring Status -player.on('stateChange', (oldState, newState) => { - console.log(`Status Player: ${newState.status}`); +player.on('error', err => { + console.log('LOG ERROR AUDIO:', err.message); }); -player.on('error', error => { - console.log('ERROR AUDIO:', error.message); +player.on('stateChange', (old, current) => { + console.log('Status Audio Saat Ini:', current.status); }); client.on('ready', async () => { - console.log(`Bot Sahur Online: ${client.user.tag}`); - + console.log(`Bot Minimalis Ready: ${client.user.tag}`); const commands = [ - new SlashCommandBuilder().setName('join').setDescription('Perintah untuk bot masuk ke Voice Channel'), - new SlashCommandBuilder().setName('testsahur').setDescription('Perintah untuk memutar suara alarm sahur') + new SlashCommandBuilder().setName('join').setDescription('Bot join ke Voice Channel'), + new SlashCommandBuilder().setName('testsahur').setDescription('Tes putar sahur.mp3') ].map(cmd => cmd.toJSON()); - + const rest = new REST({ version: '10' }).setToken(token); try { await rest.put(Routes.applicationCommands(client.user.id), { body: commands }); - console.log('Slash Commands Berhasil Didaftarkan.'); - } catch (err) { - console.error('Gagal daftar command:', err); + console.log('Slash Commands registered.'); + } catch (error) { + console.error('Error registering commands:', error); } }); client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; - // 1. PERINTAH JOIN (Hanya Masuk) + // Fix untuk /join if (interaction.commandName === 'join') { - await interaction.deferReply(); - const channel = interaction.member.voice.channel; - - if (!channel) { - return interaction.editReply('❌ Kamu harus masuk ke Voice Channel dulu!'); - } - - const connection = joinVoiceChannel({ - channelId: channel.id, - guildId: interaction.guildId, - adapterCreator: interaction.guild.voiceAdapterCreator, - selfDeaf: false, - selfMute: false, - debug: true - }); - - // Keep-Alive Logic - connection.on('stateChange', (oldState, newState) => { - if (newState.status === 'disconnected') { - console.log('Bot terputus, mencoba masuk kembali...'); - try { - joinVoiceChannel({ - channelId: channel.id, - guildId: interaction.guildId, - adapterCreator: interaction.guild.voiceAdapterCreator, - selfDeaf: false, - selfMute: false - }); - } catch (e) { - console.log('Gagal rejoin:', e.message); - } - } - }); - - console.log('Bot masuk voice!'); - await interaction.editReply('✅ Bot sudah masuk ke Voice Channel. Siap untuk /testsahur!'); - } - - // 2. PERINTAH TESTSAHUR (Auto-Join & Play) - if (interaction.commandName === 'testsahur') { + // Gunakan Defer Reply di awal await interaction.deferReply(); - let connection = getVoiceConnection(interaction.guildId); - const channel = interaction.member.voice.channel; + try { + const channel = interaction.member.voice.channel; + if (!channel) return interaction.editReply('Masuk ke VC dulu!'); - // Auto-Reconnect: Jika tidak ada koneksi, join dulu - if (!connection) { - if (!channel) { - return interaction.editReply('❌ Bot tidak di VC dan kamu juga tidak di VC. Join VC dulu!'); - } - - console.log('Connection tidak ditemukan, mencoba auto-join...'); - connection = joinVoiceChannel({ + joinVoiceChannel({ channelId: channel.id, guildId: interaction.guildId, adapterCreator: interaction.guild.voiceAdapterCreator, selfDeaf: false, selfMute: false }); - } + await interaction.editReply('Berhasil join ke Voice Channel!'); + } catch (error) { + // Anti-Stuck: Tangkap error agar tidak diam saja + await interaction.editReply('Error: ' + error.message); + } + } + + // Fix untuk /testsahur + if (interaction.commandName === 'testsahur') { + // Gunakan Defer Reply di awal + await interaction.deferReply(); + try { - const audioPath = path.join(process.cwd(), 'assets', 'audio', 'sahur.mp3'); - console.log('Membaca file audio di:', audioPath); - - if (!fs.existsSync(audioPath)) { - return interaction.editReply('❌ File audio tidak ditemukan!'); + const channel = interaction.member.voice.channel; + if (!channel) return interaction.editReply('Masuk ke VC dulu!'); + + const connection = joinVoiceChannel({ + channelId: channel.id, + guildId: interaction.guildId, + adapterCreator: interaction.guild.voiceAdapterCreator, + selfDeaf: false, + selfMute: false + }); + + // Direct Path + const filePath = './assets/audio/sahur.mp3'; + + // Verify File + if (!fs.existsSync(filePath)) { + return interaction.editReply('Error: File tidak ditemukan di assets/audio!'); } - const resource = createAudioResource(audioPath, { + // Hapus Stream Kompleks & Gunakan Jalur Langsung + const resource = createAudioResource('./assets/audio/sahur.mp3', { inputType: StreamType.Arbitrary, inlineVolume: true }); - resource.volume.setVolume(1.5); - connection.subscribe(player); + // Debug Status + console.log('Resource Readable:', resource.readable); + console.log('Connection Status:', connection.state.status); + + // Kabel Utama (Subscribe) + const subscription = connection.subscribe(player); player.play(resource); - - console.log('Kabel audio tersambung dan suara diputar!'); - await interaction.editReply('🔊 Sedang memutar alarm sahur (Auto-Connect Aktif)...'); + + await interaction.editReply('🔊 Sedang memutar sahur.mp3...'); } catch (error) { - console.log('ERROR AUDIO:', error.message); - await interaction.editReply('❌ Terjadi kesalahan: ' + error.message); + // Anti-Stuck: Tangkap error agar tidak diam saja + await interaction.editReply('Error: ' + error.message); + } + } + + // Interaction Timeout Fix: Jika belum dibalas atau di-defer + if (!interaction.replied && !interaction.deferred) { + try { + await interaction.reply('Sedang diproses...'); + } catch (err) { + console.error('Fallback reply failed:', err.message); } } }); diff --git a/sahur.mp3 b/sahur.mp3 new file mode 100644 index 0000000..13d50ac Binary files /dev/null and b/sahur.mp3 differ