Autosave: 20260217-115844
This commit is contained in:
parent
bc6c1b2066
commit
c8f71ad732
@ -2,6 +2,6 @@
|
|||||||
"discord_token": "MTQ3MTkwOTE5Mzg4Njg1OTI5NA.GCEdpc.jMIxPFsquVAhp88x3dO-yWUFI7e1u1r8oIZTcw",
|
"discord_token": "MTQ3MTkwOTE5Mzg4Njg1OTI5NA.GCEdpc.jMIxPFsquVAhp88x3dO-yWUFI7e1u1r8oIZTcw",
|
||||||
"guild_id": "1428530728706117632",
|
"guild_id": "1428530728706117632",
|
||||||
"voice_channel_id": "1457687430189682781",
|
"voice_channel_id": "1457687430189682781",
|
||||||
"alarm_time": "15:33",
|
"alarm_time": "18:55",
|
||||||
"last_voice_channel": null
|
"last_voice_channel": null
|
||||||
}
|
}
|
||||||
151
index.js
151
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 { Client, GatewayIntentBits, SlashCommandBuilder, Routes } = require('discord.js');
|
||||||
const { joinVoiceChannel, createAudioPlayer, createAudioResource, StreamType, getVoiceConnection } = require('@discordjs/voice');
|
const { joinVoiceChannel, createAudioPlayer, createAudioResource, StreamType, getVoiceConnection } = require('@discordjs/voice');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@ -8,8 +5,7 @@ const path = require('path');
|
|||||||
const { REST } = require('@discordjs/rest');
|
const { REST } = require('@discordjs/rest');
|
||||||
|
|
||||||
// Load Config
|
// Load Config
|
||||||
const configPath = path.join(__dirname, 'data/config.json');
|
const config = JSON.parse(fs.readFileSync('./data/config.json', 'utf8'));
|
||||||
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
||||||
const token = config.discord_token;
|
const token = config.discord_token;
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
@ -18,120 +14,109 @@ const client = new Client({
|
|||||||
|
|
||||||
const player = createAudioPlayer();
|
const player = createAudioPlayer();
|
||||||
|
|
||||||
// Monitoring Status
|
player.on('error', err => {
|
||||||
player.on('stateChange', (oldState, newState) => {
|
console.log('LOG ERROR AUDIO:', err.message);
|
||||||
console.log(`Status Player: ${newState.status}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
player.on('error', error => {
|
player.on('stateChange', (old, current) => {
|
||||||
console.log('ERROR AUDIO:', error.message);
|
console.log('Status Audio Saat Ini:', current.status);
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('ready', async () => {
|
client.on('ready', async () => {
|
||||||
console.log(`Bot Sahur Online: ${client.user.tag}`);
|
console.log(`Bot Minimalis Ready: ${client.user.tag}`);
|
||||||
|
|
||||||
const commands = [
|
const commands = [
|
||||||
new SlashCommandBuilder().setName('join').setDescription('Perintah untuk bot masuk ke Voice Channel'),
|
new SlashCommandBuilder().setName('join').setDescription('Bot join ke Voice Channel'),
|
||||||
new SlashCommandBuilder().setName('testsahur').setDescription('Perintah untuk memutar suara alarm sahur')
|
new SlashCommandBuilder().setName('testsahur').setDescription('Tes putar sahur.mp3')
|
||||||
].map(cmd => cmd.toJSON());
|
].map(cmd => cmd.toJSON());
|
||||||
|
|
||||||
const rest = new REST({ version: '10' }).setToken(token);
|
const rest = new REST({ version: '10' }).setToken(token);
|
||||||
try {
|
try {
|
||||||
await rest.put(Routes.applicationCommands(client.user.id), { body: commands });
|
await rest.put(Routes.applicationCommands(client.user.id), { body: commands });
|
||||||
console.log('Slash Commands Berhasil Didaftarkan.');
|
console.log('Slash Commands registered.');
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.error('Gagal daftar command:', err);
|
console.error('Error registering commands:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('interactionCreate', async interaction => {
|
client.on('interactionCreate', async interaction => {
|
||||||
if (!interaction.isChatInputCommand()) return;
|
if (!interaction.isChatInputCommand()) return;
|
||||||
|
|
||||||
// 1. PERINTAH JOIN (Hanya Masuk)
|
// Fix untuk /join
|
||||||
if (interaction.commandName === 'join') {
|
if (interaction.commandName === 'join') {
|
||||||
await interaction.deferReply();
|
// Gunakan Defer Reply di awal
|
||||||
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') {
|
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
|
||||||
let connection = getVoiceConnection(interaction.guildId);
|
try {
|
||||||
const channel = interaction.member.voice.channel;
|
const channel = interaction.member.voice.channel;
|
||||||
|
if (!channel) return interaction.editReply('Masuk ke VC dulu!');
|
||||||
|
|
||||||
// Auto-Reconnect: Jika tidak ada koneksi, join dulu
|
joinVoiceChannel({
|
||||||
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({
|
|
||||||
channelId: channel.id,
|
channelId: channel.id,
|
||||||
guildId: interaction.guildId,
|
guildId: interaction.guildId,
|
||||||
adapterCreator: interaction.guild.voiceAdapterCreator,
|
adapterCreator: interaction.guild.voiceAdapterCreator,
|
||||||
selfDeaf: false,
|
selfDeaf: false,
|
||||||
selfMute: 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 {
|
try {
|
||||||
const audioPath = path.join(process.cwd(), 'assets', 'audio', 'sahur.mp3');
|
const channel = interaction.member.voice.channel;
|
||||||
console.log('Membaca file audio di:', audioPath);
|
if (!channel) return interaction.editReply('Masuk ke VC dulu!');
|
||||||
|
|
||||||
if (!fs.existsSync(audioPath)) {
|
const connection = joinVoiceChannel({
|
||||||
return interaction.editReply('❌ File audio tidak ditemukan!');
|
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,
|
inputType: StreamType.Arbitrary,
|
||||||
inlineVolume: true
|
inlineVolume: true
|
||||||
});
|
});
|
||||||
|
|
||||||
resource.volume.setVolume(1.5);
|
// Debug Status
|
||||||
connection.subscribe(player);
|
console.log('Resource Readable:', resource.readable);
|
||||||
|
console.log('Connection Status:', connection.state.status);
|
||||||
|
|
||||||
|
// Kabel Utama (Subscribe)
|
||||||
|
const subscription = connection.subscribe(player);
|
||||||
player.play(resource);
|
player.play(resource);
|
||||||
|
|
||||||
console.log('Kabel audio tersambung dan suara diputar!');
|
await interaction.editReply('🔊 Sedang memutar sahur.mp3...');
|
||||||
await interaction.editReply('🔊 Sedang memutar alarm sahur (Auto-Connect Aktif)...');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('ERROR AUDIO:', error.message);
|
// Anti-Stuck: Tangkap error agar tidak diam saja
|
||||||
await interaction.editReply('❌ Terjadi kesalahan: ' + error.message);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user