187 lines
6.3 KiB
JavaScript
187 lines
6.3 KiB
JavaScript
require('dotenv').config();
|
|
const { Client, GatewayIntentBits } = require('discord.js');
|
|
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, NoSubscriberBehavior } = require('@discordjs/voice');
|
|
const { CronJob } = require('cron');
|
|
const path = require('path');
|
|
const play = require('play-dl');
|
|
|
|
const client = new Client({
|
|
intents: [
|
|
GatewayIntentBits.Guilds,
|
|
GatewayIntentBits.GuildVoiceStates,
|
|
GatewayIntentBits.GuildMessages,
|
|
GatewayIntentBits.MessageContent,
|
|
]
|
|
});
|
|
|
|
const VC_ID = process.env.VC_ID;
|
|
const AUDIO_PATH = path.join(__dirname, '../assets/audio/sahur.mp3');
|
|
const PREFIX = '!';
|
|
|
|
// Global state
|
|
const queues = new Map(); // guildId -> { queue: [], player, connection }
|
|
|
|
client.once('ready', () => {
|
|
console.log(`Logged in as ${client.user.tag}!`);
|
|
|
|
// Sahur Alarm
|
|
new CronJob('30 03 * * *', async () => {
|
|
if (!VC_ID) return;
|
|
const guild = client.guilds.cache.first();
|
|
const channel = guild.channels.cache.get(VC_ID);
|
|
if (channel) {
|
|
playLocal(channel, AUDIO_PATH);
|
|
}
|
|
}, null, true, 'Asia/Jakarta');
|
|
});
|
|
|
|
async function playLocal(channel, filePath) {
|
|
const connection = joinVoiceChannel({
|
|
channelId: channel.id,
|
|
guildId: channel.guild.id,
|
|
adapterCreator: channel.guild.voiceAdapterCreator,
|
|
});
|
|
|
|
const player = createAudioPlayer();
|
|
const resource = createAudioResource(filePath);
|
|
player.play(resource);
|
|
connection.subscribe(player);
|
|
|
|
player.once(AudioPlayerStatus.Idle, () => {
|
|
connection.destroy();
|
|
});
|
|
}
|
|
|
|
client.on('messageCreate', async (message) => {
|
|
if (message.author.bot || !message.content.startsWith(PREFIX)) return;
|
|
|
|
const args = message.content.slice(PREFIX.length).trim().split(/ +/);
|
|
const command = args.shift().toLowerCase();
|
|
const voiceChannel = message.member?.voice.channel;
|
|
|
|
if (command === 'join') {
|
|
if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
|
|
joinVoiceChannel({
|
|
channelId: voiceChannel.id,
|
|
guildId: message.guild.id,
|
|
adapterCreator: message.guild.voiceAdapterCreator,
|
|
});
|
|
message.reply('Sudah join! 🎧');
|
|
}
|
|
|
|
if (command === 'testsahur') {
|
|
if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
|
|
playLocal(voiceChannel, AUDIO_PATH);
|
|
message.reply('Memainkan suara sahur... 📢');
|
|
}
|
|
|
|
if (command === 'play') {
|
|
if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
|
|
const query = args.join(' ');
|
|
if (!query) return message.reply('Berikan link atau nama lagu!');
|
|
|
|
let serverQueue = queues.get(message.guild.id);
|
|
|
|
if (!serverQueue) {
|
|
serverQueue = {
|
|
songs: [],
|
|
connection: null,
|
|
player: createAudioPlayer({
|
|
behaviors: { noSubscriber: NoSubscriberBehavior.Play }
|
|
}),
|
|
};
|
|
queues.set(message.guild.id, serverQueue);
|
|
}
|
|
|
|
try {
|
|
message.reply('Mencari lagu... 🔍');
|
|
|
|
let songInfo;
|
|
if (play.sp_validate(query) === 'track') {
|
|
const sp_data = await play.spotify(query);
|
|
const search = await play.search(`${sp_data.name} ${sp_data.artists[0].name}`, { limit: 1 });
|
|
songInfo = { title: sp_data.name, url: search[0].url };
|
|
} else if (play.so_validate(query)) {
|
|
const so_data = await play.soundcloud(query);
|
|
songInfo = { title: so_data.name, url: so_data.url };
|
|
} else {
|
|
const yt_info = await play.search(query, { limit: 1 });
|
|
if (yt_info.length === 0) return message.reply('Lagu tidak ditemukan!');
|
|
songInfo = { title: yt_info[0].title, url: yt_info[0].url };
|
|
}
|
|
|
|
serverQueue.songs.push(songInfo);
|
|
|
|
if (serverQueue.songs.length === 1) {
|
|
playSong(message.guild.id, voiceChannel);
|
|
message.channel.send(`🎵 Sekarang memutar: **${songInfo.title}**`);
|
|
} else {
|
|
message.channel.send(`✅ **${songInfo.title}** ditambahkan ke antrean.`);
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
message.reply('Gagal memutar lagu.');
|
|
}
|
|
}
|
|
|
|
if (command === 'skip') {
|
|
const serverQueue = queues.get(message.guild.id);
|
|
if (!serverQueue) return message.reply('Tidak ada lagu yang sedang diputar!');
|
|
serverQueue.player.stop();
|
|
message.reply('Lagu dilewati! ⏭️');
|
|
}
|
|
|
|
if (command === 'stop') {
|
|
const serverQueue = queues.get(message.guild.id);
|
|
if (serverQueue) {
|
|
serverQueue.songs = [];
|
|
serverQueue.player.stop();
|
|
if (serverQueue.connection) serverQueue.connection.destroy();
|
|
queues.delete(message.guild.id);
|
|
}
|
|
message.reply('Musik dihentikan. 👋');
|
|
}
|
|
|
|
if (command === 'pause') {
|
|
const serverQueue = queues.get(message.guild.id);
|
|
if (serverQueue) serverQueue.player.pause();
|
|
message.reply('Dipause. ⏸️');
|
|
}
|
|
|
|
if (command === 'resume') {
|
|
const serverQueue = queues.get(message.guild.id);
|
|
if (serverQueue) serverQueue.player.unpause();
|
|
message.reply('Dilanjutkan. ▶️');
|
|
}
|
|
});
|
|
|
|
async function playSong(guildId, channel) {
|
|
const serverQueue = queues.get(guildId);
|
|
if (serverQueue.songs.length === 0) {
|
|
// Leave after some time if needed, for now just stay
|
|
return;
|
|
}
|
|
|
|
const song = serverQueue.songs[0];
|
|
const stream = await play.stream(song.url);
|
|
const resource = createAudioResource(stream.stream, { inputType: stream.type });
|
|
|
|
if (!serverQueue.connection) {
|
|
serverQueue.connection = joinVoiceChannel({
|
|
channelId: channel.id,
|
|
guildId: guildId,
|
|
adapterCreator: channel.guild.voiceAdapterCreator,
|
|
});
|
|
serverQueue.connection.subscribe(serverQueue.player);
|
|
}
|
|
|
|
serverQueue.player.play(resource);
|
|
|
|
serverQueue.player.once(AudioPlayerStatus.Idle, () => {
|
|
serverQueue.songs.shift();
|
|
playSong(guildId, channel);
|
|
});
|
|
}
|
|
|
|
client.login(process.env.DISCORD_TOKEN);
|