Réécriture complète 4.0
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6m16s

This commit is contained in:
2025-06-09 16:29:12 +02:00
parent f2c6388da6
commit ddd617317c
133 changed files with 8092 additions and 4332 deletions

View File

@@ -0,0 +1,60 @@
import { SlashCommandBuilder, PermissionFlagsBits, MessageFlags, ChannelType } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { generateDiscoEmbed } from "@/utils/player"
import type { Disco } from "@/types/schemas"
import dbGuild from "@/schemas/guild"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("disco")
.setDescription("Manage the Disco module")
.setDescriptionLocalizations({ fr: "Gérer le module Disco" })
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
.addSubcommand(subcommand => subcommand
.setName("status")
.setDescription("Display Disco mode status")
.setNameLocalizations({ fr: "statut" })
.setDescriptionLocalizations({ fr: "Afficher le statut du mode Disco" })
)
.addSubcommand(subcommand => subcommand
.setName("channel")
.setDescription("Configure the channel for Disco effects")
.setNameLocalizations({ fr: "canal" })
.setDescriptionLocalizations({ fr: "Configurer le canal pour les effets Disco" })
.addChannelOption(option => option
.setName("channel")
.setDescription("The channel where to apply Disco effects")
.setNameLocalizations({ fr: "canal" })
.setDescriptionLocalizations({ fr: "Le canal où appliquer les effets Disco" })
.setRequired(true)
)
)
export async function execute(interaction: ChatInputCommandInteraction) {
const guildProfile = await dbGuild.findOne({ guildId: interaction.guild?.id })
if (!guildProfile) return interaction.reply({ content: t(interaction.locale, "common.database_not_found"), flags: MessageFlags.Ephemeral })
const dbData = guildProfile.get("guildPlayer.disco") as Disco
const subcommand = interaction.options.getSubcommand(true)
if (subcommand === "status") {
const { embed, components } = generateDiscoEmbed(dbData, interaction.client, interaction.guild?.id ?? "", interaction.locale)
return interaction.reply({ embeds: [embed], components: components, flags: MessageFlags.Ephemeral })
}
else if (subcommand === "channel") {
const channel = interaction.options.getChannel("channel", true)
if (channel.type !== ChannelType.GuildText && channel.type !== ChannelType.GuildAnnouncement) return interaction.reply({
content: t(interaction.locale, "common.invalid_channel_type"),
flags: MessageFlags.Ephemeral
})
dbData.channelId = channel.id
guildProfile.set("guildPlayer.disco", dbData)
guildProfile.markModified("guildPlayer.disco")
await guildProfile.save().catch(console.error)
return interaction.reply({ content: t(interaction.locale, "player.disco.channel_configured_success", { channel: channel.name ?? "Inconnu" }), flags: MessageFlags.Ephemeral })
}
}

View File

@@ -0,0 +1,31 @@
import * as disco from "./disco"
import * as loop from "./loop"
import * as lyrics from "./lyrics"
import * as panel from "./panel"
import * as pause from "./pause"
import * as play from "./play"
import * as previous from "./previous"
import * as queue from "./queue"
import * as resume from "./resume"
import * as shuffle from "./shuffle"
import * as skip from "./skip"
import * as stop from "./stop"
import * as volume from "./volume"
import type { Command } from "@/types"
export default [
disco,
loop,
lyrics,
panel,
pause,
play,
previous,
queue,
resume,
shuffle,
skip,
stop,
volume
] as Command[]

View File

