Compare commits

..

16 Commits

Author SHA1 Message Date
8420344519 fix: remove all git rev thing i'll come back to that later
All checks were successful
Build and Deploy / typecheck (push) Successful in 31s
Build and Deploy / build (push) Successful in 31s
Build and Deploy / deploy (push) Successful in 2s
2026-06-01 22:33:47 +02:00
1c2d09cafc fix: rename workflow to deploy, and parse git rev in the dockerfile
All checks were successful
Build and Deploy / typecheck (push) Successful in 34s
Build and Deploy / build (push) Successful in 31s
Build and Deploy / deploy (push) Successful in 2s
2026-06-01 22:23:41 +02:00
4ce3e97727 feat(discord-bot): remove old gems rewards message
Some checks failed
Build and Deploy / typecheck (push) Successful in 1m27s
Build and Deploy / deploy (push) Has been cancelled
Build and Deploy / build (push) Has been cancelled
2026-06-01 21:58:02 +02:00
4059ea1ddf chore(discord-bot): remove all migration related code
All checks were successful
Build and Deploy / typecheck (push) Successful in 27s
Build and Deploy / build (push) Successful in 28s
Build and Deploy / deploy (push) Successful in 2s
2026-05-30 22:13:13 +02:00
82eb239f5e feat(discord-bot): remove REPORTS_JSON and implement embed migration
All checks were successful
Build and Deploy / typecheck (push) Successful in 29s
Build and Deploy / build (push) Successful in 25s
Build and Deploy / deploy (push) Successful in 4s
2026-05-30 21:58:47 +02:00
943d69472c feat(discord-bot): REPORTS_JSON for reports migration
All checks were successful
Build and Deploy / typecheck (push) Successful in 36s
Build and Deploy / build (push) Successful in 31s
Build and Deploy / deploy (push) Successful in 1s
2026-05-30 21:15:15 +02:00
fcd85350ec feat: use portainer hook instead of pushing image to gitea package repository
All checks were successful
Build and Deploy / typecheck (push) Successful in 1m28s
Build and Deploy / build (push) Successful in 13s
Build and Deploy / deploy (push) Successful in 1s
2026-05-30 12:36:33 +02:00
dab026de99 feat(discord-bot): add separator for report messages
All checks were successful
Build and Push Docker Image / typecheck (push) Successful in 31s
Build and Push Docker Image / build (push) Successful in 52s
2026-05-29 23:55:48 +02:00
d76ac73d84 feat(discord-bot): screenshots placeholder message to edit
All checks were successful
Build and Push Docker Image / typecheck (push) Successful in 26s
Build and Push Docker Image / build (push) Successful in 35s
2026-05-12 20:01:38 +02:00
d679a63d3d fix: also delete the screenshots message
All checks were successful
Build and Push Docker Image / typecheck (push) Successful in 24s
Build and Push Docker Image / build (push) Successful in 36s
2026-05-12 19:31:14 +02:00
2f7f8689b2 fix: missing env variable in docker-compose.yml
All checks were successful
Build and Push Docker Image / typecheck (push) Successful in 25s
Build and Push Docker Image / build (push) Successful in 10s
2026-05-12 19:26:57 +02:00
ca13301263 fix(discord-bot): missing types
All checks were successful
Build and Push Docker Image / typecheck (push) Successful in 24s
Build and Push Docker Image / build (push) Successful in 34s
2026-05-12 19:22:23 +02:00
00b3ade095 feat: implement reporting system
Some checks failed
Build and Push Docker Image / typecheck (push) Failing after 24s
Build and Push Docker Image / build (push) Has been skipped
2026-05-12 19:18:02 +02:00
f5a7dbf1e8 feat(discord-bot): add fdp command
All checks were successful
Build and Push Docker Image / typecheck (push) Successful in 23s
Build and Push Docker Image / build (push) Successful in 33s
2026-05-12 16:28:08 +02:00
69e461b54b fix: check command needs the packages to be built first
All checks were successful
Build and Push Docker Image / typecheck (push) Successful in 23s
Build and Push Docker Image / build (push) Successful in 38s
2026-05-12 16:06:18 +02:00
4b28b78800 feat(discord-bot): add tg command
Some checks failed
Build and Push Docker Image / typecheck (push) Failing after 13s
Build and Push Docker Image / build (push) Has been skipped
2026-05-12 16:04:01 +02:00
27 changed files with 1728 additions and 65 deletions

View File

@@ -1,4 +1,4 @@
name: Build and Push Docker Image name: Build and Deploy
on: on:
push: push:
@@ -32,14 +32,13 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Log in to DockerHub - name: Build Docker image
uses: docker/login-action@v3 run: docker build -f apps/discord-bot/Dockerfile .
with:
registry: git.pihkaal.me
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push Docker image deploy:
run: | runs-on: ubuntu-latest
docker build --build-arg COMMIT_SHA=$(git rev-parse --short HEAD) -t git.pihkaal.me/pihkaal/lbf-bot:latest -f apps/discord-bot/Dockerfile . needs: build
docker push git.pihkaal.me/pihkaal/lbf-bot:latest
steps:
- name: Trigger Portainer webhook
run: curl -X POST "${{ secrets.PORTAINER_WEBHOOK_URL }}"

View File

@@ -15,7 +15,4 @@ RUN pnpm --filter @lbf-bot/utils run build
RUN pnpm --filter @lbf-bot/database run build RUN pnpm --filter @lbf-bot/database run build
RUN pnpm --filter @lbf/discord-bot run build RUN pnpm --filter @lbf/discord-bot run build
ARG COMMIT_SHA=dev
ENV COMMIT_SHA=$COMMIT_SHA
CMD ["node", "apps/discord-bot/dist/index.js"] CMD ["node", "apps/discord-bot/dist/index.js"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@@ -15,9 +15,10 @@
"typescript": "^5.7.2" "typescript": "^5.7.2"
}, },
"dependencies": { "dependencies": {
"@lbf-bot/utils": "workspace:*",
"@lbf-bot/database": "workspace:*", "@lbf-bot/database": "workspace:*",
"discord.js": "^14.21.0", "@lbf-bot/utils": "workspace:*",
"discord.js": "^14.26.4",
"sharp": "^0.34.5",
"zod": "4.1.11" "zod": "4.1.11"
} }
} }

View File

