Throw errors in command handlers

This commit is contained in:
Max Isom 2022-01-26 22:30:58 -05:00
parent aacb107f43
commit 2e5e509b32
No known key found for this signature in database
GPG key ID: 25C9B1A7F6798880
11 changed files with 18 additions and 100 deletions

View file

@ -56,7 +56,6 @@
"release-it": "^14.11.8", "release-it": "^14.11.8",
"ts-node": "^10.4.0", "ts-node": "^10.4.0",
"type-fest": "^2.8.0", "type-fest": "^2.8.0",
"typed-emitter": "^1.4.0",
"typescript": "^4.5.4" "typescript": "^4.5.4"
}, },
"eslintConfig": { "eslintConfig": {

View file

@ -3,7 +3,6 @@ import {SlashCommandBuilder} from '@discordjs/builders';
import {TYPES} from '../types.js'; import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify'; import {inject, injectable} from 'inversify';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import errorMsg from '../utils/error-msg.js';
import Command from '.'; import Command from '.';
@injectable() @injectable()
@ -24,12 +23,7 @@ export default class implements Command {
const player = this.playerManager.get(interaction.guild!.id); const player = this.playerManager.get(interaction.guild!.id);
if (!player.voiceConnection) { if (!player.voiceConnection) {
await interaction.reply({ throw new Error('not connected');
content: errorMsg('not connected'),
ephemeral: true,
});
return;
} }
player.disconnect(); player.disconnect();

View file

@ -3,7 +3,6 @@ import {SlashCommandBuilder} from '@discordjs/builders';
import {TYPES} from '../types.js'; import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify'; import {inject, injectable} from 'inversify';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import errorMsg from '../utils/error-msg.js';
import Command from '.'; import Command from '.';
import {prettyTime} from '../utils/time.js'; import {prettyTime} from '../utils/time.js';
@ -31,41 +30,21 @@ export default class implements Command {
const currentSong = player.getCurrent(); const currentSong = player.getCurrent();
if (!currentSong) { if (!currentSong) {
await interaction.reply({ throw new Error('nothing is playing');
content: errorMsg('nothing is playing'),
ephemeral: true,
});
return;
} }
if (currentSong.isLive) { if (currentSong.isLive) {
await interaction.reply({ throw new Error('can\'t seek in a livestream');
content: errorMsg('can\'t seek in a livestream'),
ephemeral: true,
});
return;
} }
const seekTime = interaction.options.getNumber('seconds'); const seekTime = interaction.options.getNumber('seconds');
if (!seekTime) { if (!seekTime) {
await interaction.reply({ throw new Error('missing number of seconds to seek');
content: errorMsg('missing number of seconds to seek'),
ephemeral: true,
});
return;
} }
if (seekTime + player.getPosition() > currentSong.length) { if (seekTime + player.getPosition() > currentSong.length) {
await interaction.reply({ throw new Error('can\'t seek past the end of the song');
content: errorMsg('can\'t seek past the end of the song'),
ephemeral: true,
});
return;
} }
await Promise.all([ await Promise.all([

View file

@ -4,7 +4,6 @@ import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify'; import {inject, injectable} from 'inversify';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import {STATUS} from '../services/player.js'; import {STATUS} from '../services/player.js';
import errorMsg from '../utils/error-msg.js';
import Command from '.'; import Command from '.';
@injectable() @injectable()
@ -25,11 +24,7 @@ export default class implements Command {
const player = this.playerManager.get(interaction.guild!.id); const player = this.playerManager.get(interaction.guild!.id);
if (player.status !== STATUS.PLAYING) { if (player.status !== STATUS.PLAYING) {
await interaction.reply({ throw new Error('not currently playing');
content: errorMsg('not currently playing'),
ephemeral: true,
});
return;
} }
player.pause(); player.pause();

View file

@ -3,7 +3,6 @@ import {inject, injectable} from 'inversify';
import {TYPES} from '../types.js'; import {TYPES} from '../types.js';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import Command from '.'; import Command from '.';
import errorMsg from '../utils/error-msg.js';
import {SlashCommandBuilder} from '@discordjs/builders'; import {SlashCommandBuilder} from '@discordjs/builders';
@injectable() @injectable()
@ -34,17 +33,11 @@ export default class implements Command {
const range = interaction.options.getInteger('range') ?? 1; const range = interaction.options.getInteger('range') ?? 1;
if (position < 1) { if (position < 1) {
await interaction.reply({ throw new Error('position must be at least 1');
content: errorMsg('position must be greater than 0'),
ephemeral: true,
});
} }
if (range < 1) { if (range < 1) {
await interaction.reply({ throw new Error('range must be at least 1');
content: errorMsg('range must be greater than 0'),
ephemeral: true,
});
} }
player.removeFromQueue(position, range); player.removeFromQueue(position, range);

View file

@ -2,7 +2,6 @@ import {CommandInteraction} from 'discord.js';
import {TYPES} from '../types.js'; import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify'; import {inject, injectable} from 'inversify';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import errorMsg from '../utils/error-msg.js';
import Command from '.'; import Command from '.';
import {parseTime, prettyTime} from '../utils/time.js'; import {parseTime, prettyTime} from '../utils/time.js';
import {SlashCommandBuilder} from '@discordjs/builders'; import {SlashCommandBuilder} from '@discordjs/builders';
@ -32,19 +31,11 @@ export default class implements Command {
const currentSong = player.getCurrent(); const currentSong = player.getCurrent();
if (!currentSong) { if (!currentSong) {
await interaction.reply({ throw new Error('nothing is playing');
content: errorMsg('nothing is playing'),
ephemeral: true,
});
return;
} }
if (currentSong.isLive) { if (currentSong.isLive) {
await interaction.reply({ throw new Error('can\'t seek in a livestream');
content: errorMsg('can\'t seek in a livestream'),
ephemeral: true,
});
return;
} }
const time = interaction.options.getString('time')!; const time = interaction.options.getString('time')!;
@ -58,11 +49,7 @@ export default class implements Command {
} }
if (seekTime > currentSong.length) { if (seekTime > currentSong.length) {
await interaction.reply({ throw new Error('can\'t seek past the end of the song');
content: errorMsg('can\'t seek past the end of the song'),
ephemeral: true,
});
return;
} }
await Promise.all([ await Promise.all([

View file

@ -2,7 +2,6 @@ import {CommandInteraction} from 'discord.js';
import {TYPES} from '../types.js'; import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify'; import {inject, injectable} from 'inversify';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import errorMsg from '../utils/error-msg.js';
import Command from '.'; import Command from '.';
import {SlashCommandBuilder} from '@discordjs/builders'; import {SlashCommandBuilder} from '@discordjs/builders';
@ -24,11 +23,7 @@ export default class implements Command {
const player = this.playerManager.get(interaction.guild!.id); const player = this.playerManager.get(interaction.guild!.id);
if (player.isQueueEmpty()) { if (player.isQueueEmpty()) {
await interaction.reply({ throw new Error('not enough songs to shuffle');
content: errorMsg('not enough songs to shuffle'),
ephemeral: true,
});
return;
} }
player.shuffle(); player.shuffle();

View file

@ -3,7 +3,6 @@ import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify'; import {inject, injectable} from 'inversify';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import Command from '.'; import Command from '.';
import errorMsg from '../utils/error-msg.js';
import {SlashCommandBuilder} from '@discordjs/builders'; import {SlashCommandBuilder} from '@discordjs/builders';
import {buildPlayingMessageEmbed} from '../utils/build-embed.js'; import {buildPlayingMessageEmbed} from '../utils/build-embed.js';
@ -29,7 +28,7 @@ export default class implements Command {
const numToSkip = interaction.options.getInteger('skip') ?? 1; const numToSkip = interaction.options.getInteger('skip') ?? 1;
if (numToSkip < 1) { if (numToSkip < 1) {
await interaction.reply({content: errorMsg('invalid number of songs to skip'), ephemeral: true}); throw new Error('invalid number of songs to skip');
} }
const player = this.playerManager.get(interaction.guild!.id); const player = this.playerManager.get(interaction.guild!.id);
@ -41,7 +40,7 @@ export default class implements Command {
embeds: player.getCurrent() ? [buildPlayingMessageEmbed(player)] : [], embeds: player.getCurrent() ? [buildPlayingMessageEmbed(player)] : [],
}); });
} catch (_: unknown) { } catch (_: unknown) {
await interaction.reply({content: errorMsg('no song to skip to'), ephemeral: true}); throw new Error('no song to skip to');
} }
} }
} }

View file

@ -2,7 +2,6 @@ import {CommandInteraction} from 'discord.js';
import {TYPES} from '../types.js'; import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify'; import {inject, injectable} from 'inversify';
import PlayerManager from '../managers/player.js'; import PlayerManager from '../managers/player.js';
import errorMsg from '../utils/error-msg.js';
import Command from '.'; import Command from '.';
import {SlashCommandBuilder} from '@discordjs/builders'; import {SlashCommandBuilder} from '@discordjs/builders';
import {buildPlayingMessageEmbed} from '../utils/build-embed.js'; import {buildPlayingMessageEmbed} from '../utils/build-embed.js';
@ -31,10 +30,7 @@ export default class implements Command {
embeds: player.getCurrent() ? [buildPlayingMessageEmbed(player)] : [], embeds: player.getCurrent() ? [buildPlayingMessageEmbed(player)] : [],
}); });
} catch (_: unknown) { } catch (_: unknown) {
await interaction.reply({ throw new Error('no song to go back to');
content: errorMsg('no song to go back to'),
ephemeral: true,
});
} }
} }
} }