@@ -1,21 +1,29 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'
import { useQueue } from'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('loop')
.setDescription('Boucler la musique en cours de lecture.')
.addIntegerOption(option => option.setName('loop')
.setDescription('Mode de boucle (0 = Off, 1 = Titre, 2 = File d\'Attente; 3 = Autoplay)')
.setRequired(true)
.setMinValue(0)
.setMaxValue(3)),
async execute(interaction: ChatInputCommandInteraction) {
let loop = interaction.options.getInteger('loop')
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.setRepeatMode(loop as number)
return await interaction.reply(`Boucle ${loop === 0 ? 'désactivée' : loop === 1 ? 'en mode Titre' : loop === 2 ? 'en mode File d\'Attente' : 'en autoplay'}.`)
}
}
import { SlashCommandBuilder } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import type { QueueRepeatMode } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("loop")
.setDescription("Loop the current music")
.setNameLocalizations({ fr: "boucle" })
.setDescriptionLocalizations({ fr: "Boucler la musique en cours de lecture" })
.addIntegerOption(option => option
.setName("mode")
.setDescription("Loop mode (0 = Off | 1 = Track | 2 = Queue | 3 = Autoplay)")
.setDescriptionLocalizations({ fr: "Mode de boucle (0 = Arrêt | 1 = Titre | 2 = File d'Attente | 3 = Autoplay)" })
.setRequired(true)
.setMinValue(0)
.setMaxValue(3)
)
export async function execute(interaction: ChatInputCommandInteraction) {
const mode = interaction.options.getInteger("mode", true)
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue") })
queue.setRepeatMode(mode as QueueRepeatMode)
return interaction.reply(t(interaction.locale, mode === 0 ? "player.loop_off" : mode === 1 ? "player.loop_track" : mode === 2 ? "player.loop_queue" : "player.loop_autoplay"))
}

View File

@@ -1,45 +1,61 @@
import { ChatInputCommandInteraction, SlashCommandBuilder, EmbedBuilder } from 'discord.js'
import { useQueue } from 'discord-player'
import { lyricsExtractor } from '@discord-player/extractor'
export default {
data: new SlashCommandBuilder()
.setName('lyrics')
.setDescription('Rechercher les paroles d\'une musique.')
.addStringOption(option => option.setName('recherche').setDescription('Chercher une musique spécifique')),
async execute(interaction: ChatInputCommandInteraction) {
await interaction.deferReply()
let query = interaction.options.getString('recherche', false)
if (!query) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
let track = queue.currentTrack
if (!track) return interaction.followUp({ content: 'Aucune musique en cours, recherche en une plutôt !' })
if (track.raw.source === 'spotify') query = `${track.author} ${track.title}`
else query = track.title
}
let lyricsFinder = lyricsExtractor()
let lyrics = await lyricsFinder.search(query).catch(() => null)
if (!lyrics) return interaction.followUp({ content: 'Pas de paroles trouvées !' })
let trimmedLyrics = lyrics.lyrics.substring(0, 1997)
let embed = new EmbedBuilder()
.setColor('#ffc370')
.setTitle(lyrics.title)
.setURL(lyrics.url)
.setThumbnail(lyrics.thumbnail)
.setAuthor({
name: lyrics.artist.name,
iconURL: lyrics.artist.image,
url: lyrics.artist.url
})
.setDescription(trimmedLyrics.length === 1997 ? `${trimmedLyrics}...` : trimmedLyrics)
return interaction.followUp({ embeds: [embed] })
}
}
import { SlashCommandBuilder, EmbedBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue, useMainPlayer } from "discord-player"
import type { LrcSearchResult } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("lyrics")
.setDescription("Search for song lyrics")
.setNameLocalizations({ fr: "paroles" })
.setDescriptionLocalizations({ fr: "Rechercher les paroles d'une musique" })
.addStringOption(option => option
.setName("search")
.setDescription("Search for a specific song")
.setNameLocalizations({ fr: "recherche" })
.setDescriptionLocalizations({ fr: "Chercher une musique spécifique" })
)
export async function execute(interaction: ChatInputCommandInteraction) {
await interaction.deferReply()
const player = useMainPlayer()
const embed = new EmbedBuilder().setColor("#ffff64").setFooter({ text: "Powered by Genius" })
let lyrics = [] as LrcSearchResult[]
const query = interaction.options.getString("search", false)
if (!query) {
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue"), flags: MessageFlags.Ephemeral })
const track = queue.currentTrack
if (!track) return interaction.followUp({ content: t(interaction.locale, "player.no_current_track"), flags: MessageFlags.Ephemeral })
lyrics = await player.lyrics.search({ trackName: track.title, artistName: track.author })
if (!lyrics.length) return interaction.followUp({ content: t(interaction.locale, "player.no_lyrics_found"), flags: MessageFlags.Ephemeral })
const trimmedLyrics = lyrics[0].plainLyrics.substring(0, 1997)
embed
.setTitle(track.title)
.setURL(track.url)
.setDescription(trimmedLyrics.length === 1997 ? `${trimmedLyrics}...` : trimmedLyrics)
.setThumbnail(track.thumbnail)
.setAuthor({ name: track.author, url: `https://genius.com/search?q=${track.author.replace(/ /g, "-")}` })
}
else {
lyrics = await player.lyrics.search({ q: query })
if (!lyrics.length) return interaction.followUp({ content: t(interaction.locale, "player.no_lyrics_found"), flags: MessageFlags.Ephemeral })
const trimmedLyrics = lyrics[0].plainLyrics.substring(0, 1997)
embed
.setTitle(lyrics[0].name)
.setURL(`https://genius.com/search?q=${query.replace(/ /g, "%20")}`)
.setDescription(trimmedLyrics.length === 1997 ? `${trimmedLyrics}...` : trimmedLyrics)
.setThumbnail("https://play-lh.googleusercontent.com/e6-dZlTM-gJ2sFxFFs3X15O84HEv6jc9PQGgHtVTn7FP6lUXeEAkDl9v4RfVOwbSuQ")
.setAuthor({ name: lyrics[0].artistName, url: `https://genius.com/search?q=${lyrics[0].artistName.replace(/ /g, "-")}` })
}
return interaction.followUp({ embeds: [embed] })
}

