import {injectable} from 'inversify'; export interface QueuedPlaylist { title: string; source: string; } export interface QueuedSong { title: string; artist: string; url: string; length: number; playlist: QueuedPlaylist | null; } @injectable() export default class { private readonly guildQueues = new Map(); private readonly queuePositions = new Map(); forward(guildId: string): void { const currentPosition = this.queuePositions.get(guildId); if (currentPosition && currentPosition + 1 <= this.size(guildId)) { this.queuePositions.set(guildId, currentPosition + 1); } else { throw new Error('No songs in queue to forward to.'); } } back(guildId: string): void { const currentPosition = this.queuePositions.get(guildId); if (currentPosition && currentPosition - 1 >= 0) { this.queuePositions.set(guildId, currentPosition - 1); } else { throw new Error('No songs in queue to go back to.'); } } get(guildId: string): QueuedSong[] { const currentPosition = this.queuePositions.get(guildId); if (currentPosition === undefined) { return []; } const guildQueue = this.guildQueues.get(guildId); if (!guildQueue) { throw new Error('Bad state. Queue for guild exists but position does not.'); } return guildQueue.slice(currentPosition); } add(guildId: string, song: QueuedSong): void { if (!this.guildQueues.get(guildId)) { this.guildQueues.set(guildId, []); this.queuePositions.set(guildId, 0); } if (song.playlist) { // Add to end of queue this.guildQueues.set(guildId, [...this.guildQueues.get(guildId)!, song]); } else if (this.guildQueues.get(guildId)!.length === 0) { // Queue is currently empty this.guildQueues.set(guildId, [song]); } else { // Not from playlist, add immediately let insertAt = 0; // Loop until playlist song this.guildQueues.get(guildId)!.some(song => { if (song.playlist) { return true; } insertAt++; return false; }); this.guildQueues.set(guildId, [...this.guildQueues.get(guildId)!.slice(0, insertAt), song, ...this.guildQueues.get(guildId)!.slice(insertAt)]); } } size(guildId: string): number { return this.get(guildId).length; } }