@@ -0,0 +1,48 @@
import { AttachmentBuilder } from "discord.js";
import sharp from "sharp";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { noMention } from "~/discord";
import type { Command } from "./index";
const POOP_PATH = join(dirname(fileURLToPath(import.meta.url)), "../../assets/poop.png");
export const fdpCommand: Command = {
help: "Essaie et tu verras",
handler: async (message) => {
const avatarUrl = message.author.displayAvatarURL({ size: 512, extension: "png" });
const avatarBuffer = Buffer.from(await (await fetch(avatarUrl)).arrayBuffer());
const { width: avatarWidth, height: avatarHeight } = await sharp(avatarBuffer).metadata();
if (!avatarWidth || !avatarHeight) return;
const poopWidth = Math.floor(avatarWidth / 2);
const poopBuffer = await sharp(POOP_PATH).resize({ width: poopWidth }).toBuffer();
const { height: poopHeight } = await sharp(poopBuffer).metadata();
if (!poopHeight) return;
const overlap = Math.floor(poopHeight / 4);
const poopLeft = Math.floor((avatarWidth - poopWidth) / 2);
const result = await sharp({
create: {
width: avatarWidth,
height: avatarHeight + poopHeight - overlap,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0 },
},
})
.composite([
{ input: avatarBuffer, top: poopHeight - overlap, left: 0 },
{ input: poopBuffer, top: 0, left: poopLeft },
])
.webp()
.toBuffer();
await message.reply({
...noMention,
files: [new AttachmentBuilder(result, { name: "fdp.webp" })],
});
},
};

View File