View File

@@ -1,25 +1,26 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { playerGenerate } from '../../utils/player'
import getUptime from '../../utils/getUptime'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('panel')
.setDescription('Générer les infos de la lecture en cours.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
let guild = interaction.guild
if (!guild) return await interaction.reply({ content: 'Cette commande n\'est pas disponible en message privé.', ephemeral: true })
let client = guild.client
let { embed, components } = await playerGenerate(guild)
if (components && embed.data.footer) embed.setFooter({ text: `Uptime: ${getUptime(client.uptime)} \n ${embed.data.footer.text}` })
else embed.setFooter({ text: `Uptime: ${getUptime(client.uptime)}` })
return interaction.reply({ embeds: [embed] })
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { generatePlayerEmbed } from "@/utils/player"
import uptime from "@/utils/uptime"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("panel")
.setDescription("Generate current playback info")
.setNameLocalizations({ fr: "panneau" })
.setDescriptionLocalizations({ fr: "Générer les infos de la lecture en cours" })
export async function execute(interaction: ChatInputCommandInteraction) {
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue"), flags: MessageFlags.Ephemeral })
const guild = interaction.guild
if (!guild) return interaction.reply({ content: t(interaction.locale, "common.private_message_not_available"), flags: MessageFlags.Ephemeral })
const { embed, components } = generatePlayerEmbed(guild, interaction.locale)
if (components && embed.data.footer) embed.setFooter({ text: `${t(interaction.locale, "player.uptime")}: ${uptime(guild.client.uptime)} \n ${embed.data.footer.text}` })
else embed.setFooter({ text: `${t(interaction.locale, "player.uptime")}: ${uptime(guild.client.uptime)}` })
return interaction.reply({ embeds: [embed] })
}

View File

@@ -1,15 +1,17 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('pause')
.setDescription('Met en pause la musique.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.setPaused(!queue.node.isPaused())
return await interaction.reply('Musique mise en pause !')
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("pause")
.setDescription("Pause the music")
.setDescriptionLocalizations({ fr: "Met en pause la musique" })
export const execute = async (interaction: ChatInputCommandInteraction) => {
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue_search_instead"), flags: MessageFlags.Ephemeral })
queue.node.setPaused(!queue.node.isPaused())
return interaction.reply(t(interaction.locale, "player.paused"))
}

View File

@@ -1,96 +1,123 @@
import { SlashCommandBuilder, ChatInputCommandInteraction, AutocompleteInteraction, GuildMember } from 'discord.js'
import { useMainPlayer, useQueue, QueryType } from 'discord-player'
import dbGuild from '../../schemas/guild'
interface TrackSearchResult { name: string, value: string }
export default {
data: new SlashCommandBuilder()
.setName('play')
.setDescription('Jouer une musique.')
.addStringOption(option => option.setName('recherche').setDescription('Titre de la musique à chercher').setRequired(true).setAutocomplete(true)),
async autocompleteRun(interaction: AutocompleteInteraction) {
let query = interaction.options.getString('recherche', true)
if (!query) return interaction.respond([])
let player = useMainPlayer()
const resultsYouTube = await player.search(query, { searchEngine: QueryType.YOUTUBE })
const resultsSpotify = await player.search(query, { searchEngine: QueryType.SPOTIFY_SEARCH })
const tracksYouTube = resultsYouTube.tracks.slice(0, 5).map((t) => ({
name: `YouTube: ${`${t.title} - ${t.author} (${t.duration})`.length > 75 ? `${`${t.title} - ${t.author}`.substring(0, 75)}... (${t.duration})` : `${t.title} - ${t.author} (${t.duration})`}`,
value: t.url
}))
const tracksSpotify = resultsSpotify.tracks.slice(0, 5).map((t) => ({
name: `Spotify: ${`${t.title} - ${t.author} (${t.duration})`.length > 75 ? `${`${t.title} - ${t.author}`.substring(0, 75)}... (${t.duration})` : `${t.title} - ${t.author} (${t.duration})`}`,
value: t.url
}))
const tracks: TrackSearchResult[] = []
tracksYouTube.forEach((t) => tracks.push({ name: t.name, value: t.value }))
tracksSpotify.forEach((t) => tracks.push({ name: t.name, value: t.value }))
return interaction.respond(tracks)
},
async execute(interaction: ChatInputCommandInteraction) {
let member = interaction.member as GuildMember
let voiceChannel = member.voice.channel
if (!voiceChannel) return await interaction.reply({ content: 'T\'es pas dans un vocal, idiot !', ephemeral: true })
let botChannel = interaction.guild?.members.me?.voice.channel
if (botChannel && voiceChannel.id !== botChannel.id) return await interaction.reply({ content: 'T\'es pas dans mon vocal !', ephemeral: true })
await interaction.deferReply()
let query = interaction.options.getString('recherche', true)
let player = useMainPlayer()
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) {
if (interaction.guild) queue = player.nodes.create(interaction.guild, {
metadata: {
channel: interaction.channel,
client: interaction.guild.members.me,
requestedBy: interaction.user
},
selfDeaf: true,
volume: 20,
leaveOnEmpty: true,
leaveOnEmptyCooldown: 30000,
leaveOnEnd: true,
leaveOnEndCooldown: 300000
})
else return
}
try { if (!queue.connection) await queue.connect(voiceChannel) }
catch (error: unknown) { console.error(error) }
let guildProfile = await dbGuild.findOne({ guildId: queue.guild.id })
if (!guildProfile) return console.log(`Database data for **${queue.guild.name}** does not exist !`)
let dbData = guildProfile.get('guildPlayer.replay')
dbData['textChannelId'] = interaction.channel?.id
dbData['voiceChannelId'] = voiceChannel.id
guildProfile.set('guildPlayer.replay', dbData)
await guildProfile.save().catch(console.error)
let result = await player.search(query, { requestedBy: interaction.user })
if (!result.hasTracks()) return interaction.followUp(`Aucune musique trouvée pour **${query}** !`)
let track = result.tracks[0]
let entry = queue.tasksQueue.acquire()
await entry.getTask()
queue.addTrack(track)
try {
if (!queue.isPlaying()) await queue.node.play()
let track_source = track.source === 'youtube' ? 'Youtube' : track.source === 'spotify' ? 'Spotify' : 'Inconnu'
return interaction.followUp(`Chargement de la musique **${track.title}** de **${track.author}** sur **${track_source}**...`)
} catch (error: unknown) { console.error(error) }
finally { queue.tasksQueue.release() }
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction, AutocompleteInteraction, GuildMember } from "discord.js"
import { useMainPlayer, useQueue } from "discord-player"
import { SpotifyExtractor } from "@discord-player/extractor"
import { YoutubeiExtractor } from "discord-player-youtubei"
import { startProgressSaving } from "@/utils/player"
import type { TrackSearchResult } from "@/types/player"
import type { GuildPlayer } from "@/types/schemas"
import dbGuild from "@/schemas/guild"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("play")
.setDescription("Play a song")
.setNameLocalizations({ fr: "jouer" })
.setDescriptionLocalizations({ fr: "Jouer une musique" })
.addStringOption(option => option
.setName("search")
.setDescription("Music title to search for")
.setNameLocalizations({ fr: "recherche" })
.setDescriptionLocalizations({ fr: "Titre de la musique à chercher" })
.setRequired(true)
.setAutocomplete(true)
)
export async function execute(interaction: ChatInputCommandInteraction) {
const member = interaction.member as GuildMember
const voiceChannel = member.voice.channel
if (!voiceChannel) return interaction.reply({ content: t(interaction.locale, "player.not_in_voice"), flags: MessageFlags.Ephemeral })
const botChannel = interaction.guild?.members.me?.voice.channel
if (botChannel && voiceChannel.id !== botChannel.id) return interaction.reply({ content: t(interaction.locale, "player.not_in_same_voice"), flags: MessageFlags.Ephemeral })
await interaction.deferReply()
const query = interaction.options.getString("search", true)
const player = useMainPlayer()
let queue = useQueue(interaction.guild?.id ?? "")
if (!queue) {
if (interaction.guild) queue = player.nodes.create(interaction.guild, {
metadata: {
channel: interaction.channel,
client: interaction.guild.members.me,
requestedBy: interaction.user
},
selfDeaf: true,
volume: 20,
leaveOnEmpty: true,
leaveOnEmptyCooldown: 30000,
leaveOnEnd: true,
leaveOnEndCooldown: 300000
})
else return
}
try { if (!queue.connection) await queue.connect(voiceChannel) }
catch (error) { console.error(error) }
const guildProfile = await dbGuild.findOne({ guildId: queue.guild.id })
if (!guildProfile) return interaction.reply({ content: t(interaction.locale, "common.database_not_found"), flags: MessageFlags.Ephemeral })
const botId = interaction.client.user.id
const dbData = guildProfile.get("guildPlayer") as GuildPlayer
dbData.instances ??= []
const instanceIndex = dbData.instances.findIndex(instance => instance.botId === botId)
const instance = { botId, replay: {
textChannelId: interaction.channel?.id ?? "",
voiceChannelId: voiceChannel.id,
trackUrl: "",
progress: 0
} }
if (instanceIndex === -1) dbData.instances.push(instance)
else dbData.instances[instanceIndex] = instance
guildProfile.set("guildPlayer", dbData)
guildProfile.markModified("guildPlayer")
await guildProfile.save().catch(console.error)
const result = await player.search(query, { requestedBy: interaction.user })
if (!result.hasTracks()) return interaction.followUp({ content: t(interaction.locale, "player.no_track_found", { query }), flags: MessageFlags.Ephemeral })
const track = result.tracks[0]
const entry = queue.tasksQueue.acquire()
await entry.getTask()
queue.addTrack(track)
try {
if (!queue.isPlaying()) await queue.node.play()
startProgressSaving(queue.guild.id, botId)
const track_source = track.source === "spotify" ? t(interaction.locale, "player.sources.spotify") : track.source === "youtube" ? t(interaction.locale, "player.sources.youtube") : t(interaction.locale, "player.sources.unknown")
return await interaction.followUp(t(interaction.locale, "player.loading_track", { title: track.title, author: track.author, source: track_source }))
}
catch (error) { console.error(error) }
finally { queue.tasksQueue.release() }
}
export async function autocompleteRun(interaction: AutocompleteInteraction) {
const query = interaction.options.getString("search", true)
if (!query) return interaction.respond([])
const player = useMainPlayer()
const resultsSpotify = await player.search(query, { searchEngine: `ext:${SpotifyExtractor.identifier}` })
const resultsYouTube = await player.search(query, { searchEngine: `ext:${YoutubeiExtractor.identifier}` })
const tracksSpotify = resultsSpotify.tracks.slice(0, 5).map(t => ({
name: `Spotify: ${`${t.title} - ${t.author} (${t.duration})`.length > 75 ? `${`${t.title} - ${t.author}`.substring(0, 75)}... (${t.duration})` : `${t.title} - ${t.author} (${t.duration})`}`,
value: t.url
}))
const tracksYouTube = resultsYouTube.tracks.slice(0, 5).map(t => ({
name: `YouTube: ${`${t.title} - ${t.author} (${t.duration})`.length > 75 ? `${`${t.title} - ${t.author}`.substring(0, 75)}... (${t.duration})` : `${t.title} - ${t.author} (${t.duration})`}`,
value: t.url
}))
const tracks: TrackSearchResult[] = []
tracksSpotify.forEach((t) => tracks.push({ name: t.name, value: t.value }))
tracksYouTube.forEach((t) => tracks.push({ name: t.name, value: t.value }))
return interaction.respond(tracks)
}

View File

@@ -1,15 +1,18 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useHistory } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('previous')
.setDescription('Joue la musique précédente.'),
async execute(interaction: ChatInputCommandInteraction) {
let history = useHistory(interaction.guild?.id ?? '')
if (!history) return await interaction.reply('Il n\'y a pas d\'historique de musique !')
await history.previous()
return await interaction.reply('Musique précédente jouée !')
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useHistory } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("previous")
.setDescription("Play the previous song")
.setNameLocalizations({ fr: "precedent" })
.setDescriptionLocalizations({ fr: "Joue la musique précédente" })
export async function execute(interaction: ChatInputCommandInteraction) {
const history = useHistory(interaction.guild?.id ?? "")
if (!history) return interaction.reply({ content: t(interaction.locale, "player.no_session"), flags: MessageFlags.Ephemeral })
await history.previous()
return interaction.reply({ content: t(interaction.locale, "player.previous_played"), flags: MessageFlags.Ephemeral })
}

View File

@@ -1,19 +1,22 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('queue')
.setDescription("Récupérer la file d'attente."),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.reply({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
if (!queue.currentTrack) return interaction.reply({ content: 'Aucune musique en cours de lecture.' })
let track = `[${queue.currentTrack.title}](${queue.currentTrack.url})`
let tracks = queue.tracks.map((track, index) => { return `${index + 1}. [${track.title}](${track.url})` })
if (tracks.length === 0) return interaction.reply({ content: `Lecture en cours : ${track} \nAucune musique dans la file d'attente.` })
return interaction.reply({ content: `Lecture en cours : ${track} \nFile d'attente actuelle : \n${tracks.join('\n')}` })
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("queue")
.setDescription("Get the queue")
.setNameLocalizations({ fr: "file" })
.setDescriptionLocalizations({ fr: "Récupérer la file d'attente." })
export async function execute(interaction: ChatInputCommandInteraction) {
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.reply({ content: t(interaction.locale, "player.no_queue_search_instead"), flags: MessageFlags.Ephemeral})
if (!queue.currentTrack) return interaction.reply({ content: t(interaction.locale, "player.no_track_playing"), flags: MessageFlags.Ephemeral})
const track = `[${queue.currentTrack.title}](${queue.currentTrack.url})`
const tracks = queue.tracks.map((track, index) => { return `${index + 1}. [${track.title}](${track.url})` })
if (tracks.length === 0) return interaction.reply({ content: t(interaction.locale, "player.now_playing_no_queue", { track }) })
return interaction.reply({ content: t(interaction.locale, "player.now_playing_with_queue", { track, tracks: tracks.join("\n") }) })
}

View File

@@ -1,15 +1,18 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('resume')
.setDescription('Reprendre la musique.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.setPaused(!queue.node.isPaused())
return await interaction.reply('Musique reprise !')
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("resume")
.setDescription("Resume the music")
.setNameLocalizations({ fr: "reprendre" })
.setDescriptionLocalizations({ fr: "Reprendre la musique" })
export async function execute(interaction: ChatInputCommandInteraction) {
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue_search_instead"), flags: MessageFlags.Ephemeral})
queue.node.setPaused(!queue.node.isPaused())
return interaction.reply(t(interaction.locale, "player.resumed"))
}

View File

@@ -1,15 +1,18 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('shuffle')
.setDescription('Mélange la file d\'attente.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.tracks.shuffle()
return await interaction.reply('File d\'attente mélangée !')
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("shuffle")
.setDescription("Shuffle the queue")
.setNameLocalizations({ fr: "melanger" })
.setDescriptionLocalizations({ fr: "Mélange la file d'attente" })
export async function execute(interaction: ChatInputCommandInteraction) {
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue_search_instead"), flags: MessageFlags.Ephemeral})
queue.tracks.shuffle()
return interaction.reply(t(interaction.locale, "player.shuffled"))
}

View File

@@ -1,15 +1,18 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('skip')
.setDescription('Passer la musique en cours.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.skip()
return await interaction.reply('Musique passée !')
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("skip")
.setDescription("Skip the current song")
.setNameLocalizations({ fr: "passer" })
.setDescriptionLocalizations({ fr: "Passer la musique en cours" })
export async function execute(interaction: ChatInputCommandInteraction) {
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue_search_instead"), flags: MessageFlags.Ephemeral})
queue.node.skip()
return interaction.reply(t(interaction.locale, "player.skipped"))
}

View File

@@ -1,15 +1,21 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('stop')
.setDescription('Arrêter la musique.'),
async execute(interaction: ChatInputCommandInteraction) {
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.delete()
return await interaction.reply('Musique arrêtée !')
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { stopProgressSaving } from "@/utils/player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("stop")
.setDescription("Stop the music")
.setNameLocalizations({ fr: "arreter" })
.setDescriptionLocalizations({ fr: "Arrêter la musique" })
export async function execute(interaction: ChatInputCommandInteraction) {
await stopProgressSaving(interaction.guild?.id ?? "", interaction.client.user.id)
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue_search_instead"), flags: MessageFlags.Ephemeral})
queue.delete()
return interaction.reply(t(interaction.locale, "player.stopped"))
}

View File

@@ -1,21 +1,26 @@
import { SlashCommandBuilder, ChatInputCommandInteraction } from 'discord.js'
import { useQueue } from 'discord-player'
export default {
data: new SlashCommandBuilder()
.setName('volume')
.setDescription('Modifie le volume de la musique.')
.addIntegerOption(option => option.setName('volume')
.setDescription('Le volume à mettre (%)')
.setRequired(true)
.setMinValue(1)
.setMaxValue(100)),
async execute(interaction: ChatInputCommandInteraction) {
let volume = interaction.options.getInteger('volume')
let queue = useQueue(interaction.guild?.id ?? '')
if (!queue) return interaction.followUp({ content: 'Aucune file d\'attente en cours, recherche une musique plutôt !' })
queue.node.setVolume(volume as number)
return await interaction.reply(`Volume modifié à ${volume}% !`)
}
}
import { SlashCommandBuilder, MessageFlags } from "discord.js"
import type { ChatInputCommandInteraction } from "discord.js"
import { useQueue } from "discord-player"
import { t } from "@/utils/i18n"
export const data = new SlashCommandBuilder()
.setName("volume")
.setDescription("Change the music volume")
.setDescriptionLocalizations({ fr: "Modifie le volume de la musique" })
.addIntegerOption(option => option
.setName("volume")
.setDescription("The volume to set (%)")
.setDescriptionLocalizations({ fr: "Le volume à mettre (%)" })
.setRequired(true)
.setMinValue(0)
.setMaxValue(100)
)
export async function execute(interaction: ChatInputCommandInteraction) {
const volume = interaction.options.getInteger("volume", true)
const queue = useQueue(interaction.guild?.id ?? "")
if (!queue) return interaction.followUp({ content: t(interaction.locale, "player.no_queue_search_instead"), flags: MessageFlags.Ephemeral})
queue.node.setVolume(volume)
return interaction.reply(t(interaction.locale, "player.volume_changed", { volume: volume.toString() }))
}