feat: music improvements (#225)
All checks were successful
Publish latest version / build (push) Successful in 1m7s
All checks were successful
Publish latest version / build (push) Successful in 1m7s
Close #223 Kinda refactor logic around buttons, now adding buttons to music Reviewed-on: #225 Co-authored-by: Mylloon <kennel.anri@tutanota.com> Co-committed-by: Mylloon <kennel.anri@tutanota.com>
This commit is contained in:
parent
ae2f1a7d0c
commit
c3d4ab4ebf
21 changed files with 361 additions and 115 deletions
|
@ -209,6 +209,8 @@ même message.
|
|||
Contrairement aux autres éléments, les boutons doivent se faire collecter via
|
||||
la fonction [`collect`](./src/buttons/loader.ts#L46) juste après leur déclaration.
|
||||
|
||||
Aussi, le payload des boutons est défini dans la classe [ButtonAction](./src/utils/monads/ButtonAction.ts).
|
||||
|
||||
## Autocomplétion
|
||||
|
||||
La réponse qu'attend Discord doit se faire obligatoirement sous 3 secondes.
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
MessageFlags,
|
||||
} from "discord.js";
|
||||
import { getLocale } from "../utils/locales";
|
||||
import { ButtonActionTypes } from "../utils/monads/ButtonAction";
|
||||
|
||||
export default async (client: Client) => {
|
||||
// Dossier des buttons
|
||||
|
@ -74,7 +75,16 @@ export const collect = (
|
|||
}
|
||||
const msg = await button?.interaction(i, client);
|
||||
if (msg !== undefined) {
|
||||
await i.update(msg);
|
||||
const result = msg.unwrap();
|
||||
switch (result.type) {
|
||||
case ButtonActionTypes.RemoveComponents:
|
||||
message.edit({ components: [] });
|
||||
break;
|
||||
|
||||
case ButtonActionTypes.EditMessage:
|
||||
await i.update(result.message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -10,6 +10,8 @@ import { getLocale } from "../../utils/locales";
|
|||
import { getFilename } from "../../utils/misc";
|
||||
import { embedListReminders } from "../../utils/commands/reminder";
|
||||
import { collect } from "../loader";
|
||||
import { reminderListNext, reminderListPrec } from "../../utils/constants";
|
||||
import { ButtonAction, ButtonActionTypes } from "../../utils/monads/ButtonAction";
|
||||
|
||||
export default {
|
||||
data: {
|
||||
|
@ -41,8 +43,8 @@ export default {
|
|||
interaction.locale,
|
||||
);
|
||||
|
||||
const idPrec = "reminderList-prec_" + uuidv4();
|
||||
const idNext = "reminderList-next_" + uuidv4();
|
||||
const idPrec = reminderListPrec + uuidv4();
|
||||
const idNext = reminderListNext + uuidv4();
|
||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
|
@ -61,9 +63,12 @@ export default {
|
|||
collect(client, interaction, idPrec, interaction.message);
|
||||
collect(client, interaction, idNext, interaction.message);
|
||||
|
||||
return {
|
||||
embeds: [list],
|
||||
components: [row],
|
||||
};
|
||||
return new ButtonAction({
|
||||
type: ButtonActionTypes.EditMessage,
|
||||
message: {
|
||||
embeds: [list],
|
||||
components: [row],
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -10,6 +10,8 @@ import { getLocale } from "../../utils/locales";
|
|||
import { getFilename } from "../../utils/misc";
|
||||
import { embedListReminders } from "../../utils/commands/reminder";
|
||||
import { collect } from "../loader";
|
||||
import { reminderListNext, reminderListPrec } from "../../utils/constants";
|
||||
import { ButtonAction, ButtonActionTypes } from "../../utils/monads/ButtonAction";
|
||||
|
||||
export default {
|
||||
data: {
|
||||
|
@ -41,8 +43,8 @@ export default {
|
|||
interaction.locale,
|
||||
);
|
||||
|
||||
const idPrec = "reminderList-prec_" + uuidv4();
|
||||
const idNext = "reminderList-next_" + uuidv4();
|
||||
const idPrec = reminderListPrec + uuidv4();
|
||||
const idNext = reminderListNext + uuidv4();
|
||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
|
@ -61,9 +63,12 @@ export default {
|
|||
collect(client, interaction, idPrec, interaction.message);
|
||||
collect(client, interaction, idNext, interaction.message);
|
||||
|
||||
return {
|
||||
embeds: [list],
|
||||
components: [row],
|
||||
};
|
||||
return new ButtonAction({
|
||||
type: ButtonActionTypes.EditMessage,
|
||||
message: {
|
||||
embeds: [list],
|
||||
components: [row],
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
52
src/buttons/music/playLyrics.ts
Normal file
52
src/buttons/music/playLyrics.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { Client, MessageComponentInteraction } from "discord.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { getFilename } from "../../utils/misc";
|
||||
import { ButtonAction, ButtonActionTypes } from "../../utils/monads/ButtonAction";
|
||||
import {
|
||||
embedLyrics,
|
||||
embedNowPlaying,
|
||||
findLyricsFromPlayer,
|
||||
musicButtons,
|
||||
} from "../../utils/commands/music";
|
||||
import { useMainPlayer, useQueue } from "discord-player";
|
||||
import { getLocale } from "../../utils/locales";
|
||||
import {
|
||||
discord_limit_embed_per_message,
|
||||
musicLyrics,
|
||||
musicPlayResume,
|
||||
} from "../../utils/constants";
|
||||
import { collect } from "../loader";
|
||||
|
||||
export default {
|
||||
data: {
|
||||
name: getFilename(__filename),
|
||||
},
|
||||
interaction: async (interaction: MessageComponentInteraction, client: Client) => {
|
||||
const queue = useQueue(interaction.guildId!);
|
||||
|
||||
if (queue && queue.currentTrack && interaction.channel?.isSendable()) {
|
||||
const loc = getLocale(client, interaction.locale);
|
||||
|
||||
const idPauseResume = musicPlayResume + uuidv4();
|
||||
const idLyrics = musicLyrics + uuidv4();
|
||||
|
||||
collect(client, interaction, idPauseResume, interaction.message);
|
||||
collect(client, interaction, idLyrics, interaction.message);
|
||||
|
||||
const data = await findLyricsFromPlayer(useMainPlayer(), queue.currentTrack);
|
||||
const embeds = embedLyrics(data[0]);
|
||||
interaction.channel?.send({ embeds: embeds.slice(0, discord_limit_embed_per_message) });
|
||||
|
||||
return new ButtonAction({
|
||||
type: ButtonActionTypes.EditMessage,
|
||||
message: {
|
||||
embeds: [embedNowPlaying(queue.currentTrack, loc)],
|
||||
components: [musicButtons(loc, queue, idPauseResume, idLyrics)],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
interaction.deferUpdate({ withResponse: false });
|
||||
return new ButtonAction({ type: ButtonActionTypes.RemoveComponents });
|
||||
},
|
||||
};
|
41
src/buttons/music/playPauseResume.ts
Normal file
41
src/buttons/music/playPauseResume.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { useQueue } from "discord-player";
|
||||
import { Client, MessageComponentInteraction } from "discord.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { getLocale } from "../../utils/locales";
|
||||
import { getFilename } from "../../utils/misc";
|
||||
import { embedNowPlaying, musicButtons, toggleMusicPause } from "../../utils/commands/music";
|
||||
import { collect } from "../loader";
|
||||
import { ButtonAction, ButtonActionTypes } from "../../utils/monads/ButtonAction";
|
||||
import { musicLyrics, musicPlayResume } from "../../utils/constants";
|
||||
|
||||
export default {
|
||||
data: {
|
||||
name: getFilename(__filename),
|
||||
},
|
||||
interaction: async (interaction: MessageComponentInteraction, client: Client) => {
|
||||
// Get queue
|
||||
const queue = useQueue(interaction.guildId!);
|
||||
if (queue && queue.currentTrack) {
|
||||
const loc = getLocale(client, interaction.locale);
|
||||
|
||||
const idPauseResume = musicPlayResume + uuidv4();
|
||||
const idLyrics = musicLyrics + uuidv4();
|
||||
|
||||
toggleMusicPause(queue);
|
||||
|
||||
collect(client, interaction, idPauseResume, interaction.message);
|
||||
collect(client, interaction, idLyrics, interaction.message);
|
||||
|
||||
return new ButtonAction({
|
||||
type: ButtonActionTypes.EditMessage,
|
||||
message: {
|
||||
embeds: [embedNowPlaying(queue.currentTrack, loc)],
|
||||
components: [musicButtons(loc, queue, idPauseResume, idLyrics)],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
interaction.deferUpdate({ withResponse: false });
|
||||
return new ButtonAction({ type: ButtonActionTypes.RemoveComponents });
|
||||
},
|
||||
};
|
|
@ -12,6 +12,8 @@ import { getLocale } from "../../utils/locales";
|
|||
import { getFilename } from "../../utils/misc";
|
||||
import { collect } from "../loader";
|
||||
import { embedListQueue } from "../../utils/commands/music";
|
||||
import { musicQueueNext, musicQueuePrec } from "../../utils/constants";
|
||||
import { ButtonAction, ButtonActionTypes } from "../../utils/monads/ButtonAction";
|
||||
|
||||
export default {
|
||||
data: {
|
||||
|
@ -40,8 +42,8 @@ export default {
|
|||
embedListQueue(client, embed, queue, page, interaction.locale);
|
||||
|
||||
// Create buttons
|
||||
const idPrec = "queueList-prec_" + uuidv4();
|
||||
const idNext = "queueList-next_" + uuidv4();
|
||||
const idPrec = musicQueuePrec + uuidv4();
|
||||
const idNext = musicQueueNext + uuidv4();
|
||||
rows.push(
|
||||
new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
|
@ -65,9 +67,13 @@ export default {
|
|||
// In case queue doesn't exists
|
||||
embed.setDescription(loc.get("c_queue2"));
|
||||
}
|
||||
return {
|
||||
embeds: [embed],
|
||||
components: rows,
|
||||
};
|
||||
|
||||
return new ButtonAction({
|
||||
type: ButtonActionTypes.EditMessage,
|
||||
message: {
|
||||
embeds: [embed],
|
||||
components: rows,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -12,6 +12,8 @@ import { getLocale } from "../../utils/locales";
|
|||
import { getFilename } from "../../utils/misc";
|
||||
import { collect } from "../loader";
|
||||
import { embedListQueue } from "../../utils/commands/music";
|
||||
import { musicQueueNext, musicQueuePrec } from "../../utils/constants";
|
||||
import { ButtonAction, ButtonActionTypes } from "../../utils/monads/ButtonAction";
|
||||
|
||||
export default {
|
||||
data: {
|
||||
|
@ -40,8 +42,8 @@ export default {
|
|||
embedListQueue(client, embed, queue, page, interaction.locale);
|
||||
|
||||
// Create buttons
|
||||
const idPrec = "queueList-prec_" + uuidv4();
|
||||
const idNext = "queueList-next_" + uuidv4();
|
||||
const idPrec = musicQueuePrec + uuidv4();
|
||||
const idNext = musicQueueNext + uuidv4();
|
||||
rows.push(
|
||||
new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
|
@ -65,9 +67,13 @@ export default {
|
|||
// In case queue doesn't exists
|
||||
embed.setDescription(loc.get("c_queue2"));
|
||||
}
|
||||
return {
|
||||
embeds: [embed],
|
||||
components: rows,
|
||||
};
|
||||
|
||||
return new ButtonAction({
|
||||
type: ButtonActionTypes.EditMessage,
|
||||
message: {
|
||||
embeds: [embed],
|
||||
components: rows,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
getReminderInfo,
|
||||
newReminder,
|
||||
} from "../../utils/commands/reminder";
|
||||
import { reminderListNext, reminderListPrec } from "../../utils/constants";
|
||||
|
||||
export default {
|
||||
scope: () => [],
|
||||
|
@ -218,8 +219,8 @@ export default {
|
|||
interaction.locale,
|
||||
);
|
||||
|
||||
const idPrec = "reminderList-prec_" + uuidv4();
|
||||
const idNext = "reminderList-next_" + uuidv4();
|
||||
const idPrec = reminderListPrec + uuidv4();
|
||||
const idNext = reminderListNext + uuidv4();
|
||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import { useMainPlayer, useQueue } from "discord-player";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
Client,
|
||||
EmbedBuilder,
|
||||
Message,
|
||||
MessageFlags,
|
||||
} from "discord.js";
|
||||
import { ChatInputCommandInteraction, Client, Message, MessageFlags } from "discord.js";
|
||||
import { getLocale, getLocalizations } from "../../utils/locales";
|
||||
import { getFilename } from "../../utils/misc";
|
||||
import { discord_limit_message } from "../../utils/constants";
|
||||
import { RegexC } from "../../utils/regex";
|
||||
import { discord_limit_embed_per_message, discord_limit_message } from "../../utils/constants";
|
||||
import { embedLyrics, findLyricsFromPlayer } from "../../utils/commands/music";
|
||||
|
||||
export default {
|
||||
scope: () => [],
|
||||
|
@ -115,11 +109,8 @@ export default {
|
|||
} else if (queue) {
|
||||
const track = queue.history.currentTrack;
|
||||
if (track) {
|
||||
request = track.cleanTitle + " " + track.author.replaceAll(RegexC(/ - Topic$/), "");
|
||||
try {
|
||||
data = await player.lyrics.search({
|
||||
q: request,
|
||||
});
|
||||
data = await findLyricsFromPlayer(player, track);
|
||||
} catch {
|
||||
return await interaction.followUp(`❌ | ${loc.get("c_lyrics2")} \`${track.title}\``);
|
||||
}
|
||||
|
@ -205,52 +196,16 @@ export default {
|
|||
}
|
||||
|
||||
if (data) {
|
||||
if (data.length === 0 || (data.length > 0 && data[0].plainLyrics !== null)) {
|
||||
if (data.length === 0 || (data.length > 0 && data[0].plainLyrics == null)) {
|
||||
return await interaction.followUp(`❌ | ${loc.get("c_lyrics2")} \`${request}\``);
|
||||
}
|
||||
|
||||
const title = data[0];
|
||||
const limit_desc = 4096;
|
||||
const nb_embed = Math.ceil(title.plainLyrics.length / limit_desc);
|
||||
const embeds = embedLyrics(data[0]);
|
||||
|
||||
// https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/issues/186
|
||||
// TODO: If lyrics < 6000, only send one message with multiples embed
|
||||
for (let i = 0, j = 0; i < nb_embed; i++, j += limit_desc) {
|
||||
// + Better cut in lyrics
|
||||
const lyrics = title.plainLyrics.slice(j, j + limit_desc);
|
||||
|
||||
let embed;
|
||||
switch (i) {
|
||||
case 0: {
|
||||
// First embed
|
||||
embed = new EmbedBuilder();
|
||||
embed
|
||||
.setTitle(title.trackName)
|
||||
.setAuthor({ name: title.artistName })
|
||||
.setDescription(lyrics);
|
||||
break;
|
||||
}
|
||||
|
||||
case nb_embed - 1: {
|
||||
// Footer of last embed in case of multiple embed
|
||||
embed = new EmbedBuilder().setDescription(lyrics).setFooter({
|
||||
text: `${title.artistName} · ${title.trackName}`,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// Embed with only lyrics in case of multiple embed
|
||||
embed = new EmbedBuilder().setDescription(lyrics);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Send embed
|
||||
await interaction.followUp({ embeds: [embed] });
|
||||
}
|
||||
|
||||
return;
|
||||
// TODO: Send multiple messages if there is too many embeds, instead of not sending the end
|
||||
return await interaction.followUp({
|
||||
embeds: embeds.slice(0, discord_limit_embed_per_message),
|
||||
});
|
||||
}
|
||||
|
||||
return await interaction.followUp(`❌ | ${loc.get("c_lyrics1")}`);
|
||||
|
|
|
@ -3,6 +3,7 @@ import { useQueue } from "discord-player";
|
|||
import { ChatInputCommandInteraction, Client, EmbedBuilder } from "discord.js";
|
||||
import { getLocale, getLocalizations } from "../../utils/locales";
|
||||
import { getFilename } from "../../utils/misc";
|
||||
import { QueueStatus, toggleMusicPause } from "../../utils/commands/music";
|
||||
|
||||
export default {
|
||||
scope: () => [],
|
||||
|
@ -27,14 +28,10 @@ export default {
|
|||
|
||||
if (queue) {
|
||||
const embed = new EmbedBuilder();
|
||||
if (queue.node.isPaused()) {
|
||||
queue.node.resume();
|
||||
|
||||
if (toggleMusicPause(queue) == QueueStatus.Play) {
|
||||
embed.setDescription(loc.get("c_pause1"));
|
||||
return await interaction.reply({ embeds: [embed] });
|
||||
} else {
|
||||
queue.node.pause();
|
||||
|
||||
embed.setDescription(loc.get("c_pause2"));
|
||||
return await interaction.reply({ embeds: [embed] });
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ export default {
|
|||
defaultFFmpegFilters: ["silenceremove"],
|
||||
leaveOnEndCooldown: 15000,
|
||||
metadata: {
|
||||
channel: interaction.channel,
|
||||
interaction: interaction,
|
||||
} as Metadata,
|
||||
});
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import { collect } from "../../buttons/loader";
|
|||
import { getLocale, getLocalizations } from "../../utils/locales";
|
||||
import { getFilename } from "../../utils/misc";
|
||||
import { embedListQueue } from "../../utils/commands/music";
|
||||
import { musicQueueNext, musicQueuePrec } from "../../utils/constants";
|
||||
|
||||
export default {
|
||||
scope: () => [],
|
||||
|
@ -109,8 +110,8 @@ export default {
|
|||
embedListQueue(client, embed, queue, page, interaction.locale);
|
||||
|
||||
const rows = [];
|
||||
const idPrec = "queueList-prec_" + uuidv4();
|
||||
const idNext = "queueList-next_" + uuidv4();
|
||||
const idPrec = musicQueuePrec + uuidv4();
|
||||
const idNext = musicQueueNext + uuidv4();
|
||||
rows.push(
|
||||
new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
import { EmbedBuilder } from "@discordjs/builders";
|
||||
import { GuildQueue, Track } from "discord-player";
|
||||
import { Client } from "discord.js";
|
||||
import { Metadata } from "../../utils/metadata";
|
||||
import { emojiPng } from "../../utils/misc";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { collect } from "../../buttons/loader";
|
||||
import { embedNowPlaying, musicButtons } from "../../utils/commands/music";
|
||||
import { getLocale } from "../../utils/locales";
|
||||
import { musicLyrics, musicPlayResume } from "../../utils/constants";
|
||||
|
||||
/** https://discord-player.js.org/docs/types/discord-player/GuildQueueEvents */
|
||||
export default (queue: GuildQueue<Metadata>, track: Track, client: Client) => {
|
||||
const loc_default = client.locales.get(client.config.default_lang);
|
||||
export default async (queue: GuildQueue<Metadata>, track: Track, client: Client) => {
|
||||
const loc = getLocale(client, queue.metadata.interaction?.locale);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setDescription(`${loc_default?.get("e_trackstart1")} ${track.requestedBy}`)
|
||||
.setTitle(track.title + " • " + track.author)
|
||||
.setURL(track.url)
|
||||
.setThumbnail(track.thumbnail)
|
||||
.setFooter({
|
||||
text: `${loc_default?.get("e_trackstart2")} ${
|
||||
track.duration
|
||||
} via ${track.source.capitalize()}`,
|
||||
iconURL: emojiPng("🎶"),
|
||||
const embed = embedNowPlaying(track, loc);
|
||||
|
||||
const idPauseResume = musicPlayResume + uuidv4();
|
||||
const idLyrics = musicLyrics + uuidv4();
|
||||
|
||||
if (queue.metadata.interaction?.channel?.isSendable()) {
|
||||
const message = await queue.metadata?.interaction?.channel.send({
|
||||
embeds: [embed],
|
||||
components: [musicButtons(loc, queue, idPauseResume, idLyrics)],
|
||||
});
|
||||
|
||||
if (queue.metadata.channel?.isSendable()) {
|
||||
queue.metadata?.channel?.send({ embeds: [embed] });
|
||||
// Buttons interactions
|
||||
collect(client, queue.metadata.interaction!, idPauseResume, message);
|
||||
collect(client, queue.metadata.interaction!, idLyrics, message);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -108,9 +108,11 @@
|
|||
|
||||
"c_pause_name": "pause",
|
||||
"c_pause_desc": "Pauses or restarts music",
|
||||
"c_pause1": "Resuming music...",
|
||||
"c_pause1": "Resuming music.",
|
||||
"c_pause2": "Pause the music.",
|
||||
"c_pause3": "The bot is not playing anything right now.",
|
||||
"c_pause4": "Pause",
|
||||
"c_pause5": "Resume",
|
||||
|
||||
"c_queue_name": "queue",
|
||||
"c_queue_desc": "Command relative to the music queue",
|
||||
|
|
|
@ -108,9 +108,11 @@
|
|||
|
||||
"c_pause_name": "pause",
|
||||
"c_pause_desc": "Met en pause ou relance la musique",
|
||||
"c_pause1": "Relance la musique...",
|
||||
"c_pause1": "Relance la musique.",
|
||||
"c_pause2": "Met en pause la musique.",
|
||||
"c_pause3": "Le bot ne joue rien en ce moment.",
|
||||
"c_pause4": "Pause",
|
||||
"c_pause5": "Reprend",
|
||||
|
||||
"c_queue_name": "queue",
|
||||
"c_queue_desc": "Commande relative à la file d'attente des musiques",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import { Collection } from "discord.js";
|
||||
import { Database } from "sqlite3";
|
||||
import { ButtonAction } from "../utils/monads/ButtonAction";
|
||||
|
||||
export {};
|
||||
|
||||
|
@ -58,7 +59,7 @@ declare module "discord.js" {
|
|||
interaction: (
|
||||
interaction: MessageComponentInteraction,
|
||||
client: Client,
|
||||
) => Promise<InteractionUpdateOptions>;
|
||||
) => Promise<ButtonAction>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { EmbedBuilder } from "@discordjs/builders";
|
||||
import { GuildQueue, QueueRepeatMode } from "discord-player";
|
||||
import { Client } from "discord.js";
|
||||
import { GuildQueue, LrcSearchResult, Player, QueueRepeatMode, Track } from "discord-player";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, Client } from "discord.js";
|
||||
import { getLocale } from "../locales";
|
||||
import { blank } from "../misc";
|
||||
import { discord_limit_embed_field } from "../constants";
|
||||
import { blank, emojiPng } from "../misc";
|
||||
import { discord_limit_embed_description_length, discord_limit_embed_field } from "../constants";
|
||||
import { RegexC } from "../regex";
|
||||
|
||||
export const embedListQueue = (
|
||||
client: Client,
|
||||
|
@ -58,3 +59,107 @@ const printRepeatMode = (mode: QueueRepeatMode, loc: Map<string, string>) => {
|
|||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export enum QueueStatus {
|
||||
/** Currently playing */
|
||||
Play = 0,
|
||||
/** Currently in pause */
|
||||
Pause = 1,
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the status of the queue
|
||||
* @param queue Queue
|
||||
* @returns Current status, after the changes
|
||||
*/
|
||||
export const toggleMusicPause = (queue: GuildQueue) => {
|
||||
if (queue.node.isPaused()) {
|
||||
queue.node.resume();
|
||||
return QueueStatus.Play;
|
||||
}
|
||||
|
||||
queue.node.pause();
|
||||
return QueueStatus.Pause;
|
||||
};
|
||||
|
||||
export const embedNowPlaying = (track: Track, loc: Map<string, string>) => {
|
||||
return new EmbedBuilder()
|
||||
.setDescription(`${loc?.get("e_trackstart1")} ${track.requestedBy}`)
|
||||
.setTitle(track.title + " • " + track.author)
|
||||
.setURL(track.url)
|
||||
.setThumbnail(track.thumbnail)
|
||||
.setFooter({
|
||||
text: `${loc?.get("e_trackstart2")} ${track.duration} via ${track.source.capitalize()}`,
|
||||
iconURL: emojiPng("🎶"),
|
||||
});
|
||||
};
|
||||
|
||||
export const embedLyrics = (title: LrcSearchResult) => {
|
||||
const nb_embed = Math.ceil(title.plainLyrics.length / discord_limit_embed_description_length);
|
||||
|
||||
/* https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/issues/186
|
||||
* TODO: If lyrics < 6000, only send one message with multiples embed
|
||||
* + Better cut in lyrics */
|
||||
|
||||
const embeds = [];
|
||||
for (let i = 0, j = 0; i < nb_embed; i++, j += discord_limit_embed_description_length) {
|
||||
const lyrics = title.plainLyrics.slice(j, j + discord_limit_embed_description_length);
|
||||
|
||||
const embed = new EmbedBuilder();
|
||||
switch (i) {
|
||||
case 0: {
|
||||
// First embed
|
||||
embed
|
||||
.setTitle(title.trackName)
|
||||
.setAuthor({ name: title.artistName })
|
||||
.setDescription(lyrics);
|
||||
break;
|
||||
}
|
||||
|
||||
case nb_embed - 1: {
|
||||
// Footer of last embed in case of multiple embed
|
||||
embed.setDescription(lyrics).setFooter({
|
||||
text: `${title.artistName} · ${title.trackName}`,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// Embed with only lyrics in case of multiple embed
|
||||
embed.setDescription(lyrics);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
embeds.push(embed);
|
||||
}
|
||||
return embeds;
|
||||
};
|
||||
|
||||
export const findLyricsFromPlayer = async (player: Player, track: Track) => {
|
||||
const request = track.cleanTitle + " " + track.author.replace(RegexC(/ - Topic$/), "");
|
||||
return await player.lyrics.search({
|
||||
q: request,
|
||||
});
|
||||
};
|
||||
|
||||
export const musicButtons = (
|
||||
loc: Map<string, string>,
|
||||
queue: GuildQueue,
|
||||
idPauseResume: string,
|
||||
idLyrics: string,
|
||||
) => {
|
||||
return new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId(idPauseResume)
|
||||
.setLabel(queue.node.isPaused() ? loc.get("c_pause5")! : loc.get("c_pause4")!)
|
||||
.setStyle(queue.node.isPaused() ? ButtonStyle.Primary : ButtonStyle.Secondary),
|
||||
)
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId(idLyrics)
|
||||
.setLabel(loc.get("c_lyrics_name")!.capitalize())
|
||||
.setStyle(ButtonStyle.Secondary),
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/** Max message length */
|
||||
export const discord_limit_message = 2000;
|
||||
|
||||
/** Max embed description length */
|
||||
export const discord_limit_embed_description_length = 4096;
|
||||
|
||||
/** Max embed field an embed can have */
|
||||
export const discord_limit_embed_field = 25;
|
||||
|
||||
|
@ -9,3 +12,24 @@ export const discord_limit_autocompletion_list_length = 25;
|
|||
|
||||
/** Max length of an element in autocompletion of slash commands */
|
||||
export const discord_limit_autocompletion_value_length = 100;
|
||||
|
||||
/** Max embeds per message */
|
||||
export const discord_limit_embed_per_message = 10;
|
||||
|
||||
/** Last page in the music queue */
|
||||
export const musicQueuePrec = "queueList-prec_";
|
||||
|
||||
/** Next page in the music queue */
|
||||
export const musicQueueNext = "queueList-next_";
|
||||
|
||||
/** Last page in the reminder list */
|
||||
export const reminderListPrec = "reminderList-prec_";
|
||||
|
||||
/** Next page in the reminder queue */
|
||||
export const reminderListNext = "reminderList-next_";
|
||||
|
||||
/** Pause or resume the current track */
|
||||
export const musicPlayResume = "playPauseResume_";
|
||||
|
||||
/** Print lyrics of the current track */
|
||||
export const musicLyrics = "playLyrics_";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { TextBasedChannel } from "discord.js";
|
||||
import { ChatInputCommandInteraction } from "discord.js";
|
||||
|
||||
export type Metadata = {
|
||||
channel: TextBasedChannel | null;
|
||||
interaction: ChatInputCommandInteraction | null;
|
||||
};
|
||||
|
|
28
src/utils/monads/ButtonAction.ts
Normal file
28
src/utils/monads/ButtonAction.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { InteractionUpdateOptions } from "discord.js";
|
||||
|
||||
export enum ButtonActionTypes {
|
||||
RemoveComponents,
|
||||
EditMessage,
|
||||
ChangeNothing,
|
||||
}
|
||||
|
||||
type UnitType = {
|
||||
type: ButtonActionTypes.RemoveComponents | ButtonActionTypes.ChangeNothing;
|
||||
};
|
||||
|
||||
type MessageType = {
|
||||
type: ButtonActionTypes.EditMessage;
|
||||
message: InteractionUpdateOptions;
|
||||
};
|
||||
|
||||
type ButtonActionPossibilities = UnitType | MessageType;
|
||||
|
||||
export class ButtonAction {
|
||||
constructor(private readonly action: ButtonActionPossibilities) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
unwrap(): ButtonActionPossibilities {
|
||||
return this.action;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue