| import { Message, EmbedBuilder } from 'discord.js'; | |
| import { | |
| joinVoiceChannel, | |
| createAudioResource, | |
| AudioPlayerStatus, | |
| } from '@discordjs/voice'; | |
| import { get } from 'https'; | |
| import { MusicQueue } from '../utils/MusicQueue'; | |
| import { queues } from '../index'; | |
| import type { Command } from '../types'; | |
| async function playSong(queue: MusicQueue, guildId: string) { | |
| if (queue.songs.length === 0) { | |
| queue.playing = false; | |
| return; | |
| } | |
| queue.playing = true; | |
| queue.currentSong = queue.songs.shift()!; | |
| try { | |
| const stream = await new Promise<Readable>((resolve, reject) => { | |
| get(queue.currentSong.url, (res) => { | |
| if (res.statusCode !== 200) return reject(new Error('Failed to fetch MP3')); | |
| resolve(res); | |
| }).on('error', reject); | |
| }); | |
| const resource = createAudioResource(stream); | |
| queue.player.play(resource); | |
| queue.player.once(AudioPlayerStatus.Idle, () => playSong(queue, guildId)); | |
| } catch (error) { | |
| console.error('Error playing mp3:', error); | |
| queue.playing = false; | |
| } | |
| } | |
| export default <Command>{ | |
| data: { | |
| name: 'play', | |
| description: 'Phát nhạc từ link .mp3', | |
| toJSON() { | |
| return { name: 'play', description: 'Phát nhạc từ link .mp3' }; | |
| }, | |
| }, | |
| ownersOnly: false, | |
| async execute(message: Message, args: string[]) { | |
| const guildId = message.guild?.id; | |
| if (!guildId) return message.reply('❌ Lệnh này chỉ hoạt động trong server.'); | |
| const voiceChannel = message.member?.voice.channel; | |
| if (!voiceChannel) { | |
| return message.reply('❌ Bạn cần tham gia voice channel để phát nhạc.'); | |
| } | |
| const query = args.join(' ').trim(); | |
| if (!query || !query.endsWith('.mp3')) { | |
| return message.reply('❌ Vui lòng cung cấp một link `.mp3` hợp lệ.'); | |
| } | |
| if (!queues.has(guildId)) { | |
| queues.set(guildId, new MusicQueue()); | |
| } | |
| const queue = queues.get(guildId)!; | |
| const song = { | |
| title: query.split('/').pop() || 'MP3 File', | |
| url: query, | |
| duration: 0, | |
| thumbnail: '', | |
| requestedBy: message.author.id, | |
| }; | |
| queue.songs.push(song); | |
| if (!queue.playing) { | |
| if (!queue.connection) { | |
| queue.connection = joinVoiceChannel({ | |
| channelId: voiceChannel.id, | |
| guildId: guildId, | |
| adapterCreator: message.guild!.voiceAdapterCreator, | |
| }); | |
| queue.connection.subscribe(queue.player); | |
| } | |
| playSong(queue, guildId); | |
| } | |
| const embed = new EmbedBuilder() | |
| .setColor('#00ff00') | |
| .setTitle('🎵 Đã thêm vào hàng đợi') | |
| .setDescription(`**${song.title}**`) | |
| .addFields( | |
| { name: 'Vị trí', value: queue.songs.length.toString(), inline: true }, | |
| { name: 'Người yêu cầu', value: `<@${song.requestedBy}>`, inline: true } | |
| ); | |
| await message.reply({ embeds: [embed] }); | |
| }, | |
| }; |