@@ -1,10 +1,14 @@
import type { Message, OmitPartialGroupDMChannel } from "discord.js"; import type { Message, OmitPartialGroupDMChannel } from "discord.js";
import { fdpCommand } from "./fdp";
import { pingCommand } from "./ping"; import { pingCommand } from "./ping";
import { trackCommand } from "./tracking"; import { trackCommand } from "./tracking";
import { iconeCommand } from "./icone"; import { iconeCommand } from "./icone";
import { gemmesCommand } from "./gemmes"; import { gemmesCommand } from "./gemmes";
import { resultCommand } from "./result"; import { resultCommand } from "./result";
import { queteCommand } from "./quete"; import { queteCommand } from "./quete";
import { tgCommand } from "./tg";
import { reportmsgCommand } from "./reportmsg";
import { reportsCommand } from "./reports";
export type CommandHandler = ( export type CommandHandler = (
message: OmitPartialGroupDMChannel<Message<boolean>>, message: OmitPartialGroupDMChannel<Message<boolean>>,
@@ -17,10 +21,14 @@ export type Command = {
}; };
export const commands: Record<string, Command> = { export const commands: Record<string, Command> = {
fdp: fdpCommand,
ping: pingCommand, ping: pingCommand,
track: trackCommand, track: trackCommand,
icone: iconeCommand, icone: iconeCommand,
gemmes: gemmesCommand, gemmes: gemmesCommand,
quete: queteCommand, quete: queteCommand,
result: resultCommand, result: resultCommand,
tg: tgCommand,
reportmsg: reportmsgCommand,
reports: reportsCommand,
}; };

View File

@@ -1,5 +1,4 @@
import { noMention } from "~/discord"; import { noMention } from "~/discord";
import { env } from "~/env";
import type { Command } from "./index"; import type { Command } from "./index";
export const pingCommand: Command = { export const pingCommand: Command = {
@@ -7,7 +6,7 @@ export const pingCommand: Command = {
handler: async (message) => { handler: async (message) => {
await message.reply({ await message.reply({
options: noMention, options: noMention,
content: `🫵 Pong \`${env.COMMIT_SHA}\``, content: `🫵 Pong`,
}); });
}, },
}; };

View File

@@ -0,0 +1,23 @@
import { ChannelType } from "discord.js";
import { sendReportEmbed } from "~/reporting";
import { replyError } from "~/discord";
import type { Command } from "./index";
import { env } from "~/env";
export const reportmsgCommand: Command = {
help: "Envoie le message de signalement dans ce salon",
handler: async (message) => {
if (!message.member?.roles.cache.has(env.DISCORD_STAFF_ROLE_ID)) {
await replyError(message, "Tu t'es cru chez mémé ou quoi faut être staff");
return;
}
if (message.channel.type !== ChannelType.GuildText) {
await replyError(message, "Cette commande doit être utilisée dans un salon texte.");
return;
}
await message.delete();
await sendReportEmbed(message.channel);
},
};

View File

@@ -0,0 +1,50 @@
import { EmbedBuilder } from "discord.js";
import { db, tables, eq } from "@lbf-bot/database";
import { noMention, replyError } from "~/discord";
import { searchPlayer } from "~/wov";
import type { Command } from "./index";
export const reportsCommand: Command = {
help: "Liste tous les signalements d'un joueur",
handler: async (message, args) => {
const username = args.join(" ");
if (!username) {
await replyError(message, "Usage: `lbf reports <pseudo>`");
return;
}
const player = await searchPlayer(username);
if (!player) {
await replyError(message, `Aucun joueur avec le pseudo **${username}** n'a été trouvé.`);
return;
}
const reports = await db
.select()
.from(tables.reports)
.where(eq(tables.reports.playerId, player.id))
.orderBy(tables.reports.createdAt);
if (reports.length === 0) {
await message.reply({ ...noMention, content: `Aucun signalement trouvé pour **${username}**.` });
return;
}
const lines = reports.map((r, i) => {
const date = r.createdAt.toLocaleDateString("fr-FR");
const reason = r.reason.length > 100 ? `${r.reason.slice(0, 100)}` : r.reason;
const link = r.messageLink ? ` - [voir](${r.messageLink})` : "";
return `**${i + 1}.** ${date} - \`${reason}\`${link}`;
});
await message.reply({
...noMention,
embeds: [
new EmbedBuilder()
.setTitle(`Signalements de ${username}`)
.setDescription(lines.join("\n"))
.setFooter({ text: `${reports.length} signalement${reports.length > 1 ? "s" : ""}` }),
],
});
},
};

View File

@@ -0,0 +1,9 @@
import { noMention } from "~/discord";
import type { Command } from "./index";
export const tgCommand: Command = {
help: "...",
handler: async (message) => {
await message.reply({ ...noMention, content: "non toi tg" });
},
};

View File

@@ -13,8 +13,8 @@ export const env = parseEnv({
// TODO: rename to reward ask channel or smth // TODO: rename to reward ask channel or smth
DISCORD_ADMIN_CHANNEL: z.string(), DISCORD_ADMIN_CHANNEL: z.string(),
DISCORD_TRACKING_CHANNEL: z.string(), DISCORD_TRACKING_CHANNEL: z.string(),
DISCORD_REPORT_CHANNEL: z.string(),
DISCORD_STAFF_ROLE_ID: z.string(), DISCORD_STAFF_ROLE_ID: z.string(),
COMMIT_SHA: z.string().default("dev"),
WOV_API_KEY: z.string(), WOV_API_KEY: z.string(),
WOV_CLAN_ID: z.string(), WOV_CLAN_ID: z.string(),
WOV_FETCH_INTERVAL: z.coerce.number(), WOV_FETCH_INTERVAL: z.coerce.number(),

View File

@@ -1,9 +1,10 @@
import type { Client, OmitPartialGroupDMChannel, Message } from "discord.js"; import type { Client, Interaction, OmitPartialGroupDMChannel, Message } from "discord.js";
import { logger } from "@lbf-bot/utils"; import { logger } from "@lbf-bot/utils";
import { env } from "~/env"; import { env } from "~/env";
import { questCheckCron } from "~/quests"; import { questCheckCron } from "~/quests";
import { trackingCron } from "~/tracking"; import { trackingCron } from "~/tracking";
import { commands } from "~/commands"; import { commands } from "~/commands";
import { handleReportButton, handleReportModal, handleEditButton, handleDeleteButton, handleEditModal, REPORT_BUTTON_ID, REPORT_MODAL_ID, REPORT_EDIT_BUTTON_PREFIX, REPORT_DELETE_BUTTON_PREFIX, REPORT_EDIT_MODAL_PREFIX } from "~/reporting";
const onReady = async (client: Client<true>) => { const onReady = async (client: Client<true>) => {
logger.info(`Client ready`); logger.info(`Client ready`);
@@ -37,7 +38,30 @@ const onMessage = async (message: OmitPartialGroupDMChannel<Message>) => {
} }
}; };
const onInteraction = async (interaction: Interaction, client: Client) => {
if (interaction.isButton()) {
if (interaction.customId === REPORT_BUTTON_ID) {
await handleReportButton(interaction);
} else if (interaction.customId.startsWith(`${REPORT_EDIT_BUTTON_PREFIX}:`)) {
const reportId = interaction.customId.slice(REPORT_EDIT_BUTTON_PREFIX.length + 1);
await handleEditButton(interaction, reportId);
} else if (interaction.customId.startsWith(`${REPORT_DELETE_BUTTON_PREFIX}:`)) {
const reportId = interaction.customId.slice(REPORT_DELETE_BUTTON_PREFIX.length + 1);
await handleDeleteButton(interaction, reportId);
}
} else if (interaction.isModalSubmit()) {
if (interaction.customId === REPORT_MODAL_ID) {
await handleReportModal(interaction, client);
} else if (interaction.customId.startsWith(`${REPORT_EDIT_MODAL_PREFIX}:`)) {
const rest = interaction.customId.slice(REPORT_EDIT_MODAL_PREFIX.length + 1);
const [reportId, channelId, messageId] = rest.split(":");
await handleEditModal(interaction, client, reportId, channelId, messageId);
}
}
};
export const setupBotMode = (client: Client) => { export const setupBotMode = (client: Client) => {
client.on("clientReady", (client) => { void onReady(client); }); client.on("clientReady", (client) => { void onReady(client); });
client.on("messageCreate", (message) => { void onMessage(message); }); client.on("messageCreate", (message) => { void onMessage(message); });
client.on("interactionCreate", (interaction) => { void onInteraction(interaction, client); });
}; };

View File

@@ -32,7 +32,7 @@ export const makeResultEmbed = async (result: QuestResult, exclude: Array<string
rewardsEmbed = new EmbedBuilder() rewardsEmbed = new EmbedBuilder()
.setTitle("Récompenses") .setTitle("Récompenses")
.setDescription(`${rewards.join("\n")}\n\n-# \`lbf gemmes\` pour voir votre nombre de gemmes. Puis avec ${env.DISCORD_REWARDS_GIVER} pour échanger contre des cadeaux !`) .setDescription(rewards.join("\n"))
.setColor(color); .setColor(color);
} }

View File

@@ -0,0 +1,299 @@
import {
ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, ComponentType,
EmbedBuilder, FileUploadBuilder, LabelBuilder, MessageFlags, ModalBuilder, TextInputBuilder, TextInputStyle,
type ButtonInteraction, type Client, type FileUploadModalData, type ModalSubmitInteraction, type TextChannel,
} from "discord.js";
import { createLogger } from "@lbf-bot/utils";
import { db, tables, eq } from "@lbf-bot/database";
import { env } from "~/env";
import { searchPlayer } from "~/wov";
const logger = createLogger({ prefix: "reporting" });
export const REPORT_BUTTON_ID = "report:open";
export const REPORT_MODAL_ID = "report:modal";
export const REPORT_EDIT_BUTTON_PREFIX = "report:edit";
export const REPORT_DELETE_BUTTON_PREFIX = "report:delete";
export const REPORT_EDIT_MODAL_PREFIX = "report:edit:modal";
const formatDate = (date: Date): string => {
const d = String(date.getDate()).padStart(2, "0");
const m = String(date.getMonth() + 1).padStart(2, "0");
return `${d}/${m}/${date.getFullYear()}`;
};
const buildReportEmbed = (report: { playerName: string; playerId: string; reason: string; reporterId: string; createdAt: Date }) =>
new EmbedBuilder()
.setDescription([
`**Pseudo**: \`${report.playerName}\``,
`**ID**: \`${report.playerId}\``,
`**Date**: \`${formatDate(report.createdAt)}\``,
`**Raison**: \`\`\`${report.reason}\`\`\``,
`-# Signalé par <@${report.reporterId}>`
].join("\n"));
const reportActionRow = (reportId: string) =>
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId(`${REPORT_EDIT_BUTTON_PREFIX}:${reportId}`)
.setLabel("Modifier")
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId(`${REPORT_DELETE_BUTTON_PREFIX}:${reportId}`)
.setLabel("Supprimer")
.setStyle(ButtonStyle.Danger),
);
const isAuthorized = (interaction: ButtonInteraction | ModalSubmitInteraction, reporterId: string) => {
if (interaction.user.id === reporterId) return true;
const { member } = interaction;
if (!member) return false;
const roles = member.roles;
if (Array.isArray(roles)) return roles.includes(env.DISCORD_STAFF_ROLE_ID);
return "cache" in roles && roles.cache.has(env.DISCORD_STAFF_ROLE_ID);
};
const extractScreenshots = (fields: ModalSubmitInteraction["fields"]) => {
const fileField = fields.fields.get("screenshots") as FileUploadModalData | undefined;
const attachments = fileField?.type === ComponentType.FileUpload && fileField.attachments?.size > 0
? [...fileField.attachments.values()]
: null;
const screenshotUrls = attachments ? attachments.map(a => a.url).join("\n") : null;
return { attachments, screenshotUrls };
};
const buildModal = () =>
new ModalBuilder()
.setCustomId(REPORT_MODAL_ID)
.setTitle("Signaler un joueur")
.addLabelComponents(
new LabelBuilder()
.setLabel("Pseudo du joueur (les majuscules comptent !)")
.setTextInputComponent(
new TextInputBuilder()
.setCustomId("player_name")
.setStyle(TextInputStyle.Short)
.setRequired(true),
),
new LabelBuilder()
.setLabel("Raison du signalement")
.setTextInputComponent(
new TextInputBuilder()
.setCustomId("reason")
.setStyle(TextInputStyle.Paragraph)
.setRequired(true),
),
new LabelBuilder()
.setLabel("Screenshots (optionnel)")
.setFileUploadComponent(
new FileUploadBuilder()
.setCustomId("screenshots")
.setMaxValues(10)
.setRequired(false),
),
);
const buildEditModal = (reportId: string, channelId: string, messageId: string, currentReason: string) =>
new ModalBuilder()
.setCustomId(`${REPORT_EDIT_MODAL_PREFIX}:${reportId}:${channelId}:${messageId}`)
.setTitle("Modifier le signalement")
.addLabelComponents(
new LabelBuilder()
.setLabel("Raison du signalement")
.setTextInputComponent(
new TextInputBuilder()
.setCustomId("reason")
.setStyle(TextInputStyle.Paragraph)
.setValue(currentReason)
.setRequired(true),
),
new LabelBuilder()
.setLabel("Screenshots (optionnel)")
.setFileUploadComponent(
new FileUploadBuilder()
.setCustomId("screenshots")
.setMaxValues(10)
.setRequired(false),
),
);
const retryRow = () =>
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId(REPORT_BUTTON_ID)
.setLabel("Réessayer")
.setStyle(ButtonStyle.Danger),
);
export const sendReportEmbed = async (channel: TextChannel) => {
await channel.send({
embeds: [
new EmbedBuilder()
.setTitle("🚨 Signaler un joueur")
.setDescription([
"Tu as observé un comportement toxique ou de l'anti jeu ?",
"",
"Clique sur le bouton ci-dessous pour signaler un joueur.",
"Pense à fournir le plus de détails dans 'raison', tu peux aussi ajouter des screenshots.",
"",
`-# Les signalements sont envoyés dans <#${env.DISCORD_REPORT_CHANNEL}>.`,
].join("\n"))
.setColor(0xe74c3c),
],
components: [
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId(REPORT_BUTTON_ID)
.setLabel("Signaler un joueur")
.setStyle(ButtonStyle.Danger),
),
],
});
};
export const handleReportButton = async (interaction: ButtonInteraction) => {
await interaction.showModal(buildModal());
};
export const handleReportModal = async (interaction: ModalSubmitInteraction, client: Client) => {
const playerName = interaction.fields.getTextInputValue("player_name");
const reason = interaction.fields.getTextInputValue("reason");
const { attachments, screenshotUrls } = extractScreenshots(interaction.fields);
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
const player = await searchPlayer(playerName);
if (!player) {
await interaction.editReply({
content: `Aucun joueur avec le pseudo **${playerName}** n'a été trouvé. Vérifie les majuscules et réessaie.`,
components: [retryRow()],
});
return;
}
const [inserted] = await db
.insert(tables.reports)
.values({
reporterId: interaction.user.id,
playerName,
playerId: player.id,
reason,
screenshots: screenshotUrls,
})
.returning({ id: tables.reports.id });
let messageLink = "";
const reportChannel = await client.channels.fetch(env.DISCORD_REPORT_CHANNEL);
if (reportChannel?.type === ChannelType.GuildText) {
const reportMessage = await reportChannel.send({
content: "─────────────────────────────────",
embeds: [buildReportEmbed({ playerName, playerId: player.id, reason, reporterId: interaction.user.id, createdAt: new Date() })],
components: [reportActionRow(inserted.id)],
});
messageLink = `https://discord.com/channels/${reportChannel.guild.id}/${reportChannel.id}/${reportMessage.id}`;
const screenshotsMessage = attachments
? await reportChannel.send({ files: attachments.map(a => a.url) })
: await reportChannel.send({ content: "-# Pas de screenshots" });
await db.update(tables.reports)
.set({ messageLink, screenshotsMessageId: screenshotsMessage.id })
.where(eq(tables.reports.id, inserted.id));
} else {
logger.error("Invalid 'DISCORD_REPORT_CHANNEL'");
}
await interaction.editReply({
content: `Le joueur **${playerName}** a bien été signalé. Merci !${messageLink ? ` ${messageLink}` : ""}`,
});
};
export const handleEditButton = async (interaction: ButtonInteraction, reportId: string) => {
const [report] = await db.select().from(tables.reports).where(eq(tables.reports.id, reportId));
if (!report) {
await interaction.reply({ content: "Signalement introuvable.", flags: MessageFlags.Ephemeral });
return;
}
if (!isAuthorized(interaction, report.reporterId)) {
await interaction.reply({ content: "Tu n'as pas la permission de modifier ce signalement.", flags: MessageFlags.Ephemeral });
return;
}
await interaction.showModal(buildEditModal(reportId, interaction.channelId, interaction.message.id, report.reason));
};
export const handleDeleteButton = async (interaction: ButtonInteraction, reportId: string) => {
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
const [report] = await db.select().from(tables.reports).where(eq(tables.reports.id, reportId));
if (!report) {
await interaction.editReply({ content: "Signalement introuvable." });
return;
}
if (!isAuthorized(interaction, report.reporterId)) {
await interaction.editReply({ content: "Tu n'as pas la permission de supprimer ce signalement." });
return;
}
await db.delete(tables.reports).where(eq(tables.reports.id, reportId));
if (report.screenshotsMessageId) {
try {
const screenshotsMsg = await interaction.message.channel.messages.fetch(report.screenshotsMessageId);
await screenshotsMsg.delete();
} catch {
// already deleted or not found
}
}
await interaction.message.delete();
await interaction.editReply({ content: "Signalement supprimé." });
};
export const handleEditModal = async (interaction: ModalSubmitInteraction, client: Client, reportId: string, channelId: string, messageId: string) => {
const reason = interaction.fields.getTextInputValue("reason");
const { attachments, screenshotUrls } = extractScreenshots(interaction.fields);
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
const [report] = await db.select().from(tables.reports).where(eq(tables.reports.id, reportId));
if (!report) {
await interaction.editReply({ content: "Signalement introuvable." });
return;
}
if (!isAuthorized(interaction, report.reporterId)) {
await interaction.editReply({ content: "Tu n'as pas la permission de modifier ce signalement." });
return;
}
const channel = await client.channels.fetch(channelId);
if (channel?.type === ChannelType.GuildText) {
try {
const message = await channel.messages.fetch(messageId);
await message.edit({
embeds: [buildReportEmbed({ ...report, reason })],
components: [reportActionRow(reportId)],
});
} catch {
logger.error("Failed to fetch/edit report message");
}
if (report.screenshotsMessageId) {
try {
const screenshotsMsg = await channel.messages.fetch(report.screenshotsMessageId);
if (attachments) {
await screenshotsMsg.edit({ content: "", files: attachments.map(a => a.url), attachments: [] });
} else {
await screenshotsMsg.edit({ content: "-# Pas de screenshots", attachments: [] });
}
} catch {
logger.error("Failed to edit screenshots message");
}
}
}
await db.update(tables.reports)
.set({ reason, screenshots: screenshotUrls })
.where(eq(tables.reports.id, reportId));
await interaction.editReply({ content: "Signalement modifié." });
};

