Merge branch 'master' into feature/select-dotenv-path

This commit is contained in:
João Costa 2024-10-28 16:16:27 +00:00 committed by GitHub
commit ce8edf4145
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 529 additions and 350 deletions

View file

@ -56,6 +56,15 @@ export default class implements Command {
.setMinValue(0)
.setMaxValue(100)
.setRequired(true)))
.addSubcommand(subcommand => subcommand
.setName('set-default-queue-page-size')
.setDescription('set the default page size of the /queue command')
.addIntegerOption(option => option
.setName('page-size')
.setDescription('page size of the /queue command')
.setMinValue(1)
.setMaxValue(30)
.setRequired(true)))
.addSubcommand(subcommand => subcommand
.setName('get')
.setDescription('show all settings'));
@ -171,6 +180,23 @@ export default class implements Command {
break;
}
case 'set-default-queue-page-size': {
const value = interaction.options.getInteger('page-size')!;
await prisma.setting.update({
where: {
guildId: interaction.guild!.id,
},
data: {
defaultQueuePageSize: value,
},
});
await interaction.reply('👍 default queue page size updated');
break;
}
case 'get': {
const embed = new EmbedBuilder().setTitle('Config');
@ -185,6 +211,7 @@ export default class implements Command {
'Auto announce next song in queue': config.autoAnnounceNextSong ? 'yes' : 'no',
'Add to queue reponses show for requester only': config.autoAnnounceNextSong ? 'yes' : 'no',
'Default Volume': config.defaultVolume,
'Default queue page size': config.defaultQueuePageSize,
};
let description = '';

View file

@ -28,7 +28,10 @@ export default class implements Command {
.setDescription('shuffle the input if you\'re adding multiple tracks'))
.addBooleanOption(option => option
.setName('split')
.setDescription('if a track has chapters, split it')))
.setDescription('if a track has chapters, split it'))
.addBooleanOption(option => option
.setName('skip')
.setDescription('skip the currently playing track')))
.addSubcommand(subcommand => subcommand
.setName('list')
.setDescription('list all favorites'))
@ -124,6 +127,7 @@ export default class implements Command {
shuffleAdditions: interaction.options.getBoolean('shuffle') ?? false,
addToFrontOfQueue: interaction.options.getBoolean('immediate') ?? false,
shouldSplitChapters: interaction.options.getBoolean('split') ?? false,
skipCurrentTrack: interaction.options.getBoolean('skip') ?? false,
});
}

View file

@ -29,7 +29,10 @@ export default class implements Command {
.setDescription('shuffle the input if you\'re adding multiple tracks'))
.addBooleanOption(option => option
.setName('split')
.setDescription('if a track has chapters, split it'));
.setDescription('if a track has chapters, split it'))
.addBooleanOption(option => option
.setName('skip')
.setDescription('skip the currently playing track'));
public requiresVC = true;
@ -52,6 +55,7 @@ export default class implements Command {
addToFrontOfQueue: interaction.options.getBoolean('immediate') ?? false,
shuffleAdditions: interaction.options.getBoolean('shuffle') ?? false,
shouldSplitChapters: interaction.options.getBoolean('split') ?? false,
skipCurrentTrack: interaction.options.getBoolean('skip') ?? false,
});
}

View file

