diff options
| author | Max Isom <[email protected]> | 2022-03-13 18:30:36 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-03-13 17:30:36 -0500 |
| commit | 6c00727a4a22e28c45711b301c7bf4dbaff90117 (patch) | |
| tree | c23696f95ce0ef9a4f31586af96021329dedf292 /src | |
| parent | 03d5cfffd1a9cd8a9977de0d24cce1be0cc73210 (diff) | |
| download | muse-6c00727a4a22e28c45711b301c7bf4dbaff90117.tar.xz muse-6c00727a4a22e28c45711b301c7bf4dbaff90117.zip | |
Parse duration strings for /fseek and /seek (#565)
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands/fseek.ts | 15 | ||||
| -rw-r--r-- | src/commands/seek.ts | 5 | ||||
| -rw-r--r-- | src/services/player.ts | 16 | ||||
| -rw-r--r-- | src/utils/duration-string-to-seconds.ts | 21 |
4 files changed, 46 insertions, 11 deletions
diff --git a/src/commands/fseek.ts b/src/commands/fseek.ts index 985a7c4..3e34438 100644 --- a/src/commands/fseek.ts +++ b/src/commands/fseek.ts @@ -5,15 +5,16 @@ import {inject, injectable} from 'inversify'; import PlayerManager from '../managers/player.js'; import Command from '.'; import {prettyTime} from '../utils/time.js'; +import durationStringToSeconds from '../utils/duration-string-to-seconds.js'; @injectable() export default class implements Command { public readonly slashCommand = new SlashCommandBuilder() .setName('fseek') .setDescription('seek forward in the current song') - .addNumberOption(option => option - .setName('seconds') - .setDescription('the number of seconds to skip forward') + .addStringOption(option => option + .setName('time') + .setDescription('an interval expression or number of seconds (1m, 30s, 100)') .setRequired(true)); public requiresVC = true; @@ -37,12 +38,14 @@ export default class implements Command { throw new Error('can\'t seek in a livestream'); } - const seekTime = interaction.options.getNumber('seconds'); + const seekValue = interaction.options.getString('value'); - if (!seekTime) { - throw new Error('missing number of seconds to seek'); + if (!seekValue) { + throw new Error('missing seek value'); } + const seekTime = durationStringToSeconds(seekValue); + if (seekTime + player.getPosition() > currentSong.length) { throw new Error('can\'t seek past the end of the song'); } diff --git a/src/commands/seek.ts b/src/commands/seek.ts index 07f6590..00e9c2e 100644 --- a/src/commands/seek.ts +++ b/src/commands/seek.ts @@ -5,6 +5,7 @@ import PlayerManager from '../managers/player.js'; import Command from '.'; import {parseTime, prettyTime} from '../utils/time.js'; import {SlashCommandBuilder} from '@discordjs/builders'; +import durationStringToSeconds from '../utils/duration-string-to-seconds.js'; @injectable() export default class implements Command { @@ -13,7 +14,7 @@ export default class implements Command { .setDescription('seek to a position from beginning of song') .addStringOption(option => option.setName('time') - .setDescription('time to seek') + .setDescription('an interval expression or number of seconds (1m, 30s, 100)') .setRequired(true), ); @@ -45,7 +46,7 @@ export default class implements Command { if (time.includes(':')) { seekTime = parseTime(time); } else { - seekTime = parseInt(time, 10); + seekTime = durationStringToSeconds(time); } if (seekTime > currentSong.length) { diff --git a/src/services/player.ts b/src/services/player.ts index 6e99364..b3ed34d 100644 --- a/src/services/player.ts +++ b/src/services/player.ts @@ -5,7 +5,17 @@ import ytdl from 'ytdl-core'; import {WriteStream} from 'fs-capacitor'; import ffmpeg from 'fluent-ffmpeg'; import shuffle from 'array-shuffle'; -import {AudioPlayer, AudioPlayerStatus, createAudioPlayer, createAudioResource, joinVoiceChannel, StreamType, VoiceConnection, VoiceConnectionStatus} from '@discordjs/voice'; +import { + AudioPlayer, + AudioPlayerState, + AudioPlayerStatus, + createAudioPlayer, + createAudioResource, + joinVoiceChannel, + StreamType, + VoiceConnection, + VoiceConnectionStatus, +} from '@discordjs/voice'; import FileCacheProvider from './file-cache.js'; import debug from '../utils/debug.js'; import {prisma} from '../utils/db.js'; @@ -493,7 +503,7 @@ export default class { } if (this.audioPlayer.listeners('stateChange').length === 0) { - this.audioPlayer.on('stateChange', this.onAudioPlayerStateChange.bind(this)); + this.audioPlayer.on(AudioPlayerStatus.Idle, this.onAudioPlayerIdle.bind(this)); } } @@ -501,7 +511,7 @@ export default class { this.disconnect(); } - private async onAudioPlayerStateChange(_oldState: {status: AudioPlayerStatus}, newState: {status: AudioPlayerStatus}): Promise<void> { + private async onAudioPlayerIdle(_oldState: AudioPlayerState, newState: AudioPlayerState): Promise<void> { // Automatically advance queued song at end if (newState.status === AudioPlayerStatus.Idle && this.status === STATUS.PLAYING) { await this.forward(1); diff --git a/src/utils/duration-string-to-seconds.ts b/src/utils/duration-string-to-seconds.ts new file mode 100644 index 0000000..588ba5b --- /dev/null +++ b/src/utils/duration-string-to-seconds.ts @@ -0,0 +1,21 @@ +import parse from 'parse-duration'; + +/** + * Parse duration strings to seconds. + * @param str any common duration format, like 1m or 1hr 30s. If the input is a number it's assumed to be in seconds. + * @returns seconds + */ +const durationStringToSeconds = (str: string) => { + let seconds; + const isInputSeconds = Boolean(/\d+$/.exec(str)); + + if (isInputSeconds) { + seconds = Number.parseInt(str, 10); + } else { + seconds = parse(str) / 1000; + } + + return seconds; +}; + +export default durationStringToSeconds; |
