This commit is contained in:
Flatlogic Bot 2026-02-16 16:20:35 +00:00
parent 91498377d0
commit 2c48546b22
5 changed files with 198 additions and 33 deletions

67
bot.log
View File

@ -1,4 +1,63 @@
Logged in as AsepXiaoQin#6954 Interaction Error: DiscordAPIError[10062]: Unknown interaction
(node:4352) 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. at handleErrors (/home/ubuntu/executor/workspace/node_modules/@discordjs/rest/dist/index.js:762:13)
(Use `node --trace-deprecation ...` to show where the warning was created) at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
Successfully registered application commands. at async BurstHandler.runRequest (/home/ubuntu/executor/workspace/node_modules/@discordjs/rest/dist/index.js:866:23)
at async _REST.request (/home/ubuntu/executor/workspace/node_modules/@discordjs/rest/dist/index.js:1307:22)
at async ChatInputCommandInteraction.reply (/home/ubuntu/executor/workspace/node_modules/discord.js/src/structures/interfaces/InteractionResponses.js:193:22)
at async Client.<anonymous> (/home/ubuntu/executor/workspace/index.js:68:13) {
requestBody: { files: [], json: { type: 4, data: [Object] } },
rawError: { message: 'Unknown interaction', code: 10062 },
code: 10062,
status: 404,
method: 'POST',
url: 'https://discord.com/api/v10/interactions/1472990887029248135/aW50ZXJhY3Rpb246MTQ3Mjk5MDg4NzAyOTI0ODEzNTp2V1dQTFpXN3IybjBtYmZNcjJxaW5qZnlBR1RQdVpKelhnYjdiRUtWQmI1YW9IbXpZS25WVzQzVVpEWVpSa2hVY3FlamhRYVdlaEt0dVlYRVI5bUNCMVM3bnNmUjZhbDBqZk1RdEhrYXB5R3p6VWZsbUNwQUl6RURGa3hkWEwzaw/callback?with_response=false'
}
(node:7629) Warning: Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead.
(Use `node --trace-warnings ...` to show where the warning was created)
node:events:496
throw er; // Unhandled 'error' event
^
DiscordAPIError[10062]: Unknown interaction
at handleErrors (/home/ubuntu/executor/workspace/node_modules/@discordjs/rest/dist/index.js:762:13)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async BurstHandler.runRequest (/home/ubuntu/executor/workspace/node_modules/@discordjs/rest/dist/index.js:866:23)
at async _REST.request (/home/ubuntu/executor/workspace/node_modules/@discordjs/rest/dist/index.js:1307:22)
at async ChatInputCommandInteraction.reply (/home/ubuntu/executor/workspace/node_modules/discord.js/src/structures/interfaces/InteractionResponses.js:193:22)
at async Client.<anonymous> (/home/ubuntu/executor/workspace/index.js:156:9)
Emitted 'error' event on Client instance at:
at emitUnhandledRejectionOrErr (node:events:401:10)
at process.processTicksAndRejections (node:internal/process/task_queues:92:21) {
requestBody: {
files: [],
json: {
type: 4,
data: {
content: '🔊 Memutar audio Sahur!',
tts: false,
nonce: undefined,
enforce_nonce: false,
embeds: undefined,
components: undefined,
username: undefined,
avatar_url: undefined,
allowed_mentions: undefined,
flags: undefined,
message_reference: undefined,
attachments: undefined,
sticker_ids: undefined,
thread_name: undefined,
applied_tags: undefined,
poll: undefined
}
}
},
rawError: { message: 'Unknown interaction', code: 10062 },
code: 10062,
status: 404,
method: 'POST',
url: 'https://discord.com/api/v10/interactions/1472990887029248135/aW50ZXJhY3Rpb246MTQ3Mjk5MDg4NzAyOTI0ODEzNTp2V1dQTFpXN3IybjBtYmZNcjJxaW5qZnlBR1RQdVpKelhnYjdiRUtWQmI1YW9IbXpZS25WVzQzVVpEWVpSa2hVY3FlamhRYVdlaEt0dVlYRVI5bUNCMVM3bnNmUjZhbDBqZk1RdEhrYXB5R3p6VWZsbUNwQUl6RURGa3hkWEwzaw/callback?with_response=false'
}
Node.js v22.18.0
ode.js v22.18.0