View File

@@ -28,7 +28,9 @@ services:
discord-bot: discord-bot:
container_name: lbf-bot container_name: lbf-bot
image: git.pihkaal.me/pihkaal/lbf-bot:latest build:
context: .
dockerfile: apps/discord-bot/Dockerfile
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
postgres: postgres:
@@ -47,6 +49,7 @@ services:
- DISCORD_ADMIN_MENTION - DISCORD_ADMIN_MENTION
- DISCORD_ADMIN_CHANNEL - DISCORD_ADMIN_CHANNEL
- DISCORD_TRACKING_CHANNEL - DISCORD_TRACKING_CHANNEL
- DISCORD_REPORT_CHANNEL
- DISCORD_STAFF_ROLE_ID - DISCORD_STAFF_ROLE_ID
- WOV_API_KEY - WOV_API_KEY
- WOV_CLAN_ID - WOV_CLAN_ID

View File

@@ -2,7 +2,7 @@
"name": "lbf-bot", "name": "lbf-bot",
"packageManager": "pnpm@10.24.0", "packageManager": "pnpm@10.24.0",
"scripts": { "scripts": {
"check": "pnpm -r check" "check": "pnpm --filter @lbf-bot/utils run build && pnpm --filter @lbf-bot/database run build && pnpm -r check"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^10.3.0", "eslint": "^10.3.0",

View File

@@ -0,0 +1,10 @@
CREATE TABLE "reports" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"reporter_id" text NOT NULL,
"reporter_username" text NOT NULL,
"player_name" text NOT NULL,
"player_id" text NOT NULL,
"reason" text NOT NULL,
"screenshots" text,
"created_at" timestamp DEFAULT now() NOT NULL
);

View File

@@ -0,0 +1 @@
ALTER TABLE "reports" ADD COLUMN "message_link" text;

View File

@@ -0,0 +1 @@
ALTER TABLE "reports" ADD COLUMN "screenshots_message_id" text;

View File

@@ -0,0 +1 @@
ALTER TABLE "reports" DROP COLUMN "reporter_username";

View File

@@ -0,0 +1,208 @@
{
"id": "4e4b7960-a3a0-4ee7-8bec-4f9379eae836",
"prevId": "80475ee2-c581-462e-8075-13b1ae696df5",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.accounts": {
"name": "accounts",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"balance": {
"name": "balance",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.reports": {
"name": "reports",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"reporter_id": {
"name": "reporter_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"reporter_username": {
"name": "reporter_username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_name": {
"name": "player_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_id": {
"name": "player_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"reason": {
"name": "reason",
"type": "text",
"primaryKey": false,
"notNull": true
},
"screenshots": {
"name": "screenshots",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tracked_players": {
"name": "tracked_players",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.username_history": {
"name": "username_history",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"first_seen_at": {
"name": "first_seen_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"username_history_player_id_tracked_players_player_id_fk": {
"name": "username_history_player_id_tracked_players_player_id_fk",
"tableFrom": "username_history",
"tableTo": "tracked_players",
"columnsFrom": [
"player_id"
],
"columnsTo": [
"player_id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,214 @@
{
"id": "4643e6bd-db18-44c9-893d-8f57a94e8c0a",
"prevId": "4e4b7960-a3a0-4ee7-8bec-4f9379eae836",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.accounts": {
"name": "accounts",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"balance": {
"name": "balance",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.reports": {
"name": "reports",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"reporter_id": {
"name": "reporter_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"reporter_username": {
"name": "reporter_username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_name": {
"name": "player_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_id": {
"name": "player_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"reason": {
"name": "reason",
"type": "text",
"primaryKey": false,
"notNull": true
},
"screenshots": {
"name": "screenshots",
"type": "text",
"primaryKey": false,
"notNull": false
},
"message_link": {
"name": "message_link",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tracked_players": {
"name": "tracked_players",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.username_history": {
"name": "username_history",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"first_seen_at": {
"name": "first_seen_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"username_history_player_id_tracked_players_player_id_fk": {
"name": "username_history_player_id_tracked_players_player_id_fk",
"tableFrom": "username_history",
"tableTo": "tracked_players",
"columnsFrom": [
"player_id"
],
"columnsTo": [
"player_id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,220 @@
{
"id": "a19383ff-8e7a-4da4-8c29-888e8ea9f670",
"prevId": "4643e6bd-db18-44c9-893d-8f57a94e8c0a",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.accounts": {
"name": "accounts",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"balance": {
"name": "balance",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.reports": {
"name": "reports",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"reporter_id": {
"name": "reporter_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"reporter_username": {
"name": "reporter_username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_name": {
"name": "player_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_id": {
"name": "player_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"reason": {
"name": "reason",
"type": "text",
"primaryKey": false,
"notNull": true
},
"screenshots": {
"name": "screenshots",
"type": "text",
"primaryKey": false,
"notNull": false
},
"message_link": {
"name": "message_link",
"type": "text",
"primaryKey": false,
"notNull": false
},
"screenshots_message_id": {
"name": "screenshots_message_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tracked_players": {
"name": "tracked_players",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.username_history": {
"name": "username_history",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"first_seen_at": {
"name": "first_seen_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"username_history_player_id_tracked_players_player_id_fk": {
"name": "username_history_player_id_tracked_players_player_id_fk",
"tableFrom": "username_history",
"tableTo": "tracked_players",
"columnsFrom": [
"player_id"
],
"columnsTo": [
"player_id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,214 @@
{
"id": "11a9aa46-c570-4372-aa71-c5a576a930f4",
"prevId": "a19383ff-8e7a-4da4-8c29-888e8ea9f670",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.accounts": {
"name": "accounts",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"balance": {
"name": "balance",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.reports": {
"name": "reports",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"reporter_id": {
"name": "reporter_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_name": {
"name": "player_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"player_id": {
"name": "player_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"reason": {
"name": "reason",
"type": "text",
"primaryKey": false,
"notNull": true
},
"screenshots": {
"name": "screenshots",
"type": "text",
"primaryKey": false,
"notNull": false
},
"message_link": {
"name": "message_link",
"type": "text",
"primaryKey": false,
"notNull": false
},
"screenshots_message_id": {
"name": "screenshots_message_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tracked_players": {
"name": "tracked_players",
"schema": "",
"columns": {
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.username_history": {
"name": "username_history",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"player_id": {
"name": "player_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"first_seen_at": {
"name": "first_seen_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"username_history_player_id_tracked_players_player_id_fk": {
"name": "username_history_player_id_tracked_players_player_id_fk",
"tableFrom": "username_history",
"tableTo": "tracked_players",
"columnsFrom": [
"player_id"
],
"columnsTo": [
"player_id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -8,6 +8,34 @@
"when": 1764882945878, "when": 1764882945878,
"tag": "0000_tan_justin_hammer", "tag": "0000_tan_justin_hammer",
"breakpoints": true "breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1778601650406,
"tag": "0001_broken_dorian_gray",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1778605638295,
"tag": "0002_lucky_praxagora",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1778607030657,
"tag": "0003_uneven_mephistopheles",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1780166865311,
"tag": "0004_curved_imperial_guard",
"breakpoints": true
} }
] ]
} }

View File

@@ -1,5 +1,20 @@
import { integer, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"; import { integer, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
/**
* REPORTING SYSTEM
*/
export const reports = pgTable("reports", {
id: uuid("id").primaryKey().defaultRandom(),
reporterId: text("reporter_id").notNull(),
playerName: text("player_name").notNull(),
playerId: text("player_id").notNull(),
reason: text("reason").notNull(),
screenshots: text("screenshots"),
messageLink: text("message_link"),
screenshotsMessageId: text("screenshots_message_id"),
createdAt: timestamp("created_at").notNull().defaultNow(),
});
/** /**
* ECONOMY SYSTEM * ECONOMY SYSTEM
*/ */

367
pnpm-lock.yaml generated
View File

@@ -24,8 +24,11 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../../packages/utils version: link:../../packages/utils
discord.js: discord.js:
specifier: ^14.21.0 specifier: ^14.26.4
version: 14.25.1 version: 14.26.4
sharp:
specifier: ^0.34.5
version: 0.34.5
zod: zod:
specifier: 4.1.11 specifier: 4.1.11
version: 4.1.11 version: 4.1.11
@@ -92,8 +95,8 @@ importers:
packages: packages:
'@discordjs/builders@1.13.1': '@discordjs/builders@1.14.1':
resolution: {integrity: sha512-cOU0UDHc3lp/5nKByDxkmRiNZBpdp0kx55aarbiAfakfKJHlxv/yFW1zmIqCAmwH5CRlrH9iMFKJMpvW4DPB+w==} resolution: {integrity: sha512-gSKkhXLqs96TCzk66VZuHHl8z2bQMJFGwrXC0f33ngK+FLNau4hU1PYny3DNJfNdSH+gVMzE85/d5FQ2BpcNwQ==}
engines: {node: '>=16.11.0'} engines: {node: '>=16.11.0'}
'@discordjs/collection@1.5.3': '@discordjs/collection@1.5.3':
@@ -108,8 +111,8 @@ packages:
resolution: {integrity: sha512-y4UPwWhH6vChKRkGdMB4odasUbHOUwy7KL+OVwF86PvT6QVOwElx+TiI1/6kcmcEe+g5YRXJFiXSXUdabqZOvQ==} resolution: {integrity: sha512-y4UPwWhH6vChKRkGdMB4odasUbHOUwy7KL+OVwF86PvT6QVOwElx+TiI1/6kcmcEe+g5YRXJFiXSXUdabqZOvQ==}
engines: {node: '>=16.11.0'} engines: {node: '>=16.11.0'}
'@discordjs/rest@2.6.0': '@discordjs/rest@2.6.1':
resolution: {integrity: sha512-RDYrhmpB7mTvmCKcpj+pc5k7POKszS4E2O9TYc+U+Y4iaCP+r910QdO43qmpOja8LRr1RJ0b3U+CqVsnPqzf4w==} resolution: {integrity: sha512-wwQdgjeaoYFiaG+atbqx6aJDpqW7JHAo0HrQkBTbYzM3/PJ3GweQIpgElNcGZ26DCUOXMyawYd0YF7vtr+fZXg==}
engines: {node: '>=18'} engines: {node: '>=18'}
'@discordjs/util@1.2.0': '@discordjs/util@1.2.0':
@@ -123,6 +126,9 @@ packages:
'@drizzle-team/brocli@0.10.2': '@drizzle-team/brocli@0.10.2':
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
'@emnapi/runtime@1.10.0':
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
'@esbuild-kit/core-utils@3.3.2': '@esbuild-kit/core-utils@3.3.2':
resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
deprecated: 'Merged into tsx: https://tsx.is' deprecated: 'Merged into tsx: https://tsx.is'
@@ -625,6 +631,143 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'} engines: {node: '>=18.18'}
'@img/colour@1.1.0':
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'}
'@img/sharp-darwin-arm64@0.34.5':
resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [darwin]
'@img/sharp-darwin-x64@0.34.5':
resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [darwin]
'@img/sharp-libvips-darwin-arm64@1.2.4':
resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
cpu: [arm64]
os: [darwin]
'@img/sharp-libvips-darwin-x64@1.2.4':
resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
cpu: [x64]
os: [darwin]
'@img/sharp-libvips-linux-arm64@1.2.4':
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
'@img/sharp-libvips-linux-arm@1.2.4':
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
os: [linux]
'@img/sharp-libvips-linux-ppc64@1.2.4':
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
cpu: [ppc64]
os: [linux]
'@img/sharp-libvips-linux-riscv64@1.2.4':
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
cpu: [riscv64]
os: [linux]
'@img/sharp-libvips-linux-s390x@1.2.4':
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
cpu: [s390x]
os: [linux]
'@img/sharp-libvips-linux-x64@1.2.4':
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
os: [linux]
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
os: [linux]
'@img/sharp-linux-arm64@0.34.5':
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
'@img/sharp-linux-arm@0.34.5':
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
'@img/sharp-linux-ppc64@0.34.5':
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ppc64]
os: [linux]
'@img/sharp-linux-riscv64@0.34.5':
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [riscv64]
os: [linux]
'@img/sharp-linux-s390x@0.34.5':
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
'@img/sharp-linux-x64@0.34.5':
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
'@img/sharp-linuxmusl-arm64@0.34.5':
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
'@img/sharp-linuxmusl-x64@0.34.5':
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
'@img/sharp-wasm32@0.34.5':
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [wasm32]
'@img/sharp-win32-arm64@0.34.5':
resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [win32]
'@img/sharp-win32-ia32@0.34.5':
resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ia32]
os: [win32]
'@img/sharp-win32-x64@0.34.5':
resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [win32]
'@ioredis/commands@1.4.0': '@ioredis/commands@1.4.0':
resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==} resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==}
@@ -652,6 +795,10 @@ packages:
resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==} resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'} engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
'@sapphire/snowflake@3.5.5':
resolution: {integrity: sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
'@types/esrecurse@4.3.1': '@types/esrecurse@4.3.1':
resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
@@ -802,15 +949,19 @@ packages:
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
dir-glob@3.0.1: dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'} engines: {node: '>=8'}
discord-api-types@0.38.36: discord-api-types@0.38.47:
resolution: {integrity: sha512-qrbUbjjwtyeBg5HsAlm1C859epfOyiLjPqAOzkdWlCNsZCWJrertnETF/NwM8H+waMFU58xGSc5eXUfXah+WTQ==} resolution: {integrity: sha512-XgXQodHQBAE6kfD7kMvVo30863iHX1LHSqNq6MGUTDwIFCCvHva13+rwxyxVXDqudyApMNAd32PGjgVETi5rjA==}
discord.js@14.25.1: discord.js@14.26.4:
resolution: {integrity: sha512-2l0gsPOLPs5t6GFZfQZKnL1OJNYFcuC/ETWsW4VtKVD/tg4ICa9x+jb9bkPffkMdRpRpuUaO/fKkHCBeiCKh8g==} resolution: {integrity: sha512-4oBp8tc6Kf8IDBwAHhbsMaAqx1b5fob9SNasZT7V6yyyUydoO5i5fGuX7TmvRtR+q/WgKRnRViRoAWnG7fNyvA==}
engines: {node: '>=18'} engines: {node: '>=18'}
dotenv@17.2.3: dotenv@17.2.3:
@@ -1107,11 +1258,11 @@ packages:
lodash.snakecase@4.1.1: lodash.snakecase@4.1.1:
resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
lodash@4.17.21: lodash@4.18.1:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
magic-bytes.js@1.12.1: magic-bytes.js@1.13.0:
resolution: {integrity: sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==} resolution: {integrity: sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg==}
merge2@1.4.1: merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
@@ -1271,6 +1422,10 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
sharp@0.34.5:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
shebang-command@2.0.0: shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -1346,8 +1501,8 @@ packages:
undici-types@6.21.0: undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
undici@6.21.3: undici@6.24.1:
resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} resolution: {integrity: sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==}
engines: {node: '>=18.17'} engines: {node: '>=18.17'}
uri-js@4.4.1: uri-js@4.4.1:
@@ -1387,12 +1542,12 @@ packages:
snapshots: snapshots:
'@discordjs/builders@1.13.1': '@discordjs/builders@1.14.1':
dependencies: dependencies:
'@discordjs/formatters': 0.6.2 '@discordjs/formatters': 0.6.2
'@discordjs/util': 1.2.0 '@discordjs/util': 1.2.0
'@sapphire/shapeshift': 4.0.0 '@sapphire/shapeshift': 4.0.0
discord-api-types: 0.38.36 discord-api-types: 0.38.47
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
ts-mixer: 6.0.4 ts-mixer: 6.0.4
tslib: 2.8.1 tslib: 2.8.1
@@ -1403,33 +1558,33 @@ snapshots:
'@discordjs/formatters@0.6.2': '@discordjs/formatters@0.6.2':
dependencies: dependencies:
discord-api-types: 0.38.36 discord-api-types: 0.38.47
'@discordjs/rest@2.6.0': '@discordjs/rest@2.6.1':
dependencies: dependencies:
'@discordjs/collection': 2.1.1 '@discordjs/collection': 2.1.1
'@discordjs/util': 1.2.0 '@discordjs/util': 1.2.0
'@sapphire/async-queue': 1.5.5 '@sapphire/async-queue': 1.5.5
'@sapphire/snowflake': 3.5.3 '@sapphire/snowflake': 3.5.5
'@vladfrangu/async_event_emitter': 2.4.7 '@vladfrangu/async_event_emitter': 2.4.7
discord-api-types: 0.38.36 discord-api-types: 0.38.47
magic-bytes.js: 1.12.1 magic-bytes.js: 1.13.0
tslib: 2.8.1 tslib: 2.8.1
undici: 6.21.3 undici: 6.24.1
'@discordjs/util@1.2.0': '@discordjs/util@1.2.0':
dependencies: dependencies:
discord-api-types: 0.38.36 discord-api-types: 0.38.47
'@discordjs/ws@1.2.3': '@discordjs/ws@1.2.3':
dependencies: dependencies:
'@discordjs/collection': 2.1.1 '@discordjs/collection': 2.1.1
'@discordjs/rest': 2.6.0 '@discordjs/rest': 2.6.1
'@discordjs/util': 1.2.0 '@discordjs/util': 1.2.0
'@sapphire/async-queue': 1.5.5 '@sapphire/async-queue': 1.5.5
'@types/ws': 8.18.1 '@types/ws': 8.18.1
'@vladfrangu/async_event_emitter': 2.4.7 '@vladfrangu/async_event_emitter': 2.4.7
discord-api-types: 0.38.36 discord-api-types: 0.38.47
tslib: 2.8.1 tslib: 2.8.1
ws: 8.18.3 ws: 8.18.3
transitivePeerDependencies: transitivePeerDependencies:
@@ -1438,6 +1593,11 @@ snapshots:
'@drizzle-team/brocli@0.10.2': {} '@drizzle-team/brocli@0.10.2': {}
'@emnapi/runtime@1.10.0':
dependencies:
tslib: 2.8.1
optional: true
'@esbuild-kit/core-utils@3.3.2': '@esbuild-kit/core-utils@3.3.2':
dependencies: dependencies:
esbuild: 0.18.20 esbuild: 0.18.20
@@ -1716,6 +1876,102 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {} '@humanwhocodes/retry@0.4.3': {}
'@img/colour@1.1.0': {}
'@img/sharp-darwin-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.2.4
optional: true
'@img/sharp-darwin-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.2.4
optional: true
'@img/sharp-libvips-darwin-arm64@1.2.4':
optional: true
'@img/sharp-libvips-darwin-x64@1.2.4':
optional: true
'@img/sharp-libvips-linux-arm64@1.2.4':
optional: true
'@img/sharp-libvips-linux-arm@1.2.4':
optional: true
'@img/sharp-libvips-linux-ppc64@1.2.4':
optional: true
'@img/sharp-libvips-linux-riscv64@1.2.4':
optional: true
'@img/sharp-libvips-linux-s390x@1.2.4':
optional: true
'@img/sharp-libvips-linux-x64@1.2.4':
optional: true
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
optional: true
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
optional: true
'@img/sharp-linux-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.2.4
optional: true
'@img/sharp-linux-arm@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.2.4
optional: true
'@img/sharp-linux-ppc64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-ppc64': 1.2.4
optional: true
'@img/sharp-linux-riscv64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-riscv64': 1.2.4
optional: true
'@img/sharp-linux-s390x@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-s390x': 1.2.4
optional: true
'@img/sharp-linux-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.2.4
optional: true
'@img/sharp-linuxmusl-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
optional: true
'@img/sharp-linuxmusl-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
optional: true
'@img/sharp-wasm32@0.34.5':
dependencies:
'@emnapi/runtime': 1.10.0
optional: true
'@img/sharp-win32-arm64@0.34.5':
optional: true
'@img/sharp-win32-ia32@0.34.5':
optional: true
'@img/sharp-win32-x64@0.34.5':
optional: true
'@ioredis/commands@1.4.0': {} '@ioredis/commands@1.4.0': {}
'@nodelib/fs.scandir@2.1.5': '@nodelib/fs.scandir@2.1.5':
@@ -1735,10 +1991,12 @@ snapshots:
'@sapphire/shapeshift@4.0.0': '@sapphire/shapeshift@4.0.0':
dependencies: dependencies:
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
lodash: 4.17.21 lodash: 4.18.1
'@sapphire/snowflake@3.5.3': {} '@sapphire/snowflake@3.5.3': {}
'@sapphire/snowflake@3.5.5': {}
'@types/esrecurse@4.3.1': {} '@types/esrecurse@4.3.1': {}
'@types/estree@1.0.9': {} '@types/estree@1.0.9': {}
@@ -1910,27 +2168,29 @@ snapshots:
denque@2.1.0: {} denque@2.1.0: {}
detect-libc@2.1.2: {}
dir-glob@3.0.1: dir-glob@3.0.1:
dependencies: dependencies:
path-type: 4.0.0 path-type: 4.0.0
discord-api-types@0.38.36: {} discord-api-types@0.38.47: {}
discord.js@14.25.1: discord.js@14.26.4:
dependencies: dependencies:
'@discordjs/builders': 1.13.1 '@discordjs/builders': 1.14.1
'@discordjs/collection': 1.5.3 '@discordjs/collection': 1.5.3
'@discordjs/formatters': 0.6.2 '@discordjs/formatters': 0.6.2
'@discordjs/rest': 2.6.0 '@discordjs/rest': 2.6.1
'@discordjs/util': 1.2.0 '@discordjs/util': 1.2.0
'@discordjs/ws': 1.2.3 '@discordjs/ws': 1.2.3
'@sapphire/snowflake': 3.5.3 '@sapphire/snowflake': 3.5.3
discord-api-types: 0.38.36 discord-api-types: 0.38.47
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
lodash.snakecase: 4.1.1 lodash.snakecase: 4.1.1
magic-bytes.js: 1.12.1 magic-bytes.js: 1.13.0
tslib: 2.8.1 tslib: 2.8.1
undici: 6.21.3 undici: 6.24.1
transitivePeerDependencies: transitivePeerDependencies:
- bufferutil - bufferutil
- utf-8-validate - utf-8-validate
@@ -2232,9 +2492,9 @@ snapshots:
lodash.snakecase@4.1.1: {} lodash.snakecase@4.1.1: {}
lodash@4.17.21: {} lodash@4.18.1: {}
magic-bytes.js@1.12.1: {} magic-bytes.js@1.13.0: {}
merge2@1.4.1: {} merge2@1.4.1: {}
@@ -2362,6 +2622,37 @@ snapshots:
semver@7.8.0: {} semver@7.8.0: {}
sharp@0.34.5:
dependencies:
'@img/colour': 1.1.0
detect-libc: 2.1.2
semver: 7.8.0
optionalDependencies:
'@img/sharp-darwin-arm64': 0.34.5
'@img/sharp-darwin-x64': 0.34.5
'@img/sharp-libvips-darwin-arm64': 1.2.4
'@img/sharp-libvips-darwin-x64': 1.2.4
'@img/sharp-libvips-linux-arm': 1.2.4
'@img/sharp-libvips-linux-arm64': 1.2.4
'@img/sharp-libvips-linux-ppc64': 1.2.4
'@img/sharp-libvips-linux-riscv64': 1.2.4
'@img/sharp-libvips-linux-s390x': 1.2.4
'@img/sharp-libvips-linux-x64': 1.2.4
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
'@img/sharp-linux-arm': 0.34.5
'@img/sharp-linux-arm64': 0.34.5
'@img/sharp-linux-ppc64': 0.34.5
'@img/sharp-linux-riscv64': 0.34.5
'@img/sharp-linux-s390x': 0.34.5
'@img/sharp-linux-x64': 0.34.5
'@img/sharp-linuxmusl-arm64': 0.34.5
'@img/sharp-linuxmusl-x64': 0.34.5
'@img/sharp-wasm32': 0.34.5
'@img/sharp-win32-arm64': 0.34.5
'@img/sharp-win32-ia32': 0.34.5
'@img/sharp-win32-x64': 0.34.5
shebang-command@2.0.0: shebang-command@2.0.0:
dependencies: dependencies:
shebang-regex: 3.0.0 shebang-regex: 3.0.0
@@ -2434,7 +2725,7 @@ snapshots:
undici-types@6.21.0: {} undici-types@6.21.0: {}
undici@6.21.3: {} undici@6.24.1: {}
uri-js@4.4.1: uri-js@4.4.1:
dependencies: dependencies: