diff --git a/commands/Music/queue.js b/commands/Music/queue.js index ac8535f5..ddb5f220 100644 --- a/commands/Music/queue.js +++ b/commands/Music/queue.js @@ -1,4 +1,4 @@ -const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js"); const BaseCommand = require("../../base/BaseCommand"); class Queue extends BaseCommand { @@ -34,38 +34,175 @@ class Queue extends BaseCommand { const queue = client.player.getQueue(interaction.guildId); if (!queue) return interaction.error("music/play:NOT_PLAYING"); - const currentTrack = queue.current; - const tracks = queue.tracks.slice(0, 5).map((track, i) => { - return `${i + 1}. [${track.title}](${track.url})\n> ${interaction.translate("music/queue:ADDED")} ${track.requestedBy}`; - }); + let currentPage = 0; + const embeds = generateQueueEmbed(interaction, queue); - const embed = new EmbedBuilder() - .setAuthor({ - name: interaction.translate("music/queue:TITLE"), - iconURL: interaction.guild.iconURL() - }) - .setColor(client.config.embed.color) - .addFields( - { - name: interaction.translate("music/nowplaying:CURRENTLY_PLAYING"), - value: `[${currentTrack.title}](${currentTrack.url})\n> ${interaction.translate("music/queue:ADDED")} ${currentTrack.requestedBy}\n` - }, - { - name: interaction.translate("music/queue:QUEUE"), - value: tracks.length > 0 ? tracks.join("\n") : interaction.translate("music/queue:NO_QUEUE") - }, - { - name: "\u200b", - value: `${interaction.translate("music/queue:MORE", { - tracks: `${queue.tracks.length - tracks.length} ${client.getNoun(queue.tracks.length - tracks.length, interaction.translate("misc:NOUNS:TRACKS:1"), interaction.translate("misc:NOUNS:TRACKS:2"), interaction.translate("misc:NOUNS:TRACKS:5"))}` - })}` - } + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId("queue_prev_page") + .setLabel(interaction.translate("music/queue:PREV_PAGE")) + .setStyle(ButtonStyle.Primary) + .setEmoji("⬅️"), + new ButtonBuilder() + .setCustomId("queue_next_page") + .setLabel(interaction.translate("music/queue:NEXT_PAGE")) + .setStyle(ButtonStyle.Primary) + .setEmoji("➡️"), + new ButtonBuilder() + .setCustomId("queue_jump_page") + .setLabel(interaction.translate("music/queue:JUMP_PAGE")) + .setStyle(ButtonStyle.Secondary) + .setEmoji("↗️"), + new ButtonBuilder() + .setCustomId("queue_stop") + .setLabel(interaction.translate("common:CANCEL")) + .setStyle(ButtonStyle.Danger) + .setEmoji("⏹️"), ); - interaction.reply({ - embeds: [embed] + await interaction.reply({ + content: interaction.translate("music/queue:PAGE", { + current: currentPage + 1, + length: embeds.length + }), + embeds: [embeds[currentPage]], + components: [row] + }); + + const filter = i => i.user.id === interaction.user.id; + const collector = interaction.channel.createMessageComponentCollector({ filter, idle: (60 * 1000) }); + + collector.on("collect", async i => { + if (i.isButton()) { + if (i.customId === "queue_prev_page") { + i.deferUpdate(); + + if (currentPage !== 0) { + --currentPage; + interaction.editReply({ + content: interaction.translate("music/queue:PAGE", { + current: currentPage + 1, + length: embeds.length + }), + embeds: [embeds[currentPage]], + components: [row] + }); + } + } else if (i.customId === "queue_next_page") { + i.deferUpdate(); + + if (currentPage < embeds.length - 1) { + currentPage++; + interaction.editReply({ + content: interaction.translate("music/queue:PAGE", { + current: currentPage + 1, + length: embeds.length + }), + embeds: [embeds[currentPage]], + components: [row] + }); + } + } else if (i.customId === "queue_jump_page") { + i.deferUpdate(); + + const msg = await interaction.followUp({ + content: interaction.translate("music/queue:PAGE_TO_JUMP", { + length: embeds.length + }), + fetchReply: true + }); + + const filter = res => { + return res.author.id === interaction.user.id && !isNaN(res.content); + }; + + interaction.channel.awaitMessages({ filter, max: 1, time: (30 * 1000) }).then(collected => { + if (embeds[Number(collected.first().content) - 1]) { + currentPage = Number(collected.first().content) - 1; + interaction.editReply({ + content: interaction.translate("music/queue:PAGE", { + current: currentPage + 1, + length: embeds.length + }), + embeds: [embeds[currentPage]], + components: [row] + }); + + if (collected.first().deletable) collected.first().delete(); + if (msg.deletable) msg.delete(); + } else { + if (collected.first().deletable) collected.first().delete(); + if (msg.deletable) msg.delete(); + return; + } + }); + } else if (i.customId === "queue_stop") { + i.deferUpdate(); + collector.stop(true); + } + } + }); + + collector.on("end", async (_, reason) => { + if (reason) { + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId("queue_prev_page") + .setLabel(interaction.translate("music/queue:PREV_PAGE")) + .setStyle(ButtonStyle.Primary) + .setEmoji("⬅️") + .setDisabled(true), + new ButtonBuilder() + .setCustomId("queue_next_page") + .setLabel(interaction.translate("music/queue:NEXT_PAGE")) + .setStyle(ButtonStyle.Primary) + .setEmoji("➡️") + .setDisabled(true), + new ButtonBuilder() + .setCustomId("queue_jump_page") + .setLabel(interaction.translate("music/queue:JUMP_PAGE")) + .setStyle(ButtonStyle.Secondary) + .setEmoji("↗️") + .setDisabled(true), + new ButtonBuilder() + .setCustomId("queue_stop") + .setLabel(interaction.translate("common:CANCEL")) + .setStyle(ButtonStyle.Danger) + .setEmoji("⏹️") + .setDisabled(true), + ); + return interaction.editReply({ + components: [row] + }); + } }); } } +function generateQueueEmbed(interaction, queue) { + const embeds = []; + const currentTrack = queue.current; + let k = 10; + + for (let i = 0; i < queue.tracks.length; i += 10) { + const current = queue.tracks.slice(i, k); + let j = i; + k += 10; + + const info = current.map(track => `${++j}. [${track.title}](${track.url})\n> ${interaction.translate("music/queue:ADDED")} ${track.requestedBy}`).join("\n"); + + const embed = new EmbedBuilder() + .setTitle(interaction.translate("music/nowplaying:CURRENTLY_PLAYING")) + .setThumbnail(currentTrack.thumbnail) + .setColor(interaction.client.config.embed.color) + .setDescription(`[${currentTrack.title}](${currentTrack.url})\n> ${interaction.translate("music/queue:ADDED")} ${currentTrack.requestedBy}\n\n**${interaction.translate("music/queue:NEXT")}**\n${info}`) + .setTimestamp(); + embeds.push(embed); + } + + return embeds; +} + module.exports = Queue; \ No newline at end of file diff --git a/dashboard/public/docs/updates.md b/dashboard/public/docs/updates.md index ab4dd809..0dc73bfb 100644 --- a/dashboard/public/docs/updates.md +++ b/dashboard/public/docs/updates.md @@ -1,3 +1,6 @@ +### JaBa v4.1.1 +* Добавлено + * Страницы в *queue*. ### JaBa v4.1 * Изменения diff --git a/languages/ru-RU/music/queue.json b/languages/ru-RU/music/queue.json index 0a31fe75..28088dec 100644 --- a/languages/ru-RU/music/queue.json +++ b/languages/ru-RU/music/queue.json @@ -3,7 +3,12 @@ "USAGE": "", "EXAMPLES": "queue", "QUEUE": "Очередь", + "PAGE": "Страница **{{current}}**/**{{length}}**", "NO_QUEUE": "Пусто", "ADDED": "Добавил", - "MORE": "и ещё {{tracks}}" + "NEXT_PAGE": "След. страница", + "PREV_PAGE": "Пред. страница", + "JUMP_PAGE": "Перейти к странице", + "PAGE_TO_JUMP": "Укажите страницу к которой хотите перейти (максимум **{{length}}**):", + "NEXT": "Далее" } \ No newline at end of file diff --git a/languages/ru-RU/music/skipto.json b/languages/ru-RU/music/skipto.json index 7144a5ae..e2d5d80c 100644 --- a/languages/ru-RU/music/skipto.json +++ b/languages/ru-RU/music/skipto.json @@ -3,7 +3,7 @@ "USAGE": "[номер]", "EXAMPLES": "skipto 3", "POSITION": "Номер трека в очереди", - "SUCCESS": "Выполнен переход на позицию {{position}}", + "SUCCESS": "Выполнен переход на трек под номером **{{position}}**", "ERROR": "На позиции {{position}} ничего не найдено", "NO_PREV_SONG": "Вы не можете перейти назад, для этого используйте команду `back`!" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0445d09f..26f66f25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jaba", - "version": "4.1", + "version": "4.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "jaba", - "version": "4.1", + "version": "4.1.1", "license": "ISC", "dependencies": { "@discord-player/extractor": "^3.0.2", diff --git a/package.json b/package.json index 67ca4312..931c0eba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jaba", - "version": "4.1", + "version": "4.1.1", "description": "My Discord Bot", "main": "index.js", "private": true,