Autosave: 20260218-022345

This commit is contained in:
Flatlogic Bot 2026-02-18 02:23:46 +00:00
parent 0e42ce02fa
commit efb0d9f141
5 changed files with 137 additions and 91 deletions

24
bot.log
View File

@ -1,8 +1,16 @@
Bot Starting... [dotenv@17.3.1] injecting env (2) from .env -- tip: ⚙️ override existing env vars with { override: true }
[dotenv@17.3.1] injecting env (2) from .env -- tip: 🛠️ run anywhere with `dotenvx run -- yourcommand` Logging in...
Keep-Alive aktif di port 8080 ✅ Server Keep-Alive aktif di port 8080
Bot logged in as XiaoMao#2565 Unhandled Rejection: Error [TokenInvalid]: An invalid token was provided.
Memulai refresh slash commands... at WebSocketManager.connect (/home/ubuntu/executor/workspace/node_modules/discord.js/src/client/websocket/WebSocketManager.js:140:26)
(node:20667) 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 Client.login (/home/ubuntu/executor/workspace/node_modules/discord.js/src/client/Client.js:229:21)
(Use `node --trace-deprecation ...` to show where the warning was created) at Object.<anonymous> (/home/ubuntu/executor/workspace/index.js:206:8)
Berhasil mendaftarkan slash commands! at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at TracingChannel.traceSync (node:diagnostics_channel:322:14)
at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:171:5) {
code: 'TokenInvalid'
}

192
index.js
View File