@ -5,6 +5,7 @@ import {TYPES} from '../types.js';
import PlayerManager from '../managers/player.js';
import Command from './index.js';
import {buildQueueEmbed} from '../utils/build-embed.js';
import {getGuildSettings} from '../utils/get-guild-settings.js';
@injectable()
export default class implements Command {
@ -14,6 +15,12 @@ export default class implements Command {
.addIntegerOption(option => option
.setName('page')
.setDescription('page of queue to show [default: 1]')
.setRequired(false))
.addIntegerOption(option => option
.setName('page-size')
.setDescription('how many items to display per page [default: 10, max: 30]')
.setMinValue(1)
.setMaxValue(30)
.setRequired(false));
private readonly playerManager: PlayerManager;
@ -23,9 +30,17 @@ export default class implements Command {
}
public async execute(interaction: ChatInputCommandInteraction) {
const player = this.playerManager.get(interaction.guild!.id);
const guildId = interaction.guild!.id;
const player = this.playerManager.get(guildId);
const embed = buildQueueEmbed(player, interaction.options.getInteger('page') ?? 1);
const pageSizeFromOptions = interaction.options.getInteger('page-size');
const pageSize = pageSizeFromOptions ?? (await getGuildSettings(guildId)).defaultQueuePageSize;
const embed = buildQueueEmbed(
player,
interaction.options.getInteger('page') ?? 1,
pageSize,
);
await interaction.reply({embeds: [embed]});
}

View file

@ -40,5 +40,5 @@ export default async (guild: Guild): Promise<void> => {
}
const owner = await guild.fetchOwner();
await owner.send('👋 Hi! Someone (probably you) just invited me to a server you own. By default, I\'m usable by all guild member in all guild channels. To change this, check out the wiki page on permissions: https://github.com/codetheweb/muse/wiki/Configuring-Bot-Permissions.');
await owner.send('👋 Hi! Someone (probably you) just invited me to a server you own. By default, I\'m usable by all guild member in all guild channels. To change this, check out the wiki page on permissions: https://github.com/museofficial/muse/wiki/Configuring-Bot-Permissions.');
};

View file

@ -38,12 +38,14 @@ export default class AddQueryToQueue {
addToFrontOfQueue,
shuffleAdditions,
shouldSplitChapters,
skipCurrentTrack,
interaction,
}: {
query: string;
addToFrontOfQueue: boolean;
shuffleAdditions: boolean;
shouldSplitChapters: boolean;
skipCurrentTrack: boolean;
interaction: ChatInputCommandInteraction;
}): Promise<void> {
const guildId = interaction.guild!.id;
@ -169,6 +171,14 @@ export default class AddQueryToQueue {
await player.play();
}
if (skipCurrentTrack) {
try {
await player.forward(1);
} catch (_: unknown) {
throw new Error('no song to skip to');
}
}
// Build response message
if (statusMsg !== '') {
if (extraMsg === '') {
@ -183,9 +193,9 @@ export default class AddQueryToQueue {
}
if (newSongs.length === 1) {
await interaction.editReply(`u betcha, **${firstSong.title}** added to the${addToFrontOfQueue ? ' front of the' : ''} queue${extraMsg}`);
await interaction.editReply(`u betcha, **${firstSong.title}** added to the${addToFrontOfQueue ? ' front of the' : ''} queue${skipCurrentTrack ? 'and current track skipped' : ''}${extraMsg}`);
} else {
await interaction.editReply(`u betcha, **${firstSong.title}** and ${newSongs.length - 1} other songs were added to the queue${extraMsg}`);
await interaction.editReply(`u betcha, **${firstSong.title}** and ${newSongs.length - 1} other songs were added to the queue${skipCurrentTrack ? 'and current track skipped' : ''}${extraMsg}`);
}
}

View file

@ -1,7 +1,7 @@
import {VoiceChannel, Snowflake} from 'discord.js';
import {Readable} from 'stream';
import hasha from 'hasha';
import ytdl, {videoFormat} from 'ytdl-core';
import ytdl, {videoFormat} from '@distube/ytdl-core';
import {WriteStream} from 'fs-capacitor';
import ffmpeg from 'fluent-ffmpeg';
import shuffle from 'array-shuffle';
@ -280,8 +280,8 @@ export default class {
if (this.getCurrent() && this.status !== STATUS.PAUSED) {
await this.play();
} else {
this.audioPlayer?.stop(true);
this.status = STATUS.IDLE;
this.audioPlayer?.stop(true);
const settings = await getGuildSettings(this.guildId);

View file

@ -1,7 +1,7 @@
import {inject, injectable} from 'inversify';
import {toSeconds, parse} from 'iso8601-duration';
import got, {Got} from 'got';
import ytsr, {Video} from 'ytsr';
import ytsr, {Video} from '@distube/ytsr';
import PQueue from 'p-queue';
import {SongMetadata, QueuedPlaylist, MediaSource} from './player.js';
import {TYPES} from '../types.js';

View file

@ -5,8 +5,6 @@ import getProgressBar from './get-progress-bar.js';
import {prettyTime} from './time.js';
import {truncate} from './string.js';
const PAGE_SIZE = 10;
const getMaxSongTitleLength = (title: string) => {
// eslint-disable-next-line no-control-regex
const nonASCII = /[^\x00-\x7F]+/;
@ -77,7 +75,7 @@ export const buildPlayingMessageEmbed = (player: Player): EmbedBuilder => {
return message;
};
export const buildQueueEmbed = (player: Player, page: number): EmbedBuilder => {
export const buildQueueEmbed = (player: Player, page: number, pageSize: number): EmbedBuilder => {
const currentlyPlaying = player.getCurrent();
if (!currentlyPlaying) {
@ -85,14 +83,14 @@ export const buildQueueEmbed = (player: Player, page: number): EmbedBuilder => {
}
const queueSize = player.queueSize();
const maxQueuePage = Math.ceil((queueSize + 1) / PAGE_SIZE);
const maxQueuePage = Math.ceil((queueSize + 1) / pageSize);
if (page > maxQueuePage) {
throw new Error('the queue isn\'t that big');
}
const queuePageBegin = (page - 1) * PAGE_SIZE;
const queuePageEnd = queuePageBegin + PAGE_SIZE;
const queuePageBegin = (page - 1) * pageSize;
const queuePageEnd = queuePageBegin + pageSize;
const queuedSongs = player
.getQueue()
.slice(queuePageBegin, queuePageEnd)