import { AudioPlayerStatus, AudioResource, createAudioPlayer, createAudioResource, VoiceConnection } from "@discordjs/voice"; import { stream as createStream } from "play-dl"; import { Guild } from "discord.js"; import { getOrCreateVoiceConnection } from "./util"; import { OutputHandler } from "../utils/outputHandler"; import play from "play-dl"; namespace InitPlayDl { let initialized = false; export async function init() { if (initialized) return; await play.getFreeClientID(); initialized = true; } } class MusicQueue { private connection: VoiceConnection; private list: AudioResource[]; constructor(connection: VoiceConnection) { this.connection = connection; this.list = []; } public static fromConnection(connection: VoiceConnection): MusicQueue { return (connection as any).queue ??= new MusicQueue(connection); } private play() { if (!this.list[0]) return; const player = createAudioPlayer(); this.connection.subscribe(player); player.once(AudioPlayerStatus.Idle, this.next.bind(this)); player.play(this.list[0]); } public enqueue(resource: AudioResource) { this.list.push(resource); if (this.list.length == 1) { this.play(); return; } } public next() { this.list.shift(); this.play(); } } // TODO: 토큰 설정하고 플레이돼게 만들기 export async function playMusic(guild: Guild, url: string) { try { const connection = await getOrCreateVoiceConnection(guild); if (!connection) throw new Error("Yaeju is not joined VoiceChat"); await InitPlayDl.init(); const validation = play.yt_validate(url); if (validation !== "video" && validation !== "playlist") throw new Error("Invalid YouTube URL: " + validation); const stream = await play.stream(url); MusicQueue.fromConnection(connection).enqueue( createAudioResource(stream.stream, { inputType: stream.type }) ); } catch(err) { OutputHandler.errorLog("[PlayMusic Error]", err); throw err; } } export async function skipMusic(guild: Guild) { const connection = await getOrCreateVoiceConnection(guild); if (!connection) throw new Error("Yaeju is not joined VoiceChat"); MusicQueue.fromConnection(connection).next(); }