src/functions/myqueue.ts (view raw)
1import { createAudioResource, createAudioPlayer, NoSubscriberBehavior, AudioPlayerStatus, VoiceConnection, AudioPlayer } from '@discordjs/voice';
2import play, { YouTubeVideo } from 'play-dl';
3
4async function resourceFromYTUrl(url: string) {
5 const stream = await play.stream(url);
6 return createAudioResource(stream.stream, { inputType: stream.type })
7}
8
9export default class MyQueue {
10 #nowPlaying: YouTubeVideo;
11 #queue: Array<YouTubeVideo>;
12 connection: VoiceConnection;
13 player: AudioPlayer;
14 static _instance: MyQueue;
15 get queue() {
16 if (this.#nowPlaying)
17 return [this.#nowPlaying].concat(this.#queue);
18 return null
19 }
20
21 constructor() {
22 if (MyQueue._instance) {
23 return MyQueue._instance
24 }
25 MyQueue._instance = this;
26
27 this.#nowPlaying = null;
28 this.connection = null;
29 this.#queue = Array<YouTubeVideo>();
30 this.player = createAudioPlayer({ behaviors: { noSubscriber: NoSubscriberBehavior.Stop } });
31 this.player.on(AudioPlayerStatus.Idle, () => {
32 if (this.#queue.length > 0)
33 return this.next();
34 this.connection.disconnect();
35 });
36 }
37
38 clear() {
39 this.#queue = Array<YouTubeVideo>();
40 }
41
42 stop() {
43 this.clear();
44 this.#nowPlaying = null;
45 if (this.player) return this.player.stop();
46 return false;
47 }
48
49 async next() {
50 if (this.#queue.length == 0)
51 return this.stop();
52 this.#nowPlaying = this.#queue.shift();
53 const resource = await resourceFromYTUrl(this.#nowPlaying.url);
54 this.player.play(resource);
55 this.connection.subscribe(this.player);
56 }
57
58 add(video: YouTubeVideo, position=this.#queue.length) {
59 const l = this.#queue.length;
60 const normalizedPosition = position % (l + 1);
61 this.#queue.splice(normalizedPosition, 0, video);
62 if (l == 0) this.next();
63 }
64
65 async addArray(urls: YouTubeVideo[]) {
66 const l = this.#queue.length;
67 this.#queue.push(...urls);
68 if (l == 0 && this.player.state.status == AudioPlayerStatus.Idle) this.next();
69 return urls;
70 }
71
72 pause() {
73 this.player.pause();
74 }
75
76 resume() {
77 this.player.unpause();
78 this.connection.subscribe(this.player);
79 }
80
81 async outro(url: string) {
82 this.player.pause();
83 const resource = await resourceFromYTUrl(url);
84
85 const p = createAudioPlayer();
86 p.on(AudioPlayerStatus.Idle, () => {
87 if (this.player.state.status == AudioPlayerStatus.Paused) {
88 this.resume();
89 return
90 }
91 this.connection.disconnect();
92 });
93
94 p.play(resource);
95 this.connection.subscribe(p);
96 }
97}
98
99(module).exports = MyQueue;