This commit is contained in:
Flatlogic Bot 2026-02-18 09:24:47 +00:00
parent eb4f306c8d
commit 68832bd914
2 changed files with 123 additions and 79 deletions

11
bot.log
View File

@ -1,11 +1,10 @@
[dotenv@17.3.1] injecting env (7) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
Dashboard running at http://localhost:8080
[dotenv@17.3.1] injecting env (7) from .env -- tip: 🔐 prevent committing .env to code: https://dotenvx.com/precommit
Keep-Alive server running on port 8080
Bot logged in as XiaoMao#2565
Started refreshing application (/) commands.
Scheduled sahur at 3:0
(node:7171) 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.
Mendaftarkan ulang slash commands (setelah reset)...
(node:7936) 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)
Successfully reloaded application (/) commands.
Berhasil mendaftarkan command: /join, /test_sahur
/home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js:746
throw new Error(
^

191
index.js
View File

@ -1,17 +1,13 @@
require('dotenv').config();
const {
Client,
GatewayIntentBits,
REST,
Routes,
SlashCommandBuilder
} = require('discord.js');
const { Client, GatewayIntentBits, REST, Routes, SlashCommandBuilder } = require('discord.js');
const {
joinVoiceChannel,
createAudioPlayer,
createAudioResource,
AudioPlayerStatus,
NoSubscriberBehavior
NoSubscriberBehavior,
VoiceConnectionStatus,
enterState
} = require('@discordjs/voice');
const express = require('express');
const fs = require('fs');
@ -22,15 +18,18 @@ const DISCORD_TOKEN = process.env.DISCORD_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;
const GUILD_ID = process.env.GUILD_ID;
// Keep-Alive Server
const app = express();
const port = 8080;
app.get('/', (req, res) => res.send('Bot Sahur is Alive! 🌙'));
app.listen(port, () => console.log(`Keep-Alive server running on port ${port}`));
// Discord Client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
]
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates
]
});
let player = null;
@ -39,36 +38,50 @@ let isLooping = false;
// Function to play local sahur.mp3
function playAudio() {
if (!connection) return;
try {
if (!connection) {
console.error('[Audio] Connection tidak ditemukan!');
return false;
}
const filePath = path.join(__dirname, 'sahur.mp3');
if (!fs.existsSync(filePath)) {
console.error('File sahur.mp3 tidak ditemukan!');
return;
const filePath = path.join(__dirname, 'sahur.mp3');
console.log(`[Audio] Memutar file dari: ${filePath}`);
if (!fs.existsSync(filePath)) {
console.error(`[Audio] File TIDAK ditemukan di: ${filePath}`);
return false;
}
if (!player) {
console.log('[Audio] Membuat player baru...');
player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Play,
},
});
player.on(AudioPlayerStatus.Idle, () => {
if (isLooping && connection) {
console.log('[Audio] Looping: Memutar ulang sahur.mp3');
playAudio();
}
});
player.on('error', error => {
console.error('[Audio] Player Error:', error.message);
console.error(error);
});
}
const resource = createAudioResource(filePath);
player.play(resource);
connection.subscribe(player);
console.log('[Audio] Berhasil memutar resource.');
return true;
} catch (error) {
console.error('[Audio] Exception di playAudio:', error);
return false;
}
if (!player) {
player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Play,
},
});
player.on(AudioPlayerStatus.Idle, () => {
if (isLooping && connection) {
console.log('Looping: Memutar ulang sahur.mp3');
playAudio();
}
});
player.on('error', error => {
console.error('Error Audio Player:', error.message);
});
}
const resource = createAudioResource(filePath);
player.play(resource);
connection.subscribe(player);
}
// Slash Commands Definition
@ -85,55 +98,87 @@ const rest = new REST({ version: '10' }).setToken(DISCORD_TOKEN);
async function registerCommands() {
try {
console.log('Refreshing application (/) commands...');
await rest.put(Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID), { body: commands });
console.log('Commands registered successfully.');
console.log('Mendaftarkan ulang slash commands (setelah reset)...');
await rest.put(
Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID),
{ body: commands }
);
console.log('Berhasil mendaftarkan command: /join, /test_sahur');
} catch (error) {
console.error('Error registering commands:', error);
console.error('Gagal mendaftarkan command:', error);
}
}
client.on('ready', () => {
console.log(`Bot Online: ${client.user.tag}`);
client.once('ready', () => {
console.log(`Bot logged in as ${client.user.tag}`);
registerCommands();
// Keep-Alive Ping
// Simple Keep-Alive log every 15 minutes
setInterval(() => {
console.log(`[Keep-Alive] Bot still running at ${new Date().toISOString()}`);
}, 10 * 60 * 1000); // Every 10 minutes
console.log(`[Keep-Alive] Bot active at ${new Date().toISOString()}`);
}, 15 * 60 * 1000);
});
client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'join') {
const voiceChannel = interaction.member.voice.channel;
if (!voiceChannel) {
return interaction.reply({ content: 'Kamu harus berada di Voice Channel!', ephemeral: true });
const { commandName } = interaction;
try {
if (commandName === 'join') {
const member = interaction.member;
const voiceChannel = member.voice.channel;
if (!voiceChannel) {
return interaction.reply({ content: 'Kamu harus berada di Voice Channel!', ephemeral: true });
}
connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guildId,
adapterCreator: interaction.guild.voiceAdapterCreator,
});
connection.on(VoiceConnectionStatus.Disconnected, async (oldState, newState) => {
try {
await Promise.race([
enterState(connection, VoiceConnectionStatus.Signalling, 5_000),
enterState(connection, VoiceConnectionStatus.Connecting, 5_000),
]);
} catch (error) {
console.error('[Voice] Gagal menyambung kembali:', error);
if (connection) connection.destroy();
connection = null;
}
});
await interaction.reply({ content: `Bot berhasil join ke ${voiceChannel.name}! ✅` });
}
connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guild.id,
adapterCreator: interaction.guild.voiceAdapterCreator,
});
if (commandName === 'test_sahur') {
if (!connection) {
return interaction.reply({ content: 'Bot harus join ke Voice Channel dulu! Gunakan /join', ephemeral: true });
}
await interaction.reply(`Berhasil join ke <#${voiceChannel.id}>`);
}
if (interaction.commandName === 'test_sahur') {
if (!connection) {
return interaction.reply({ content: 'Gunakan /join terlebih dahulu!', ephemeral: true });
isLooping = true;
const success = playAudio();
if (success) {
await interaction.reply({ content: 'Memutar sahur.mp3 dalam mode loop... 🔁' });
} else {
await interaction.reply({ content: 'Gagal memutar audio. Cek Logs untuk detailnya. ❌', ephemeral: true });
}
}
} catch (error) {
console.error(`[Interaction Error] Command: ${commandName}`, error);
const errorMsg = 'Terjadi kesalahan saat menjalankan command ini. Silakan coba lagi.';
if (interaction.replied || interaction.deferred) {
await interaction.followUp({ content: errorMsg, ephemeral: true });
} else {
await interaction.reply({ content: errorMsg, ephemeral: true });
}
isLooping = true;
playAudio();
await interaction.reply('Memutar sahur.mp3 (Loop aktif 🔁)');
}
});
// Minimal Keep-Alive Web Server
app.get('/', (req, res) => res.send('Bot Sahur is Alive! 🌙'));
app.listen(port, () => console.log(`Keep-Alive server on port ${port}`));
client.login(DISCORD_TOKEN);