View file

@ -1,7 +1,5 @@
import {VoiceChannel, Snowflake, Client, TextChannel} from 'discord.js'; import {VoiceChannel, Snowflake, Client, TextChannel} from 'discord.js';
import {Readable} from 'stream'; import {Readable} from 'stream';
import EventEmitter from 'events';
import TypedEmitter from 'typed-emitter';
import hasha from 'hasha'; import hasha from 'hasha';
import ytdl from 'ytdl-core'; import ytdl from 'ytdl-core';
import {WriteStream} from 'fs-capacitor'; import {WriteStream} from 'fs-capacitor';
@ -37,8 +35,10 @@ export interface PlayerEvents {
statusChange: (oldStatus: STATUS, newStatus: STATUS) => void; statusChange: (oldStatus: STATUS, newStatus: STATUS) => void;
} }
export default class extends (EventEmitter as new () => TypedEmitter<PlayerEvents>) { export default class {
public voiceConnection: VoiceConnection | null = null; public voiceConnection: VoiceConnection | null = null;
public status = STATUS.PAUSED;
private queue: QueuedSong[] = []; private queue: QueuedSong[] = [];
private queuePosition = 0; private queuePosition = 0;
private audioPlayer: AudioPlayer | null = null; private audioPlayer: AudioPlayer | null = null;
@ -47,14 +47,11 @@ export default class extends (EventEmitter as new () => TypedEmitter<PlayerEvent
private lastSongURL = ''; private lastSongURL = '';
private positionInSeconds = 0; private positionInSeconds = 0;
private internalStatus = STATUS.PAUSED;
private readonly discordClient: Client; private readonly discordClient: Client;
private readonly fileCache: FileCacheProvider; private readonly fileCache: FileCacheProvider;
constructor(client: Client, fileCache: FileCacheProvider) { constructor(client: Client, fileCache: FileCacheProvider) {
// eslint-disable-next-line constructor-super
super();
this.discordClient = client; this.discordClient = client;
this.fileCache = fileCache; this.fileCache = fileCache;
} }
@ -309,17 +306,6 @@ export default class extends (EventEmitter as new () => TypedEmitter<PlayerEvent
return this.queueSize() === 0; return this.queueSize() === 0;
} }
get status() {
return this.internalStatus;
}
set status(newStatus: STATUS) {
const previousStatus = this.internalStatus;
this.internalStatus = newStatus;
this.emit('statusChange', previousStatus, newStatus);
}
private getHashForCache(url: string): string { private getHashForCache(url: string): string {
return hasha(url); return hasha(url);
} }

View file

@ -3540,11 +3540,6 @@ type-fest@^2.8.0:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.10.0.tgz#0ee9c3cd411efb3bba434065d32235592d3644cf" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.10.0.tgz#0ee9c3cd411efb3bba434065d32235592d3644cf"
integrity sha512-u2yreDMllFI3VCpWt0rKrGs/E2LO0YHBwiiOIj+ilQh9+ALMaa4lNBSdoDvuHN3cbKcYk9L1BXP49x9RT+o/SA== integrity sha512-u2yreDMllFI3VCpWt0rKrGs/E2LO0YHBwiiOIj+ilQh9+ALMaa4lNBSdoDvuHN3cbKcYk9L1BXP49x9RT+o/SA==
typed-emitter@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-1.4.0.tgz#38c6bf1224e764906bb20cb0b458fa914100607c"
integrity sha512-weBmoo3HhpKGgLBOYwe8EB31CzDFuaK7CCL+axXhUYhn4jo6DSkHnbefboCF5i4DQ2aMFe0C/FdTWcPdObgHyg==
typedarray-to-buffer@^3.1.5: typedarray-to-buffer@^3.1.5:
version "3.1.5" version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"