From 11246812a6e5da88750bf4b6ded159dd4020a3d3 Mon Sep 17 00:00:00 2001 From: Max Isom Date: Wed, 18 Mar 2020 12:40:31 -0500 Subject: [PATCH] Don't allow seeking past end of song --- src/commands/fseek.ts | 11 +++++++++-- src/commands/play.ts | 23 +++++++++++++---------- src/commands/queue.ts | 6 ++++-- src/commands/seek.ts | 11 +++++++++-- src/services/player.ts | 4 ++++ src/services/queue.ts | 2 +- 6 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/commands/fseek.ts b/src/commands/fseek.ts index bd3c858..877e2a4 100644 --- a/src/commands/fseek.ts +++ b/src/commands/fseek.ts @@ -25,18 +25,25 @@ export default class implements Command { public async execute(msg: Message, args: string []): Promise { const queue = this.queueManager.get(msg.guild!.id); - if (!queue.getCurrent()) { + const currentSong = queue.getCurrent(); + + if (!currentSong) { await msg.channel.send(errorMsg('nothing is playing')); return; } - if (queue.getCurrent()?.isLive) { + if (currentSong.isLive) { await msg.channel.send(errorMsg('can\'t seek in a livestream')); return; } const seekTime = parseInt(args[0], 10); + if (seekTime + this.playerManager.get(msg.guild!.id).getPosition() > currentSong.length) { + await msg.channel.send(errorMsg('can\'t seek past the end of the song')); + return; + } + const loading = new LoadingMessage(msg.channel as TextChannel); await loading.start(); diff --git a/src/commands/play.ts b/src/commands/play.ts index 7b9a934..e6d6464 100644 --- a/src/commands/play.ts +++ b/src/commands/play.ts @@ -48,6 +48,8 @@ export default class implements Command { const queue = this.queueManager.get(msg.guild!.id); + const queueOldSize = queue.size(); + if (args.length === 0) { if (this.playerManager.get(msg.guild!.id).status === STATUS.PLAYING) { await res.stop(errorMsg('already playing, give me a song name')); @@ -69,8 +71,6 @@ export default class implements Command { const newSongs: QueuedSong[] = []; - let nSongsNotFound = 0; - // Test if it's a complete URL try { const url = new URL(args[0]); @@ -94,9 +94,7 @@ export default class implements Command { } } } else if (url.protocol === 'spotify:' || url.host === 'open.spotify.com') { - const [convertedSongs, nMissing] = await this.getSongs.spotifySource(args[0]); - - nSongsNotFound = nMissing; + const [convertedSongs] = await this.getSongs.spotifySource(args[0]); newSongs.push(...convertedSongs); } @@ -119,17 +117,22 @@ export default class implements Command { return; } - newSongs.forEach(song => this.queueManager.get(msg.guild!.id).add(song)); + newSongs.forEach(song => queue.add(song)); - // TODO: better response - await res.stop(`song(s) queued (${nSongsNotFound} not found)`); + const firstSong = newSongs[0]; + + if (newSongs.length === 1) { + await res.stop(`u betcha, **${firstSong.title}** added to the queue`); + } else { + await res.stop(`u betcha, **${firstSong.title}** and ${newSongs.length - 1} other songs were added to the queue`); + } if (this.playerManager.get(msg.guild!.id).voiceConnection === null) { await this.playerManager.get(msg.guild!.id).connect(targetVoiceChannel); } - if (this.queueManager.get(msg.guild!.id).size() === 0) { - // Only auto-play on first song added + if (queueOldSize === 0) { + // Only auto-play if queue was empty before await this.playerManager.get(msg.guild!.id).play(); } } diff --git a/src/commands/queue.ts b/src/commands/queue.ts index e77cbcb..a194729 100644 --- a/src/commands/queue.ts +++ b/src/commands/queue.ts @@ -18,8 +18,10 @@ export default class implements Command { } public async execute(msg: Message, _: string []): Promise { - const queue = this.queueManager.get(msg.guild!.id).get(); + const queue = this.queueManager.get(msg.guild!.id); - await msg.channel.send('`' + JSON.stringify(queue.slice(0, 10)) + '`'); + await msg.channel.send('`' + JSON.stringify(queue.getCurrent()) + '`'); + + await msg.channel.send('`' + JSON.stringify(queue.get().slice(0, 10)) + '`'); } } diff --git a/src/commands/seek.ts b/src/commands/seek.ts index b6e7d9e..e2f1154 100644 --- a/src/commands/seek.ts +++ b/src/commands/seek.ts @@ -26,12 +26,14 @@ export default class implements Command { public async execute(msg: Message, args: string []): Promise { const queue = this.queueManager.get(msg.guild!.id); - if (!queue.getCurrent()) { + const currentSong = queue.getCurrent(); + + if (!currentSong) { await msg.channel.send(errorMsg('nothing is playing')); return; } - if (queue.getCurrent()?.isLive) { + if (currentSong.isLive) { await msg.channel.send(errorMsg('can\'t seek in a livestream')); return; } @@ -46,6 +48,11 @@ export default class implements Command { seekTime = parseInt(time, 10); } + if (seekTime > currentSong.length) { + await msg.channel.send(errorMsg('can\'t seek past the end of the song')); + return; + } + const loading = new LoadingMessage(msg.channel as TextChannel); await loading.start(); diff --git a/src/services/player.ts b/src/services/player.ts index 9629547..2ac128b 100644 --- a/src/services/player.ts +++ b/src/services/player.ts @@ -64,6 +64,10 @@ export default class { throw new Error('No song currently playing'); } + if (positionSeconds > currentSong.length) { + throw new Error('Seek position is outside the range of the song.'); + } + if (await this.isCached(currentSong.url)) { this.dispatcher = this.voiceConnection.play(this.getCachedPath(currentSong.url), {seek: positionSeconds}); } else { diff --git a/src/services/queue.ts b/src/services/queue.ts index eff8a7b..5db3b74 100644 --- a/src/services/queue.ts +++ b/src/services/queue.ts @@ -77,7 +77,7 @@ export default class { // Don't clear curently playing song if (this.queue.length > 0) { - newQueue.push(this.queue[0]); + newQueue.push(this.queue[this.position]); } this.queue = newQueue;