@ -1,17 +1,22 @@
console.log('Bot Starting...');
const { Client, GatewayIntentBits, EmbedBuilder, PermissionsBitField, REST, Routes, SlashCommandBuilder } = require('discord.js'); const { Client, GatewayIntentBits, EmbedBuilder, PermissionsBitField, REST, Routes, SlashCommandBuilder } = require('discord.js');
const { DisTube } = require('distube'); const { DisTube } = require('distube');
const { YtDlpPlugin } = require('@distube/yt-dlp'); const { YtDlpPlugin } = require('@distube/yt-dlp');
const { YouTubePlugin } = require('@distube/youtube'); const { YouTubePlugin } = require('@distube/youtube');
const { GoogleGenerativeAI } = require('@google/generative-ai');
const express = require('express'); const express = require('express');
require('dotenv').config(); require('dotenv').config();
// 1. Keep-Alive System // 1. Keep-Alive Server (Port 8080)
const app = express(); const app = express();
app.get('/', (req, res) => res.send('Bot Musik Online!')); app.get('/', (req, res) => res.send('Wizzy Bot is Online!'));
app.listen(process.env.PORT || 8080, () => console.log('Keep-Alive aktif di port ' + (process.env.PORT || 8080))); const PORT = process.env.PORT || 8080;
app.listen(PORT, () => console.log(`✅ Server Keep-Alive aktif di port ${PORT}`));
// 2. Discord Client Setup // 2. Gemini AI Setup
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
const model = genAI.getGenerativeModel({ model: 'gemini-1.5-flash' });
// 3. Discord Client Setup
const client = new Client({ const client = new Client({
intents: [ intents: [
GatewayIntentBits.Guilds, GatewayIntentBits.Guilds,
@ -21,7 +26,7 @@ const client = new Client({
] ]
}); });
// 3. DisTube Setup // 4. DisTube Setup (Music)
const distube = new DisTube(client, { const distube = new DisTube(client, {
emitNewSongOnly: true, emitNewSongOnly: true,
emitAddSongWhenCreatingQueue: false, emitAddSongWhenCreatingQueue: false,
@ -32,8 +37,15 @@ const distube = new DisTube(client, {
] ]
}); });
// 4. Slash Commands Definition // 5. Slash Commands Definition
const commands = [ const commands = [
new SlashCommandBuilder()
.setName('wizzy')
.setDescription('Tanya Wizzy (Gemini AI)')
.addStringOption(option =>
option.setName('prompt')
.setDescription('Pertanyaanmu untuk Wizzy')
.setRequired(true)),
new SlashCommandBuilder() new SlashCommandBuilder()
.setName('play') .setName('play')
.setDescription('Putar musik dari judul atau link') .setDescription('Putar musik dari judul atau link')
@ -58,123 +70,137 @@ const commands = [
.setDescription('Lanjutkan musik'), .setDescription('Lanjutkan musik'),
].map(command => command.toJSON()); ].map(command => command.toJSON());
// 5. Interaction Handling // 6. Interaction Handling (Slash Commands)
client.on('interactionCreate', async interaction => { client.on('interactionCreate', async interaction => {
await interaction.deferReply().catch(e => console.error(e)); // ⚡ INSTANT DEFER: Prevent 3s Timeout
console.log('--- COMMAND DITERIMA: ' + interaction.commandName + ' ---'); if (interaction.isChatInputCommand()) {
await interaction.deferReply().catch(e => console.error('Defer Error:', e));
}
if (!interaction.isChatInputCommand()) return; if (!interaction.isChatInputCommand()) return;
console.log(`--- Perintah masuk: /${interaction.commandName} ---`);
const { commandName } = interaction; const { commandName } = interaction;
// --- WIZZY (GEMINI AI) HANDLER ---
if (commandName === 'wizzy') {
try {
const userInput = interaction.options.getString('prompt') ?? 'Halo!';
const result = await model.generateContent(userInput);
const response = result.response.text();
const reply = response.length > 1990 ? response.substring(0, 1990) + '...' : response;
await interaction.editReply(reply);
} catch (error) {
console.error('❌ Gemini Error:', error);
await interaction.editReply({ content: '⚠️ Wizzy mengalami error, coba lagi nanti.', ephemeral: true });
}
return;
}
// --- MUSIC HANDLERS ---
if (commandName === 'play') { if (commandName === 'play') {
try { try {
const query = interaction.options.getString('query'); const query = interaction.options.getString('query');
if (!interaction.member.voice.channel) { if (!interaction.member.voice.channel) {
return interaction.editReply('Kamu harus berada di voice channel untuk menggunakan bot ini!'); return interaction.editReply('Kamu harus berada di voice channel!');
} }
await interaction.editReply({ content: `🔍 Mencari: **${query}**...` });
// Memberikan feedback awal
await interaction.editReply({ content: `🔍 Sedang mencari lagu: **${query}**...` });
await distube.play(interaction.member.voice.channel, query, { await distube.play(interaction.member.voice.channel, query, {
textChannel: interaction.channel, textChannel: interaction.channel,
member: interaction.member, member: interaction.member,
interaction interaction
}); });
} catch (error) { } catch (error) {
console.error('Play Error:', error); console.error('Play Error:', error);
await interaction.editReply({ content: `Terjadi kesalahan: ${error.message}` }); await interaction.editReply({ content: `Error: ${error.message}` });
} }
} else if (commandName === 'skip') {
} else {
// Untuk command lain, kita tetap gunakan try-catch global
try { try {
if (!interaction.member.voice.channel) { const queue = distube.getQueue(interaction.guild);
return interaction.editReply('Kamu harus berada di voice channel!'); if (!queue) return interaction.editReply('❌ Tidak ada lagu!');
} await distube.skip(interaction.guild);
await interaction.editReply('⏭️ Lagu dilewati!');
if (commandName === 'skip') { } catch (e) { await interaction.editReply(`❌ Error: ${e.message}`); }
const queue = distube.getQueue(interaction.guild); } else if (commandName === 'stop') {
if (!queue) return interaction.editReply('❌ Tidak ada lagu yang sedang diputar!'); try {
await distube.skip(interaction.guild); await distube.stop(interaction.guild);
await interaction.editReply('⏭️ Lagu berhasil dilewati!'); await interaction.editReply('⏹️ Musik berhenti!');
} catch (e) { await interaction.editReply(`❌ Error: ${e.message}`); }
} else if (commandName === 'stop') { } else if (commandName === 'pause') {
await distube.stop(interaction.guild); try {
await interaction.editReply('⏹️ Musik dihentikan!'); distube.pause(interaction.guild);
await interaction.editReply('⏸️ Musik dijeda!');
} else if (commandName === 'pause') { } catch (e) { await interaction.editReply(`❌ Error: ${e.message}`); }
const queue = distube.getQueue(interaction.guild); } else if (commandName === 'resume') {
if (!queue) return interaction.editReply('❌ Tidak ada antrean!'); try {
distube.pause(interaction.guild); distube.resume(interaction.guild);
await interaction.editReply('⏸️ Musik dijeda!'); await interaction.editReply('▶️ Musik lanjut!');
} catch (e) { await interaction.editReply(`❌ Error: ${e.message}`); }
} else if (commandName === 'resume') { } else if (commandName === 'queue') {
const queue = distube.getQueue(interaction.guild); try {
if (!queue) return interaction.editReply('❌ Tidak ada antrean!'); const queue = distube.getQueue(interaction.guild);
distube.resume(interaction.guild); if (!queue) return interaction.editReply('📭 Antrean kosong!');
await interaction.editReply('▶️ Musik dilanjutkan!'); const q = queue.songs.map((song, i) => `${i === 0 ? '▶️' : `${i}.`} ${song.name}`).join('\n');
await interaction.editReply(`🎶 **Antrean:**\n${q.slice(0, 1900)}`);
} else if (commandName === 'queue') { } catch (e) { await interaction.editReply(`❌ Error: ${e.message}`); }
const queue = distube.getQueue(interaction.guild);
if (!queue) return interaction.editReply('📭 Antrean kosong!');
const q = queue.songs
.map((song, i) => `${i === 0 ? '▶️' : `${i}.`} ${song.name}`)
.join('\n');
await interaction.editReply(`🎶 **Antrean:**\n${q.slice(0, 1900)}`);
}
} catch (error) {
console.error('Interaction Error:', error);
if (interaction.deferred || interaction.replied) {
await interaction.editReply({ content: `❌ Error: ${error.message}` });
}
}
} }
}); });
// 6. DisTube Events // 7. Message Handling (Prefix Command !wizzy)
client.on('messageCreate', async (message) => {
if (message.author.bot) return;
if (!message.content.startsWith('!wizzy ')) return;
const userInput = message.content.slice(7).trim();
if (!userInput) return message.reply('Tulis pertanyaanmu!');
await message.channel.sendTyping();
try {
const result = await model.generateContent(userInput);
const response = result.response.text();
const reply = response.length > 1990 ? response.substring(0, 1990) + '...' : response;
await message.reply(reply);
} catch (error) {
console.error('❌ Error Gemini (Prefix):', error);
await message.reply('⚠️ Terjadi error pada Wizzy!');
}
});
// 8. DisTube Events
distube distube
.on('playSong', (queue, song) => { .on('playSong', (queue, song) => {
queue.textChannel.send(`🎶 Sedang memutar: **${song.name}** - \`${song.formattedDuration}\`\nDiminta oleh: ${song.user}`); queue.textChannel.send(`🎶 Memutar: **${song.name}** (\`${song.formattedDuration}\`)`);
}) })
.on('addSong', (queue, song) => { .on('addSong', (queue, song) => {
queue.textChannel.send(`✅ Menambahkan **${song.name}** ke antrean!`); queue.textChannel.send(`Ditambahkan: **${song.name}**`);
}) })
.on('error', (channel, e) => { .on('error', (channel, e) => {
if (channel && channel.send) { if (channel?.send) channel.send(`❌ DisTube Error: ${e.message.slice(0, 1000)}`);
const errorMessage = e && e.message ? e.message.slice(0, 1900) : "Unknown Error";
channel.send(`❌ Error: ${errorMessage}`).catch(console.error);
}
console.error('DisTube Error:', e); console.error('DisTube Error:', e);
}); });
// 7. Client Ready & Command Registration // 9. Ready Event & Command Registration
client.once('ready', async () => { client.once('ready', async () => {
console.log(`Bot logged in as ${client.user.tag}`); console.log(`✅ Wizzy aktif sebagai ${client.user.tag}`);
console.log('Bot siap memproses perintah!');
// Register Global Slash Commands
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN); const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
try { try {
console.log('Memulai refresh slash commands...'); console.log('Registering slash commands...');
await rest.put( await rest.put(
Routes.applicationCommands(client.user.id), Routes.applicationCommands(client.user.id),
{ body: commands }, { body: commands },
); );
console.log('Berhasil mendaftarkan slash commands!'); console.log('Successfully registered slash commands!');
} catch (error) { } catch (error) {
console.error(error); console.error('Registration Error:', error);
} }
}); });
// 8. Global Error Handling (Anti-Crash) // 10. Anti-Crash
process.on('unhandledRejection', error => { process.on('unhandledRejection', e => console.error('Unhandled Rejection:', e));
console.error('Unhandled promise rejection:', error); process.on('uncaughtException', e => console.error('Uncaught Exception:', e));
});
process.on('uncaughtException', error => { // 11. Login
console.error('Uncaught exception:', error); console.log('Logging in...');
}); client.login(process.env.DISCORD_TOKEN);
client.login('MTQ3Mjc2ODQ4NTQ0NzY5NjY1MA.Gx78sk.NGDrdd51zwcDbqyVrupL78RlUZdUSgmGvzn3pw');

10
package-lock.json generated
View File

@ -12,6 +12,7 @@
"@discordjs/voice": "^0.19.0", "@discordjs/voice": "^0.19.0",
"@distube/youtube": "^1.0.4", "@distube/youtube": "^1.0.4",
"@distube/yt-dlp": "^2.0.1", "@distube/yt-dlp": "^2.0.1",
"@google/generative-ai": "^0.24.1",
"@snazzah/davey": "^0.1.9", "@snazzah/davey": "^0.1.9",
"discord-api-types": "^0.38.39", "discord-api-types": "^0.38.39",
"discord.js": "^14.25.1", "discord.js": "^14.25.1",
@ -340,6 +341,15 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@google/generative-ai": {
"version": "0.24.1",
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.24.1.tgz",
"integrity": "sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==",
"license": "Apache-2.0",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@napi-rs/wasm-runtime": { "node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",

View File

@ -14,6 +14,7 @@
"@discordjs/voice": "^0.19.0", "@discordjs/voice": "^0.19.0",
"@distube/youtube": "^1.0.4", "@distube/youtube": "^1.0.4",
"@distube/yt-dlp": "^2.0.1", "@distube/yt-dlp": "^2.0.1",
"@google/generative-ai": "^0.24.1",
"@snazzah/davey": "^0.1.9", "@snazzah/davey": "^0.1.9",
"discord-api-types": "^0.38.39", "discord-api-types": "^0.38.39",
"discord.js": "^14.25.1", "discord.js": "^14.25.1",

1
test.js Normal file
View File

@ -0,0 +1 @@
console.log('test')