Autosave: 20260216-163403
This commit is contained in:
parent
12a425c3fc
commit
fe99f09665
38
bot.log
38
bot.log
@ -4,3 +4,41 @@ Started refreshing application (/) commands.
|
||||
(node:8584) 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.
|
||||
Interaction Error: Error: Error: Cannot find module '@discordjs/opus'
|
||||
Require stack:
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/util/loader.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/Opus.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/index.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/index.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js
|
||||
- /home/ubuntu/executor/workspace/index.js
|
||||
Error: Cannot find module 'node-opus'
|
||||
Require stack:
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/util/loader.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/Opus.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/index.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/index.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js
|
||||
- /home/ubuntu/executor/workspace/index.js
|
||||
Error: Cannot find module 'opusscript'
|
||||
Require stack:
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/util/loader.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/Opus.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/index.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/prism-media/src/index.js
|
||||
- /home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js
|
||||
- /home/ubuntu/executor/workspace/index.js
|
||||
at Object.loader [as require] (/home/ubuntu/executor/workspace/node_modules/prism-media/src/util/loader.js:12:9)
|
||||
at loadOpus (/home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/Opus.js:17:17)
|
||||
at new OpusStream (/home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/Opus.js:46:10)
|
||||
at new Encoder (/home/ubuntu/executor/workspace/node_modules/prism-media/src/opus/Opus.js:149:5)
|
||||
at Object.transformer (/home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js:2224:24)
|
||||
at /home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js:2457:58
|
||||
at Array.map (<anonymous>)
|
||||
at createAudioResource (/home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js:2457:39)
|
||||
at Client.<anonymous> (/home/ubuntu/executor/workspace/index.js:138:30)
|
||||
at Client.emit (node:events:518:28)
|
||||
(node:8584) Warning: Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead.
|
||||
Voice Connection Error: Error: No compatible encryption modes. Available include: aead_aes256_gcm_rtpsize, aead_xchacha20_poly1305_rtpsize
|
||||
at chooseEncryptionMode (/home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js:529:11)
|
||||
at /home/ubuntu/executor/workspace/node_modules/@discordjs/voice/dist/index.js:721:21
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
"discord_token": "MTQ3MTkwOTE5Mzg4Njg1OTI5NA.GCEdpc.jMIxPFsquVAhp88x3dO-yWUFI7e1u1r8oIZTcw",
|
||||
"guild_id": "1428530728706117632",
|
||||
"voice_channel_id": "1457687430189682781",
|
||||
"alarm_time": "23:27",
|
||||
"alarm_time": "23:35",
|
||||
"last_voice_channel": null
|
||||
}
|
||||
204
index.js
204
index.js
@ -1,206 +1,96 @@
|
||||
process.env.FFMPEG_PATH = require('ffmpeg-static');
|
||||
console.log('Bot starting...');
|
||||
|
||||
const { Client, GatewayIntentBits, SlashCommandBuilder, Routes } = require('discord.js');
|
||||
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, VoiceConnectionStatus, entersState } = require('@discordjs/voice');
|
||||
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus } = require('@discordjs/voice');
|
||||
const { REST } = require('@discordjs/rest');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Load Discord Token
|
||||
const configPath = path.join(__dirname, 'data/config.json');
|
||||
|
||||
function loadConfig() {
|
||||
if (fs.existsSync(configPath)) {
|
||||
return JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
const config = loadConfig();
|
||||
const config = fs.existsSync(configPath) ? JSON.parse(fs.readFileSync(configPath, 'utf8')) : {};
|
||||
const token = config.discord_token;
|
||||
|
||||
if (!token) {
|
||||
console.error('No Discord Token found in data/config.json');
|
||||
console.error('ERROR: discord_token not found in data/config.json');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const client = new Client({
|
||||
intents: [
|
||||
GatewayIntentBits.Guilds,
|
||||
GatewayIntentBits.GuildVoiceStates,
|
||||
]
|
||||
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates]
|
||||
});
|
||||
|
||||
const player = createAudioPlayer();
|
||||
|
||||
// Stay 24/7 Logic: Do nothing when idle (prevents automatic leave)
|
||||
player.on(AudioPlayerStatus.Idle, () => {
|
||||
console.log('Audio finished playing. Bot will stay in the channel.');
|
||||
console.log('Audio finished. Bot is staying in the channel (Stay 24/7).');
|
||||
});
|
||||
|
||||
player.on('error', error => {
|
||||
console.error('Audio Player Error:', error.message);
|
||||
});
|
||||
player.on('error', error => console.error('Audio Player Error:', error));
|
||||
|
||||
client.on('ready', async () => {
|
||||
console.log(`Logged in as ${client.user.tag}`);
|
||||
|
||||
// Register commands
|
||||
async function deployCommands(clientId) {
|
||||
const commands = [
|
||||
new SlashCommandBuilder()
|
||||
.setName('testsahur')
|
||||
.setDescription('Memutar file audio sahur'),
|
||||
new SlashCommandBuilder()
|
||||
.setName('join')
|
||||
.setDescription('Menyuruh bot join ke voice channel kamu'),
|
||||
new SlashCommandBuilder()
|
||||
.setName('stop')
|
||||
.setDescription('Menghentikan pemutaran audio')
|
||||
].map(command => command.toJSON());
|
||||
new SlashCommandBuilder().setName('join').setDescription('Bot masuk ke Voice Channel user'),
|
||||
new SlashCommandBuilder().setName('testsahur').setDescription('Memutar file sahur secara instan')
|
||||
].map(cmd => cmd.toJSON());
|
||||
|
||||
const rest = new REST({ version: '10' }).setToken(token);
|
||||
try {
|
||||
console.log('Started refreshing application (/) commands.');
|
||||
await rest.put(Routes.applicationCommands(client.user.id), { body: commands });
|
||||
console.log('Successfully reloaded application (/) commands.');
|
||||
} catch (error) {
|
||||
console.error('Error reloading commands:', error);
|
||||
await rest.put(Routes.applicationCommands(clientId), { body: commands });
|
||||
console.log('Slash commands deployed successfully.');
|
||||
} catch (err) {
|
||||
console.error('Failed to deploy commands:', err);
|
||||
}
|
||||
|
||||
// Auto-reconnect to last voice channel
|
||||
const currentConfig = loadConfig();
|
||||
const lastVoice = currentConfig.last_voice_channel;
|
||||
if (lastVoice && lastVoice.guildId && lastVoice.channelId) {
|
||||
console.log(`Auto-rejoining channel ${lastVoice.channelId}`);
|
||||
joinVC(lastVoice.guildId, lastVoice.channelId);
|
||||
}
|
||||
});
|
||||
|
||||
function joinVC(gId, cId) {
|
||||
const guild = client.guilds.cache.get(gId);
|
||||
if (!guild) {
|
||||
console.error(`Guild ${gId} not found in cache`);
|
||||
return;
|
||||
}
|
||||
|
||||
const connection = joinVoiceChannel({
|
||||
channelId: cId,
|
||||
guildId: gId,
|
||||
adapterCreator: guild.voiceAdapterCreator,
|
||||
selfDeaf: false,
|
||||
selfMute: false,
|
||||
});
|
||||
|
||||
connection.on(VoiceConnectionStatus.Disconnected, async () => {
|
||||
try {
|
||||
await Promise.race([
|
||||
entersState(connection, VoiceConnectionStatus.Signalling, 5_000),
|
||||
entersState(connection, VoiceConnectionStatus.Connecting, 5_000),
|
||||
]);
|
||||
} catch (error) {
|
||||
console.log('Connection lost, attempting to reconnect...');
|
||||
setTimeout(() => joinVC(gId, cId), 5000);
|
||||
}
|
||||
});
|
||||
|
||||
connection.on('error', error => {
|
||||
console.error('Voice Connection Error:', error);
|
||||
});
|
||||
|
||||
connection.subscribe(player);
|
||||
}
|
||||
|
||||
client.on('ready', async () => {
|
||||
console.log(`Bot logged in as ${client.user.tag}`);
|
||||
await deployCommands(client.user.id);
|
||||
});
|
||||
|
||||
client.on('interactionCreate', async interaction => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
// Anti-Timeout logic
|
||||
if (!interaction.deferred) await interaction.deferReply();
|
||||
|
||||
const { commandName, member } = interaction;
|
||||
|
||||
if (!member.voice.channel) {
|
||||
return interaction.editReply('Silakan masuk ke Voice Channel terlebih dahulu!');
|
||||
}
|
||||
|
||||
try {
|
||||
if (interaction.commandName === 'testsahur') {
|
||||
const member = interaction.member;
|
||||
if (!member.voice.channel) {
|
||||
return interaction.reply('Kamu harus berada di Voice Channel!');
|
||||
}
|
||||
const connection = joinVoiceChannel({
|
||||
channelId: member.voice.channel.id,
|
||||
guildId: interaction.guildId,
|
||||
adapterCreator: interaction.guild.voiceAdapterCreator,
|
||||
selfDeaf: false,
|
||||
selfMute: false,
|
||||
});
|
||||
|
||||
const channel = member.voice.channel;
|
||||
const gId = interaction.guildId;
|
||||
const cId = channel.id;
|
||||
connection.subscribe(player);
|
||||
|
||||
// Save last channel
|
||||
const currentConfig = loadConfig();
|
||||
currentConfig.last_voice_channel = { guildId: gId, channelId: cId };
|
||||
fs.writeFileSync(configPath, JSON.stringify(currentConfig, null, 2));
|
||||
|
||||
joinVC(gId, cId);
|
||||
if (commandName === 'join') {
|
||||
return interaction.editReply('Sudah join! 🎵');
|
||||
}
|
||||
|
||||
if (commandName === 'testsahur') {
|
||||
const audioPath = path.join(__dirname, 'assets/audio/sahur.mp3');
|
||||
if (!fs.existsSync(audioPath)) {
|
||||
return interaction.reply(`File audio tidak ditemukan: ${audioPath}`);
|
||||
return interaction.editReply('File ./assets/audio/sahur.mp3 tidak ditemukan!');
|
||||
}
|
||||
|
||||
const resource = createAudioResource(audioPath, { inlineVolume: true });
|
||||
resource.volume.setVolume(1.0);
|
||||
resource.volume.setVolume(1.0); // Max Volume
|
||||
player.play(resource);
|
||||
|
||||
await interaction.reply('🔊 Memutar audio Sahur!');
|
||||
} else if (interaction.commandName === 'join') {
|
||||
const member = interaction.member;
|
||||
if (!member.voice.channel) {
|
||||
return interaction.reply('Kamu harus berada di Voice Channel!');
|
||||
}
|
||||
|
||||
const channel = member.voice.channel;
|
||||
const gId = interaction.guildId;
|
||||
const cId = channel.id;
|
||||
|
||||
// Save last channel
|
||||
const currentConfig = loadConfig();
|
||||
currentConfig.last_voice_channel = { guildId: gId, channelId: cId };
|
||||
fs.writeFileSync(configPath, JSON.stringify(currentConfig, null, 2));
|
||||
|
||||
joinVC(gId, cId);
|
||||
await interaction.reply('✅ Bot telah bergabung ke Voice Channel!');
|
||||
} else if (interaction.commandName === 'stop') {
|
||||
player.stop();
|
||||
await interaction.reply('🛑 Audio dihentikan.');
|
||||
return interaction.editReply('Memutar suara sahur... 🔊');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Interaction Error:', error);
|
||||
if (interaction.replied || interaction.deferred) {
|
||||
await interaction.followUp({ content: 'Terjadi kesalahan saat menjalankan command!', ephemeral: true });
|
||||
} else {
|
||||
await interaction.reply({ content: 'Terjadi kesalahan saat menjalankan command!', ephemeral: true });
|
||||
}
|
||||
console.error('Error during interaction:', error);
|
||||
return interaction.editReply('Terjadi kesalahan teknis.');
|
||||
}
|
||||
});
|
||||
|
||||
let lastAlarmMinute = -1;
|
||||
setInterval(() => {
|
||||
const now = new Date();
|
||||
const currentMinute = now.getMinutes();
|
||||
|
||||
if (currentMinute !== lastAlarmMinute) {
|
||||
lastAlarmMinute = currentMinute;
|
||||
|
||||
const currentTime = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
|
||||
const currentConfig = loadConfig();
|
||||
|
||||
if (currentConfig.alarm_time === currentTime) {
|
||||
console.log(`Alarm triggered at ${currentTime}`);
|
||||
const lastVoice = currentConfig.last_voice_channel;
|
||||
|
||||
if (lastVoice && lastVoice.guildId && lastVoice.channelId) {
|
||||
try {
|
||||
joinVC(lastVoice.guildId, lastVoice.channelId);
|
||||
const audioPath = path.join(__dirname, 'assets/audio/sahur.mp3');
|
||||
if (fs.existsSync(audioPath)) {
|
||||
const resource = createAudioResource(audioPath, { inlineVolume: true });
|
||||
resource.volume.setVolume(1.0);
|
||||
player.play(resource);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to trigger alarm VC:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 30000); // Check every 30 seconds
|
||||
|
||||
client.login(token);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user