src/functions/myqueue.ts (view raw)
1import { createAudioResource, createAudioPlayer, NoSubscriberBehavior, AudioPlayerStatus, VoiceConnection, AudioPlayer } from '@discordjs/voice';
2import play from 'play-dl';
3
4async function resourceFromUrl(url) {
5 const stream = await play.stream(url);
6 return createAudioResource(stream.stream, { inputType: stream.type })
7}
8
9export default class MyQueue {
10 #nowPlaying = null;
11 #queue = Array();
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 = "";
28 this.connection = null;
29 this.#queue = Array();
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 //@ts-expect-error
35 this.player.subscribers.forEach((e) => e.connection.disconnect());
36 });
37 }
38
39 clear() {
40 this.#queue = Array();
41 }
42
43 stop() {
44 this.clear();
45 this.#nowPlaying = null;
46 if (this.player) return this.player.stop();
47 return false;
48 }
49
50 async next() {
51 if (this.#queue.length == 0)
52 return this.stop();
53 this.#nowPlaying = this.#queue.shift();
54 const resource = await resourceFromUrl(this.#nowPlaying);
55 this.player.play(resource);
56 this.connection.subscribe(this.player);
57 }
58
59 add(url, position=this.#queue.length) {
60 const l = this.#queue.length;
61 const normalizedPosition = position % (l + 1);
62 this.#queue.splice(normalizedPosition, 0, url);
63 if (l == 0) this.next();
64 }
65
66 async addArray(urls) {
67 const l = this.#queue.length;
68 this.#queue.push(...urls);
69 if (l == 0 && this.player.state.status == AudioPlayerStatus.Idle) this.next();
70 return l != this.#queue.length;
71 }
72
73 pause() {
74 this.player.pause();
75 }
76
77 resume() {
78 this.player.unpause();
79 this.connection.subscribe(this.player);
80 }
81
82 async outro(url) {
83 this.player.pause();
84 const resource = await resourceFromUrl(url);
85
86 const p = createAudioPlayer();
87 p.on(AudioPlayerStatus.Idle, () => {
88 if (this.player.state.status == AudioPlayerStatus.Paused) {
89 this.resume();
90 return
91 }
92 //@ts-expect-error
93 p.subscribers.forEach((e) => e.connection.disconnect());
94 });
95
96 p.play(resource);
97 this.connection.subscribe(p);
98 }
99}
100
101(module).exports = MyQueue;