Create /resume command; make query required for the /play command (#546)

This commit is contained in:
Hellyson Rodrigo Parteka 2022-03-09 23:45:59 -03:00 committed by GitHub
parent 4eefb7b30d
commit d438d46c09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 35 deletions

View file

@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- `/resume` command to resume playback
### Changed
- `query` is now a required parameter from `/play`
### Removed
- `/play` cannot resume the playback anymore since `query` is now required
## [1.2.0] - 2022-02-24
### Added

View file

@ -1,4 +1,4 @@
import {AutocompleteInteraction, CommandInteraction, GuildMember} from 'discord.js';
import {AutocompleteInteraction, CommandInteraction} from 'discord.js';
import {URL} from 'url';
import {SlashCommandBuilder} from '@discordjs/builders';
import {inject, injectable} from 'inversify';
@ -10,20 +10,17 @@ import getYouTubeAndSpotifySuggestionsFor from '../utils/get-youtube-and-spotify
import KeyValueCacheProvider from '../services/key-value-cache.js';
import {ONE_HOUR_IN_SECONDS} from '../utils/constants.js';
import AddQueryToQueue from '../services/add-query-to-queue.js';
import PlayerManager from '../managers/player.js';
import {STATUS} from '../services/player.js';
import {buildPlayingMessageEmbed} from '../utils/build-embed.js';
import {getMemberVoiceChannel, getMostPopularVoiceChannel} from '../utils/channels.js';
@injectable()
export default class implements Command {
public readonly slashCommand = new SlashCommandBuilder()
.setName('play')
.setDescription('play a song or resume playback')
.setDescription('play a song')
.addStringOption(option => option
.setName('query')
.setDescription('YouTube URL, Spotify URL, or search query')
.setAutocomplete(true))
.setAutocomplete(true)
.setRequired(true))
.addBooleanOption(option => option
.setName('immediate')
.setDescription('add track to the front of the queue'))
@ -36,42 +33,16 @@ export default class implements Command {
private readonly spotify: Spotify;
private readonly cache: KeyValueCacheProvider;
private readonly addQueryToQueue: AddQueryToQueue;
private readonly playerManager: PlayerManager;
constructor(@inject(TYPES.ThirdParty) thirdParty: ThirdParty, @inject(TYPES.KeyValueCache) cache: KeyValueCacheProvider, @inject(TYPES.Services.AddQueryToQueue) addQueryToQueue: AddQueryToQueue, @inject(TYPES.Managers.Player) playerManager: PlayerManager) {
constructor(@inject(TYPES.ThirdParty) thirdParty: ThirdParty, @inject(TYPES.KeyValueCache) cache: KeyValueCacheProvider, @inject(TYPES.Services.AddQueryToQueue) addQueryToQueue: AddQueryToQueue) {
this.spotify = thirdParty.spotify;
this.cache = cache;
this.addQueryToQueue = addQueryToQueue;
this.playerManager = playerManager;
}
// eslint-disable-next-line complexity
public async execute(interaction: CommandInteraction): Promise<void> {
const query = interaction.options.getString('query');
const player = this.playerManager.get(interaction.guild!.id);
const [targetVoiceChannel] = getMemberVoiceChannel(interaction.member as GuildMember) ?? getMostPopularVoiceChannel(interaction.guild!);
if (!query) {
if (player.status === STATUS.PLAYING) {
throw new Error('already playing, give me a song name');
}
// Must be resuming play
if (!player.getCurrent()) {
throw new Error('nothing to play');
}
await player.connect(targetVoiceChannel);
await player.play();
await interaction.reply({
content: 'the stop-and-go light is now green',
embeds: [buildPlayingMessageEmbed(player)],
});
return;
}
const query = interaction.options.getString('query')!;
await this.addQueryToQueue.addToQueue({
interaction,

46
src/commands/resume.ts Normal file
View file

@ -0,0 +1,46 @@
import {SlashCommandBuilder} from '@discordjs/builders';
import {inject, injectable} from 'inversify';
import Command from '.';
import {TYPES} from '../types.js';
import PlayerManager from '../managers/player.js';
import {STATUS} from '../services/player.js';
import {buildPlayingMessageEmbed} from '../utils/build-embed.js';
import {getMemberVoiceChannel, getMostPopularVoiceChannel} from '../utils/channels.js';
import {CommandInteraction, GuildMember} from 'discord.js';
@injectable()
export default class implements Command {
public readonly slashCommand = new SlashCommandBuilder()
.setName('resume')
.setDescription('resume playback');
public requiresVC = true;
private readonly playerManager: PlayerManager;
constructor(@inject(TYPES.Managers.Player) playerManager: PlayerManager) {
this.playerManager = playerManager;
}
// eslint-disable-next-line complexity
public async execute(interaction: CommandInteraction): Promise<void> {
const player = this.playerManager.get(interaction.guild!.id);
const [targetVoiceChannel] = getMemberVoiceChannel(interaction.member as GuildMember) ?? getMostPopularVoiceChannel(interaction.guild!);
if (player.status === STATUS.PLAYING) {
throw new Error('already playing, give me a song name');
}
// Must be resuming play
if (!player.getCurrent()) {
throw new Error('nothing to play');
}
await player.connect(targetVoiceChannel);
await player.play();
await interaction.reply({
content: 'the stop-and-go light is now green',
embeds: [buildPlayingMessageEmbed(player)],
});
}
}

View file

@ -23,6 +23,7 @@ import Pause from './commands/pause.js';
import Play from './commands/play.js';
import QueueCommand from './commands/queue.js';
import Remove from './commands/remove.js';
import Resume from './commands/resume.js';
import Seek from './commands/seek.js';
import Shuffle from './commands/shuffle.js';
import Skip from './commands/skip.js';
@ -64,6 +65,7 @@ container.bind<AddQueryToQueue>(TYPES.Services.AddQueryToQueue).to(AddQueryToQue
Play,
QueueCommand,
Remove,
Resume,
Seek,
Shuffle,
Skip,