const ffmpeg = require('ffmpeg-static'); const { generateDependencyReport } = require('@discordjs/voice'); console.log(generateDependencyReport()); // --- ENCRYPTION & AUDIO CONFIG --- // Wajib di baris paling atas agar enkripsi Discord terdeteksi dengan benar process.env.FFMPEG_PATH = ffmpeg; require('libsodium-wrappers'); // --- KEEP ALIVE --- // Membuat server sederhana agar bot merespons ping dari sistem // Port 8080 digunakan untuk internal health check http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('Bot is Online and Healthy'); res.end(); }).listen(8080, '0.0.0.0', () => { console.log('Keep-Alive server is running on port 8080'); }); // --- ERROR HANDLING --- // Mencegah bot mati jika terjadi error yang tidak terduga process.on('unhandledRejection', error => { console.error('Unhandled promise rejection:', error); }); process.on('uncaughtException', error => { console.error('Uncaught exception:', error); }); const { Client, GatewayIntentBits } = require('discord.js'); const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, VoiceConnectionStatus, getVoiceConnection } = require('@discordjs/voice'); // --- CONFIGURATION --- let TOKEN, CLIENT_ID; try { const config = require('./config.json'); TOKEN = config.DISCORD_TOKEN; CLIENT_ID = config.DISCORD_CLIENT_ID; } catch (err) { console.warn('Warning: config.json not found. Using environment variables if available.'); TOKEN = process.env.DISCORD_TOKEN; CLIENT_ID = process.env.DISCORD_CLIENT_ID; } if (!TOKEN) { console.error('ERROR: DISCORD_TOKEN is missing. Please set it in the dashboard.'); } const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, ] }); // Helper function to join voice function connectToVoice(interaction) { return joinVoiceChannel({ channelId: interaction.member.voice.channel.id, guildId: interaction.guild.id, adapterCreator: interaction.guild.voiceAdapterCreator, selfDeaf: true, selfMute: false, }); } client.on('clientReady', () => { console.log(`Logged in as ${client.user.tag}!`); console.log('Bot Status: Online'); }); client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; const { commandName } = interaction; if (commandName === 'join') { await interaction.deferReply(); try { connectToVoice(interaction); await interaction.editReply('Berhasil masuk ke Voice Channel!'); } catch (error) { await interaction.editReply({ content: error.message, ephemeral: true }); } } if (commandName === 'sahur') { await interaction.deferReply(); try { let connection = getVoiceConnection(interaction.guild.id); if (!connection) { connection = connectToVoice(interaction); } const player = createAudioPlayer(); const resource = createAudioResource(path.join(process.cwd(), 'sahur.mp3')); connection.subscribe(player); player.play(resource); console.log('Bot Status: Playing'); await interaction.editReply('🔊 Sedang memutar alarm sahur!'); player.on(AudioPlayerStatus.Idle, () => { console.log('Bot Status: Finished playing (Idle)'); }); player.on('error', e => { console.error('ERROR_AUDIO:', e.message); interaction.followUp({ content: 'Terjadi kesalahan saat memutar audio.', ephemeral: true }); }); } catch (error) { console.error('ERROR:', error); await interaction.editReply(error.message || 'Gagal memutar audio.'); } } }); if (TOKEN) { client.login(TOKEN).catch(err => { console.error('Login failed:', err.message); }); } else { console.log('Bot Status: Waiting for token setup...'); }