View File

@ -1,6 +1,10 @@
{ {
"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",
"last_voice_channel": null "alarm_time": "23:20",
"last_voice_channel": {
"guildId": "1428530728706117632",
"channelId": "1457687430189682781"
}
} }

View File

@ -0,0 +1,3 @@
-- migrations/003_add_alarm_settings.sql
INSERT IGNORE INTO bot_settings (setting_key, setting_value) VALUES
('alarm_time', '');

140
index.js
View File

@ -1,4 +1,6 @@
process.env.FFMPEG_PATH = require('ffmpeg-static'); process.env.FFMPEG_PATH = require('ffmpeg-static');
console.log('Bot starting...');
const { Client, GatewayIntentBits, SlashCommandBuilder, Routes } = require('discord.js'); const { Client, GatewayIntentBits, SlashCommandBuilder, Routes } = require('discord.js');
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, VoiceConnectionStatus, entersState } = require('@discordjs/voice'); const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, VoiceConnectionStatus, entersState } = require('@discordjs/voice');
const { REST } = require('@discordjs/rest'); const { REST } = require('@discordjs/rest');
@ -16,7 +18,6 @@ function loadConfig() {
const config = loadConfig(); const config = loadConfig();
const token = config.discord_token; const token = config.discord_token;
const guildId = config.guild_id;
if (!token) { if (!token) {
console.error('No Discord Token found in data/config.json'); console.error('No Discord Token found in data/config.json');
@ -32,6 +33,10 @@ const client = new Client({
const player = createAudioPlayer(); const player = createAudioPlayer();
player.on('error', error => {
console.error('Audio Player Error:', error.message);
});
client.on('ready', async () => { client.on('ready', async () => {
console.log(`Logged in as ${client.user.tag}`); console.log(`Logged in as ${client.user.tag}`);
@ -39,29 +44,44 @@ client.on('ready', async () => {
const commands = [ const commands = [
new SlashCommandBuilder() new SlashCommandBuilder()
.setName('testsahur') .setName('testsahur')
.setDescription('Memutar file audio sahur') .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()); ].map(command => command.toJSON());
const rest = new REST({ version: '10' }).setToken(token); const rest = new REST({ version: '10' }).setToken(token);
try { try {
console.log('Started refreshing application (/) commands.');
await rest.put(Routes.applicationCommands(client.user.id), { body: commands }); await rest.put(Routes.applicationCommands(client.user.id), { body: commands });
console.log('Successfully registered application commands.'); console.log('Successfully reloaded application (/) commands.');
} catch (error) { } catch (error) {
console.error(error); console.error('Error reloading commands:', error);
} }
// Auto-reconnect to last voice channel // Auto-reconnect to last voice channel
const lastVoice = config.last_voice_channel; const currentConfig = loadConfig();
const lastVoice = currentConfig.last_voice_channel;
if (lastVoice && lastVoice.guildId && lastVoice.channelId) { if (lastVoice && lastVoice.guildId && lastVoice.channelId) {
console.log(`Auto-rejoining channel ${lastVoice.channelId}`);
joinVC(lastVoice.guildId, lastVoice.channelId); joinVC(lastVoice.guildId, lastVoice.channelId);
} }
}); });
function joinVC(gId, cId) { 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({ const connection = joinVoiceChannel({
channelId: cId, channelId: cId,
guildId: gId, guildId: gId,
adapterCreator: client.guilds.cache.get(gId).voiceAdapterCreator, adapterCreator: guild.voiceAdapterCreator,
selfDeaf: false, selfDeaf: false,
}); });
@ -77,33 +97,103 @@ function joinVC(gId, cId) {
} }
}); });
connection.on('error', error => {
console.error('Voice Connection Error:', error);
});
connection.subscribe(player); connection.subscribe(player);
} }
client.on('interactionCreate', async interaction => { client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return; if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'testsahur') { try {
const member = interaction.member; if (interaction.commandName === 'testsahur') {
if (!member.voice.channel) { const member = interaction.member;
return interaction.reply('Kamu harus berada di Voice Channel!'); 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);
const audioPath = path.join(__dirname, 'assets/audio/sahur.mp3');
if (!fs.existsSync(audioPath)) {
return interaction.reply(`File audio tidak ditemukan: ${audioPath}`);
}
const resource = createAudioResource(audioPath);
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.');
}
} 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 });
} }
const channel = member.voice.channel;
const gId = interaction.guildId;
const cId = channel.id;
// Save last channel
config.last_voice_channel = { guildId: gId, channelId: cId };
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
joinVC(gId, cId);
const resource = createAudioResource(path.join(__dirname, 'assets/audio/sahur.mp3'));
player.play(resource);
await interaction.reply('🔊 Memutar audio Sahur!');
} }
}); });
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);
player.play(resource);
}
} catch (e) {
console.error('Failed to trigger alarm VC:', e);
}
}
}
}
}, 30000); // Check every 30 seconds
client.login(token); client.login(token);

