Autosave: 20260218-022345
This commit is contained in:
parent
0e42ce02fa
commit
efb0d9f141
24
bot.log
24
bot.log
@ -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
192
index.js
@ -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
10
package-lock.json
generated
@ -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",
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user