Réécriture complète 4.0
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6m16s
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 6m16s
This commit is contained in:
11
src/buttons/freebox/index.ts
Normal file
11
src/buttons/freebox/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import * as lcd_status from "./lcd_status"
|
||||
import * as refresh_status from "./refresh_status"
|
||||
import * as test_connection from "./test_connection"
|
||||
|
||||
import type { Button } from "@/types"
|
||||
|
||||
export default [
|
||||
lcd_status,
|
||||
refresh_status,
|
||||
test_connection
|
||||
] as Button[]
|
||||
88
src/buttons/freebox/lcd_status.ts
Normal file
88
src/buttons/freebox/lcd_status.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { EmbedBuilder, MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import crypto from "crypto"
|
||||
import * as Freebox from "@/utils/freebox"
|
||||
import type { APIResponseData, APIResponseDataError, GetChallenge, LcdConfig, OpenSession } from "@/types/freebox"
|
||||
import type { GuildFbx } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "freebox_lcd_status"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral })
|
||||
|
||||
const guildProfile = await dbGuild.findOne({ guildId: interaction.guild?.id })
|
||||
if (!guildProfile) return interaction.followUp({ content: t(interaction.locale, "common.database_not_found"), flags: MessageFlags.Ephemeral })
|
||||
|
||||
const dbData = guildProfile.get("guildFbx") as GuildFbx
|
||||
if (!dbData.enabled || !dbData.host || !dbData.appToken) {
|
||||
return interaction.followUp({ content: t(interaction.locale, "freebox.general.incomplete_configuration"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
|
||||
try {
|
||||
// Connexion à l'API Freebox
|
||||
const challengeData = await Freebox.Login.Challenge(dbData.host) as APIResponseData<GetChallenge>
|
||||
if (!challengeData.success) return await Freebox.handleError(challengeData as APIResponseDataError, interaction, false)
|
||||
|
||||
const password = crypto.createHmac("sha1", dbData.appToken).update(challengeData.result.challenge).digest("hex")
|
||||
const sessionData = await Freebox.Login.Session(dbData.host, password) as APIResponseData<OpenSession>
|
||||
if (!sessionData.success) return await Freebox.handleError(sessionData as APIResponseDataError, interaction, false)
|
||||
|
||||
const sessionToken = sessionData.result.session_token
|
||||
if (!sessionToken) return await interaction.followUp({ content: t(interaction.locale, "freebox.auth.session_token_failed"), flags: MessageFlags.Ephemeral })
|
||||
|
||||
// Récupération de la configuration LCD
|
||||
const lcdData = await Freebox.Get.LcdConfig(dbData.host, sessionToken) as APIResponseData<LcdConfig>
|
||||
if (!lcdData.success) return await Freebox.handleError(lcdData as APIResponseDataError, interaction, false)
|
||||
|
||||
const lcdConfig = lcdData.result
|
||||
|
||||
// Création de l'embed avec les informations LCD
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(t(interaction.locale, "freebox.lcd.config_title"))
|
||||
.setColor(lcdConfig.led_strip_enabled ? 0x00ff00 : 0xff0000)
|
||||
.addFields(
|
||||
{
|
||||
name: t(interaction.locale, "freebox.lcd.led_strip"),
|
||||
value: lcdConfig.led_strip_enabled ? t(interaction.locale, "freebox.lcd.led_strip_on") : t(interaction.locale, "freebox.lcd.led_strip_off"),
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: t(interaction.locale, "freebox.lcd.brightness"),
|
||||
value: `${lcdConfig.brightness}%`,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: t(interaction.locale, "freebox.lcd.orientation"),
|
||||
value: lcdConfig.orientation === 0 ? t(interaction.locale, "freebox.lcd.orientation_portrait") : t(interaction.locale, "freebox.lcd.orientation_landscape"),
|
||||
inline: true
|
||||
}
|
||||
)
|
||||
|
||||
// Informations du timer si configuré
|
||||
if (dbData.lcd) {
|
||||
const timerStatus = dbData.lcd.enabled ? t(interaction.locale, "freebox.status.timer_enabled") : t(interaction.locale, "freebox.status.timer_disabled")
|
||||
const botManaged = dbData.lcd.botId ? `<@${dbData.lcd.botId}>` : t(interaction.locale, "freebox.status.timer_no_manager")
|
||||
const morningTime = dbData.lcd.morningTime ?? t(interaction.locale, "freebox.status.timer_not_configured")
|
||||
const nightTime = dbData.lcd.nightTime ?? t(interaction.locale, "freebox.status.timer_not_configured")
|
||||
|
||||
embed.addFields({
|
||||
name: t(interaction.locale, "freebox.lcd.timer_auto"),
|
||||
value: [
|
||||
t(interaction.locale, "freebox.timer.status_field", { status: timerStatus }),
|
||||
t(interaction.locale, "freebox.timer.managed_by", { manager: botManaged }),
|
||||
t(interaction.locale, "freebox.timer.morning", { time: morningTime }),
|
||||
t(interaction.locale, "freebox.timer.night", { time: nightTime })
|
||||
].join('\n'),
|
||||
inline: false
|
||||
})
|
||||
}
|
||||
|
||||
embed.setTimestamp()
|
||||
|
||||
return await interaction.followUp({ embeds: [embed], flags: MessageFlags.Ephemeral })
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la récupération de l'état LCD:", error)
|
||||
return interaction.followUp({ content: t(interaction.locale, "freebox.lcd.unexpected_error"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
}
|
||||
76
src/buttons/freebox/refresh_status.ts
Normal file
76
src/buttons/freebox/refresh_status.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { EmbedBuilder, MessageFlags, ButtonBuilder, ButtonStyle, ActionRowBuilder } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import type { GuildFbx } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "freebox_refresh_status"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
await interaction.deferUpdate()
|
||||
|
||||
const guildProfile = await dbGuild.findOne({ guildId: interaction.guild?.id })
|
||||
if (!guildProfile) return interaction.followUp({ content: t(interaction.locale, "common.database_not_found"), flags: MessageFlags.Ephemeral })
|
||||
|
||||
const dbData = guildProfile.get("guildFbx") as GuildFbx
|
||||
|
||||
// Reconstruire l'embed de statut actualisé
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(t(interaction.locale, "freebox.status.title"))
|
||||
.setColor(dbData.enabled ? 0x00ff00 : 0xff0000)
|
||||
.addFields(
|
||||
{
|
||||
name: t(interaction.locale, "freebox.status.config_section"),
|
||||
value: [
|
||||
t(interaction.locale, "freebox.status.module_field", { status: dbData.enabled ? t(interaction.locale, "freebox.common.enabled") : t(interaction.locale, "freebox.common.disabled") }),
|
||||
t(interaction.locale, "freebox.status.host_field", { value: dbData.host ? `\`${dbData.host}\`` : t(interaction.locale, "freebox.status.host_not_configured") }),
|
||||
t(interaction.locale, "freebox.status.token_field", { status: dbData.appToken ? t(interaction.locale, "freebox.status.token_configured") : t(interaction.locale, "freebox.status.token_not_configured") })
|
||||
].join('\n'),
|
||||
inline: false
|
||||
}
|
||||
)
|
||||
|
||||
// Informations LCD si disponibles
|
||||
if (dbData.lcd) {
|
||||
const lcdStatus = dbData.lcd.enabled ? t(interaction.locale, "freebox.common.enabled") : t(interaction.locale, "freebox.common.disabled")
|
||||
const botManaged = dbData.lcd.botId ? `<@${dbData.lcd.botId}>` : t(interaction.locale, "freebox.status.timer_no_manager")
|
||||
const morningTime = dbData.lcd.morningTime ?? t(interaction.locale, "freebox.status.timer_not_configured")
|
||||
const nightTime = dbData.lcd.nightTime ?? t(interaction.locale, "freebox.status.timer_not_configured")
|
||||
|
||||
embed.addFields({
|
||||
name: t(interaction.locale, "freebox.status.timer_section"),
|
||||
value: [
|
||||
t(interaction.locale, "freebox.timer.status_field", { status: lcdStatus }),
|
||||
t(interaction.locale, "freebox.timer.managed_by", { manager: botManaged }),
|
||||
t(interaction.locale, "freebox.timer.morning", { time: morningTime }),
|
||||
t(interaction.locale, "freebox.timer.night", { time: nightTime })
|
||||
].join('\n'),
|
||||
inline: false
|
||||
})
|
||||
}
|
||||
|
||||
embed.setTimestamp()
|
||||
|
||||
// Reconstruire les boutons
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("freebox_test_connection")
|
||||
.setLabel(t(interaction.locale, "freebox.buttons.test_connection"))
|
||||
.setEmoji("🔌")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(!dbData.appToken),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("freebox_lcd_status")
|
||||
.setLabel(t(interaction.locale, "freebox.buttons.lcd_status"))
|
||||
.setEmoji("💡")
|
||||
.setStyle(ButtonStyle.Secondary)
|
||||
.setDisabled(!dbData.appToken),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("freebox_refresh_status")
|
||||
.setLabel(t(interaction.locale, "freebox.buttons.refresh_status"))
|
||||
.setEmoji("🔄")
|
||||
.setStyle(ButtonStyle.Success)
|
||||
)
|
||||
|
||||
return interaction.editReply({ embeds: [embed], components: [buttons] })
|
||||
}
|
||||
71
src/buttons/freebox/test_connection.ts
Normal file
71
src/buttons/freebox/test_connection.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { EmbedBuilder, MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import crypto from "crypto"
|
||||
import * as Freebox from "@/utils/freebox"
|
||||
import type { APIResponseData, APIResponseDataError, APIResponseDataVersion, ConnectionStatus, GetChallenge, OpenSession } from "@/types/freebox"
|
||||
import type { GuildFbx } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "freebox_test_connection"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral })
|
||||
|
||||
const guildProfile = await dbGuild.findOne({ guildId: interaction.guild?.id })
|
||||
if (!guildProfile) return interaction.followUp({ content: t(interaction.locale, "common.database_not_found"), flags: MessageFlags.Ephemeral })
|
||||
|
||||
const dbData = guildProfile.get("guildFbx") as GuildFbx
|
||||
if (!dbData.enabled || !dbData.host || !dbData.appToken) {
|
||||
return interaction.followUp({ content: t(interaction.locale, "freebox.general.incomplete_configuration"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
|
||||
try {
|
||||
// Test de la version API
|
||||
const versionData = await Freebox.Core.Version(dbData.host) as APIResponseDataVersion
|
||||
|
||||
// Test d'authentification
|
||||
const challengeData = await Freebox.Login.Challenge(dbData.host) as APIResponseData<GetChallenge>
|
||||
if (!challengeData.success) return await Freebox.handleError(challengeData as APIResponseDataError, interaction, false)
|
||||
|
||||
const password = crypto.createHmac("sha1", dbData.appToken).update(challengeData.result.challenge).digest("hex")
|
||||
const sessionData = await Freebox.Login.Session(dbData.host, password) as APIResponseData<OpenSession>
|
||||
if (!sessionData.success) return await Freebox.handleError(sessionData as APIResponseDataError, interaction, false)
|
||||
|
||||
const sessionToken = sessionData.result.session_token
|
||||
if (!sessionToken) return await interaction.followUp({ content: t(interaction.locale, "freebox.auth.session_token_failed"), flags: MessageFlags.Ephemeral })
|
||||
|
||||
// Test de la connexion
|
||||
const connectionData = await Freebox.Get.Connection(dbData.host, sessionToken) as APIResponseData<ConnectionStatus>
|
||||
if (!connectionData.success) return await Freebox.handleError(connectionData as APIResponseDataError, interaction, false)
|
||||
|
||||
// Création de l'embed de succès
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(t(interaction.locale, "freebox.test.connection_success_title"))
|
||||
.setColor(0x00ff00)
|
||||
.addFields(
|
||||
{
|
||||
name: t(interaction.locale, "freebox.test.api_field"),
|
||||
value: t(interaction.locale, "freebox.test.api_version", { version: versionData.api_version }),
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: t(interaction.locale, "freebox.test.auth_field"),
|
||||
value: t(interaction.locale, "freebox.test.token_valid"),
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: t(interaction.locale, "freebox.test.connection_field"),
|
||||
value: connectionData.result.state === "up" ?
|
||||
t(interaction.locale, "freebox.test.connection_active") :
|
||||
t(interaction.locale, "freebox.test.connection_inactive"),
|
||||
inline: true
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
|
||||
return await interaction.followUp({ embeds: [embed], flags: MessageFlags.Ephemeral })
|
||||
} catch (error) {
|
||||
console.error("Erreur lors du test de connexion Freebox:", error)
|
||||
return interaction.followUp({ content: t(interaction.locale, "freebox.test.connection_error"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
}
|
||||
26
src/buttons/index.ts
Normal file
26
src/buttons/index.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import freebox from "./freebox"
|
||||
import player from "./player"
|
||||
import twitch from "./twitch"
|
||||
|
||||
import type { Button, ButtonFolder } from "@/types"
|
||||
|
||||
export const buttonFolders = [
|
||||
{
|
||||
name: "freebox",
|
||||
commands: freebox
|
||||
},
|
||||
{
|
||||
name: "player",
|
||||
commands: player
|
||||
},
|
||||
{
|
||||
name: "twitch",
|
||||
commands: twitch
|
||||
}
|
||||
] as ButtonFolder[]
|
||||
|
||||
export default [
|
||||
...freebox,
|
||||
...player,
|
||||
...twitch
|
||||
] as Button[]
|
||||
@@ -1,16 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'loop',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
let loop = queue.repeatMode === 0 ? 1 : queue.repeatMode === 1 ? 2 : queue.repeatMode === 2 ? 3 : 0
|
||||
await queue.setRepeatMode(loop)
|
||||
await interaction.followUp({ content:`Boucle ${loop === 0 ? 'désactivée' : loop === 1 ? 'en mode Titre' : loop === 2 ? 'en mode File d\'Attente' : 'en autoplay'}.`, ephemeral: true })
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'pause',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
await queue.node.setPaused(!queue.node.isPaused())
|
||||
return interaction.followUp({ content: 'Musique mise en pause !', ephemeral: true })
|
||||
}
|
||||
}
|
||||
15
src/buttons/player/disco_channel.ts
Normal file
15
src/buttons/player/disco_channel.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { MessageFlags, ChannelType, ActionRowBuilder, ChannelSelectMenuBuilder } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_disco_channel"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const channelSelect = new ChannelSelectMenuBuilder()
|
||||
.setCustomId("player_disco_channel")
|
||||
.setPlaceholder(t(interaction.locale, "selectmenus.placeholders.select_channel_disco"))
|
||||
.addChannelTypes(ChannelType.GuildText, ChannelType.GuildAnnouncement)
|
||||
|
||||
const row = new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(channelSelect)
|
||||
|
||||
return interaction.reply({ content: t(interaction.locale, "player.disco.select_channel"), components: [row], flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
24
src/buttons/player/disco_disable.ts
Normal file
24
src/buttons/player/disco_disable.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } 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 id = "player_disco_disable"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
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
|
||||
dbData.enabled = false
|
||||
|
||||
guildProfile.set("guildPlayer.disco", dbData)
|
||||
guildProfile.markModified("guildPlayer.disco")
|
||||
await guildProfile.save().catch(console.error)
|
||||
|
||||
// Utiliser la fonction utilitaire pour générer l'embed et les composants mis à jour
|
||||
const { embed, components } = generateDiscoEmbed(dbData, interaction.client, interaction.guild?.id ?? "", interaction.locale)
|
||||
|
||||
return interaction.update({ embeds: [embed], components: components })
|
||||
}
|
||||
31
src/buttons/player/disco_enable.ts
Normal file
31
src/buttons/player/disco_enable.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } 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 id = "player_disco_enable"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
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
|
||||
|
||||
// Vérifier qu'un canal est configuré avant d'activer
|
||||
if (!dbData.channelId) return interaction.reply({
|
||||
content: t(interaction.locale, "player.disco.configure_channel_first"),
|
||||
flags: MessageFlags.Ephemeral
|
||||
})
|
||||
|
||||
dbData.enabled = true
|
||||
|
||||
guildProfile.set("guildPlayer.disco", dbData)
|
||||
guildProfile.markModified("guildPlayer.disco")
|
||||
await guildProfile.save().catch(console.error)
|
||||
|
||||
// Utiliser la fonction utilitaire pour générer l'embed et les composants mis à jour
|
||||
const { embed, components } = generateDiscoEmbed(dbData, interaction.client, interaction.guild?.id ?? "", interaction.locale)
|
||||
|
||||
return interaction.update({ embeds: [embed], components: components })
|
||||
}
|
||||
29
src/buttons/player/index.ts
Normal file
29
src/buttons/player/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import * as disco_disable from "./disco_disable"
|
||||
import * as disco_enable from "./disco_enable"
|
||||
import * as disco_channel from "./disco_channel"
|
||||
import * as loop from "./loop"
|
||||
import * as pause from "./pause"
|
||||
import * as previous from "./previous"
|
||||
import * as resume from "./resume"
|
||||
import * as shuffle from "./shuffle"
|
||||
import * as skip from "./skip"
|
||||
import * as stop from "./stop"
|
||||
import * as volume_down from "./volume_down"
|
||||
import * as volume_up from "./volume_up"
|
||||
|
||||
import type { Button } from "@/types"
|
||||
|
||||
export default [
|
||||
disco_channel,
|
||||
disco_disable,
|
||||
disco_enable,
|
||||
loop,
|
||||
pause,
|
||||
previous,
|
||||
resume,
|
||||
shuffle,
|
||||
skip,
|
||||
stop,
|
||||
volume_down,
|
||||
volume_up
|
||||
] as Button[]
|
||||
22
src/buttons/player/loop.ts
Normal file
22
src/buttons/player/loop.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_loop"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
const loop = queue.repeatMode === 0 ? 1 : queue.repeatMode === 1 ? 2 : queue.repeatMode === 2 ? 3 : 0
|
||||
queue.setRepeatMode(loop)
|
||||
|
||||
const loopModes = {
|
||||
0: t(interaction.locale, "player.loop_off"),
|
||||
1: t(interaction.locale, "player.loop_track"),
|
||||
2: t(interaction.locale, "player.loop_queue"),
|
||||
3: t(interaction.locale, "player.loop_autoplay")
|
||||
}
|
||||
|
||||
return interaction.followUp({ content: loopModes[loop], flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
13
src/buttons/player/pause.ts
Normal file
13
src/buttons/player/pause.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_pause"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
queue.node.setPaused(!queue.node.isPaused())
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.paused"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
13
src/buttons/player/previous.ts
Normal file
13
src/buttons/player/previous.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useHistory } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_previous"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const history = useHistory(interaction.guild?.id ?? "")
|
||||
if (!history) return
|
||||
|
||||
await history.previous()
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.previous_played"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
13
src/buttons/player/resume.ts
Normal file
13
src/buttons/player/resume.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_resume"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
queue.node.setPaused(!queue.node.isPaused())
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.resumed"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
13
src/buttons/player/shuffle.ts
Normal file
13
src/buttons/player/shuffle.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_shuffle"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
queue.tracks.shuffle()
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.shuffled"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
13
src/buttons/player/skip.ts
Normal file
13
src/buttons/player/skip.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_skip"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
queue.node.skip()
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.skipped"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
16
src/buttons/player/stop.ts
Normal file
16
src/buttons/player/stop.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { stopProgressSaving } from "@/utils/player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_stop"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
await stopProgressSaving(interaction.guild?.id ?? "", interaction.client.user.id)
|
||||
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
queue.delete()
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.stopped"), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
14
src/buttons/player/volume_down.ts
Normal file
14
src/buttons/player/volume_down.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_volume_down"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
const volume = queue.node.volume - 10
|
||||
queue.node.setVolume(volume)
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.volume_changed_down", { volume: volume.toString() }), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
14
src/buttons/player/volume_up.ts
Normal file
14
src/buttons/player/volume_up.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { useQueue } from "discord-player"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "player_volume_up"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const queue = useQueue(interaction.guild?.id ?? "")
|
||||
if (!queue) return
|
||||
|
||||
const volume = queue.node.volume + 10
|
||||
queue.node.setVolume(volume)
|
||||
return interaction.followUp({ content: t(interaction.locale, "player.volume_changed", { volume: volume.toString() }), flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useHistory } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'previous',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let history = useHistory(guild.id)
|
||||
if (!history) return
|
||||
|
||||
await history.previous()
|
||||
return interaction.followUp({ content: 'Musique précédente jouée !', ephemeral: true })
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'resume',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
await queue.node.setPaused(!queue.node.isPaused())
|
||||
return interaction.followUp({ content: 'Musique reprise !', ephemeral: true })
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'shuffle',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
await queue.tracks.shuffle()
|
||||
return interaction.followUp({ content: 'File d\'attente mélangée !', ephemeral: true })
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'skip',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
await queue.node.skip()
|
||||
return interaction.followUp({ content: 'Musique passée !', ephemeral: true })
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'stop',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
await queue.delete()
|
||||
return interaction.followUp({ content: 'Musique arrêtée !', ephemeral: true })
|
||||
}
|
||||
}
|
||||
19
src/buttons/twitch/channel.ts
Normal file
19
src/buttons/twitch/channel.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { MessageFlags, ChannelType, ActionRowBuilder, ChannelSelectMenuBuilder } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "twitch_channel"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
const channelSelect = new ChannelSelectMenuBuilder()
|
||||
.setCustomId("twitch_channel")
|
||||
.setPlaceholder(t(interaction.locale, "twitch.select_notification_channel_placeholder"))
|
||||
.addChannelTypes(ChannelType.GuildText, ChannelType.GuildAnnouncement)
|
||||
|
||||
const row = new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(channelSelect)
|
||||
|
||||
return interaction.reply({
|
||||
content: t(interaction.locale, "twitch.select_notification_channel"),
|
||||
components: [row],
|
||||
flags: MessageFlags.Ephemeral
|
||||
})
|
||||
}
|
||||
28
src/buttons/twitch/disable.ts
Normal file
28
src/buttons/twitch/disable.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { generateTwitchEmbed } from "@/utils/twitch"
|
||||
import type { GuildTwitch } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "twitch_disable"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
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("guildTwitch") as GuildTwitch
|
||||
dbData.enabled = false
|
||||
dbData.botId = ""
|
||||
|
||||
guildProfile.set("guildTwitch", dbData)
|
||||
guildProfile.markModified("guildTwitch")
|
||||
await guildProfile.save().catch(console.error)
|
||||
|
||||
// Utiliser la fonction utilitaire pour générer l'embed et les composants mis à jour
|
||||
const { embed, components } = generateTwitchEmbed(dbData, interaction.client, interaction.guild?.id ?? "", interaction.locale)
|
||||
|
||||
return interaction.update({
|
||||
embeds: [embed],
|
||||
components: components
|
||||
})
|
||||
}
|
||||
28
src/buttons/twitch/enable.ts
Normal file
28
src/buttons/twitch/enable.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { generateTwitchEmbed } from "@/utils/twitch"
|
||||
import type { GuildTwitch } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "twitch_enable"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
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("guildTwitch") as GuildTwitch
|
||||
dbData.enabled = true
|
||||
dbData.botId = interaction.client.user.id
|
||||
|
||||
guildProfile.set("guildTwitch", dbData)
|
||||
guildProfile.markModified("guildTwitch")
|
||||
await guildProfile.save().catch(console.error)
|
||||
|
||||
// Utiliser la fonction utilitaire pour générer l'embed et les composants mis à jour
|
||||
const { embed, components } = generateTwitchEmbed(dbData, interaction.client, interaction.guild?.id ?? "", interaction.locale)
|
||||
|
||||
return interaction.update({
|
||||
embeds: [embed],
|
||||
components: components
|
||||
})
|
||||
}
|
||||
17
src/buttons/twitch/index.ts
Normal file
17
src/buttons/twitch/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import * as twitch_disable from "./disable"
|
||||
import * as twitch_enable from "./enable"
|
||||
import * as twitch_set_channel from "./channel"
|
||||
import * as twitch_list_streamers from "./streamer_list"
|
||||
import * as twitch_add_streamer from "./streamer_add"
|
||||
import * as twitch_remove_streamer from "./streamer_remove"
|
||||
|
||||
import type { Button } from "@/types"
|
||||
|
||||
export default [
|
||||
twitch_disable,
|
||||
twitch_enable,
|
||||
twitch_set_channel,
|
||||
twitch_list_streamers,
|
||||
twitch_add_streamer,
|
||||
twitch_remove_streamer
|
||||
] as Button[]
|
||||
20
src/buttons/twitch/streamer_add.ts
Normal file
20
src/buttons/twitch/streamer_add.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { MessageFlags } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import type { GuildTwitch } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { t } from "@/utils/i18n"
|
||||
|
||||
export const id = "twitch_streamer_add"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
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("guildTwitch") as GuildTwitch
|
||||
if (!dbData.enabled) return interaction.reply({ content: t(interaction.locale, "twitch.module_disabled"), flags: MessageFlags.Ephemeral })
|
||||
if (!dbData.channelId) return interaction.reply({ content: t(interaction.locale, "twitch.configure_channel_first"), flags: MessageFlags.Ephemeral })
|
||||
|
||||
return interaction.reply({
|
||||
content: t(interaction.locale, "twitch.add_streamer_command"),
|
||||
flags: MessageFlags.Ephemeral
|
||||
})
|
||||
}
|
||||
51
src/buttons/twitch/streamer_list.ts
Normal file
51
src/buttons/twitch/streamer_list.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { MessageFlags, EmbedBuilder } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import type { GuildTwitch } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { twitchClient } from "@/utils/twitch"
|
||||
import { t } from "@/utils/i18n"
|
||||
import { logConsole } from "@/utils/console"
|
||||
|
||||
export const id = "twitch_streamer_list"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
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("guildTwitch") as GuildTwitch
|
||||
if (!dbData.enabled) return interaction.reply({ content: t(interaction.locale, "twitch.module_disabled"), flags: MessageFlags.Ephemeral })
|
||||
if (!dbData.streamers.length) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(t(interaction.locale, "twitch.list.title"))
|
||||
.setDescription(t(interaction.locale, "twitch.list.empty_description"))
|
||||
.setColor(0x808080)
|
||||
.setTimestamp()
|
||||
|
||||
return interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
|
||||
const streamers = [] as string[]
|
||||
await Promise.all(dbData.streamers.map(async (streamer, index) => {
|
||||
try {
|
||||
const user = await twitchClient.users.getUserById(streamer.twitchUserId)
|
||||
if (user) {
|
||||
const discordUser = streamer.discordUserId ? `<@${streamer.discordUserId}>` : t(interaction.locale, "twitch.list.discord_not_associated")
|
||||
streamers.push(`**${index + 1}.** ${user.displayName}\n└ Discord: ${discordUser}\n└ ID: \`${streamer.twitchUserId}\``)
|
||||
} else {
|
||||
streamers.push(`**${index + 1}.** ${t(interaction.locale, "twitch.list.user_not_found")}\n└ ID: \`${streamer.twitchUserId}\``)
|
||||
}
|
||||
} catch (error) {
|
||||
logConsole('twitch', 'user_fetch_error_buttons', { id: streamer.twitchUserId })
|
||||
console.error(error)
|
||||
streamers.push(`**${index + 1}.** ${t(interaction.locale, "twitch.list.fetch_error")}\n└ ID: \`${streamer.twitchUserId}\``)
|
||||
}
|
||||
}))
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(t(interaction.locale, "twitch.list.title"))
|
||||
.setDescription(streamers.join("\n\n"))
|
||||
.setColor(0x9146FF)
|
||||
.setFooter({ text: t(interaction.locale, "twitch.list.footer", { count: streamers.length.toString() }) })
|
||||
.setTimestamp()
|
||||
|
||||
return interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
46
src/buttons/twitch/streamer_remove.ts
Normal file
46
src/buttons/twitch/streamer_remove.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { MessageFlags, ActionRowBuilder, StringSelectMenuBuilder } from "discord.js"
|
||||
import type { ButtonInteraction } from "discord.js"
|
||||
import { twitchClient } from "@/utils/twitch"
|
||||
import type { GuildTwitch } from "@/types/schemas"
|
||||
import dbGuild from "@/schemas/guild"
|
||||
import { t } from "@/utils/i18n"
|
||||
import { logConsole } from "@/utils/console"
|
||||
|
||||
export const id = "twitch_streamer_remove"
|
||||
export async function execute(interaction: ButtonInteraction) {
|
||||
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("guildTwitch") as GuildTwitch
|
||||
if (!dbData.enabled) return interaction.reply({ content: t(interaction.locale, "twitch.module_disabled"), flags: MessageFlags.Ephemeral })
|
||||
if (!dbData.streamers.length) return interaction.reply({ content: t(interaction.locale, "twitch.no_streamers_list"), flags: MessageFlags.Ephemeral })
|
||||
|
||||
// Créer la liste des streamers dans un menu de sélection
|
||||
const options = await Promise.all(dbData.streamers.map(async (streamer) => {
|
||||
try {
|
||||
const user = await twitchClient.users.getUserById(streamer.twitchUserId)
|
||||
return {
|
||||
label: user ? user.displayName : `ID: ${streamer.twitchUserId}`,
|
||||
value: streamer.twitchUserId,
|
||||
description: user ? `@${user.name}` : t(interaction.locale, "twitch.user_not_found")
|
||||
}
|
||||
} catch (error) {
|
||||
logConsole('twitch', 'user_fetch_error_buttons', { id: streamer.twitchUserId })
|
||||
console.error(error)
|
||||
return {
|
||||
label: `ID: ${streamer.twitchUserId}`,
|
||||
value: streamer.twitchUserId,
|
||||
description: t(interaction.locale, "twitch.fetch_error")
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
const selectMenu = new StringSelectMenuBuilder()
|
||||
.setCustomId("twitch_streamer_remove")
|
||||
.setPlaceholder(t(interaction.locale, "twitch.select_streamer_to_remove"))
|
||||
.addOptions(options.slice(0, 25)) // Discord limite à 25 options
|
||||
|
||||
const row = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(selectMenu)
|
||||
|
||||
return interaction.reply({ content: t(interaction.locale, "twitch.select_streamer_prompt"), components: [row], flags: MessageFlags.Ephemeral })
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'volume_down',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
let volume = queue.node.volume - 10
|
||||
await queue.node.setVolume(volume)
|
||||
return interaction.followUp({ content: `🔉 | Volume modifié à ${volume}% !`, ephemeral: true })
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js'
|
||||
import { useQueue } from 'discord-player'
|
||||
|
||||
export default {
|
||||
id: 'volume_up',
|
||||
async execute(interaction: ButtonInteraction) {
|
||||
let guild = interaction.guild
|
||||
if (!guild) return
|
||||
let queue = useQueue(guild.id)
|
||||
if (!queue) return
|
||||
|
||||
let volume = queue.node.volume + 10
|
||||
await queue.node.setVolume(volume)
|
||||
return interaction.followUp({ content: `🔊 | Volume modifié à ${volume}% !`, ephemeral: true })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user