View File

@ -17,16 +17,19 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = $_POST['discord_token'] ?? ''; $token = $_POST['discord_token'] ?? '';
$guild = $_POST['guild_id'] ?? ''; $guild = $_POST['guild_id'] ?? '';
$channel = $_POST['voice_channel_id'] ?? ''; $channel = $_POST['voice_channel_id'] ?? '';
$alarm = $_POST['alarm_time'] ?? '';
save_setting('discord_token', $token); save_setting('discord_token', $token);
save_setting('guild_id', $guild); save_setting('guild_id', $guild);
save_setting('voice_channel_id', $channel); save_setting('voice_channel_id', $channel);
save_setting('alarm_time', $alarm);
// Also update JSON for the bot // Also update JSON for the bot
$config = [ $config = [
'discord_token' => $token, 'discord_token' => $token,
'guild_id' => $guild, 'guild_id' => $guild,
'voice_channel_id' => $channel, 'voice_channel_id' => $channel,
'alarm_time' => $alarm,
'last_voice_channel' => json_decode(get_setting('last_voice_channel'), true) ?: null 'last_voice_channel' => json_decode(get_setting('last_voice_channel'), true) ?: null
]; ];
if (!is_dir(__DIR__ . '/data')) mkdir(__DIR__ . '/data', 0775, true); if (!is_dir(__DIR__ . '/data')) mkdir(__DIR__ . '/data', 0775, true);
@ -38,6 +41,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = get_setting('discord_token'); $token = get_setting('discord_token');
$guildId = get_setting('guild_id'); $guildId = get_setting('guild_id');
$voiceId = get_setting('voice_channel_id'); $voiceId = get_setting('voice_channel_id');
$alarmTime = get_setting('alarm_time');
?> ?>
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
@ -163,6 +167,11 @@ $voiceId = get_setting('voice_channel_id');
<input type="text" name="voice_channel_id" class="form-control" value="<?= htmlspecialchars($voiceId) ?>" placeholder="9876543210..."> <input type="text" name="voice_channel_id" class="form-control" value="<?= htmlspecialchars($voiceId) ?>" placeholder="9876543210...">
</div> </div>
</div> </div>
<div class="mb-3">
<label class="form-label small fw-medium">Alarm Time (HH:MM)</label>
<input type="time" name="alarm_time" class="form-control" value="<?= htmlspecialchars($alarmTime) ?>">
<div class="hint">Bot will automatically join the voice channel and play audio at this time.</div>
</div>
<button type="submit" class="btn btn-primary w-100 mt-2">Save Configuration</button> <button type="submit" class="btn btn-primary w-100 mt-2">Save Configuration</button>
</form> </form>
</div> </div>