all repos — simple-discord-music-bot @ f1b6c2135d3740fb92fc2a8f095e159d93480a4a

A Discord bot making use of discord.js and play-yt.

src/functions/myqueue.ts (view raw)

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