refactor(discord-bot): improve project structure
This commit is contained in:
65
apps/discord-bot/src/commands/gemmes.ts
Normal file
65
apps/discord-bot/src/commands/gemmes.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import type { Command } from "~/commands";
|
||||||
|
import { getAccountBalance, setAccountBalance } from "~/services/account";
|
||||||
|
import { getClanMembers } from "~/services/wov";
|
||||||
|
import { createErrorEmbed } from "~/utils/discord";
|
||||||
|
|
||||||
|
const STAFF_ROLE_ID = "1147963065640439900";
|
||||||
|
|
||||||
|
export const gemmesCommand: Command = async (message, args) => {
|
||||||
|
const displayName = message.member?.displayName || message.author.username;
|
||||||
|
let playerName = displayName.replace("🕸 |", "").trim();
|
||||||
|
if (args.length >= 1) {
|
||||||
|
playerName = args[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const clanMembers = await getClanMembers();
|
||||||
|
|
||||||
|
let clanMember = clanMembers.find((x) => x.username === playerName);
|
||||||
|
if (!clanMember) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
`\`${playerName}\` n'est pas dans le clan (la honte).\n**Attention les majuscules sont importantes**`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (args.length === 2 && message.member) {
|
||||||
|
if (!message.member.roles.cache.has(STAFF_ROLE_ID)) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed("Tu t'es cru chez mémé ou quoi faut être staff"),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(args[1][0] !== "+" && args[1][0] !== "-") ||
|
||||||
|
!args[1] ||
|
||||||
|
isNaN(Number(args[1].substring(1)))
|
||||||
|
) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Format: `@LBF gemmes <pseudo> <+GEMMES | -GEMMES>`\nExemple:`@LBF gemmes Yuno -10000`\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mult = args[1][0] === "+" ? 1 : -1;
|
||||||
|
const delta = Number(args[1].substring(1)) * mult;
|
||||||
|
const balance = await getAccountBalance(clanMember.playerId);
|
||||||
|
await setAccountBalance(
|
||||||
|
clanMember.playerId,
|
||||||
|
Math.max(0, balance + delta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const balance = await getAccountBalance(clanMember.playerId);
|
||||||
|
await message.reply({
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
description: `### 💎 Compte de ${playerName}\n\n\nGemmes disponibles: **${balance}**\n\n-# Voir avec <@294871767820795904> pour échanger contre skin/carte etc`,
|
||||||
|
color: 4360641,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
51
apps/discord-bot/src/commands/icone.ts
Normal file
51
apps/discord-bot/src/commands/icone.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import type { Command } from "~/commands";
|
||||||
|
import { searchPlayer, getClanInfos } from "~/services/wov";
|
||||||
|
import { createErrorEmbed } from "~/utils/discord";
|
||||||
|
|
||||||
|
export const iconeCommand: Command = async (message, args) => {
|
||||||
|
let playerName = args[0];
|
||||||
|
if (!playerName) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Usage:`@LBF icone NOM_JOUEUR`, exemple: `@LBF icone Yuno`.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const player = await searchPlayer(playerName);
|
||||||
|
if (!player) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Joueur·euse non trouvé·e.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!player.clanId) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Cette personne __n'a pas de clan__ ou __a caché son clan__.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const clan = await getClanInfos(player.clanId);
|
||||||
|
if (!clan) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed("Impossible de récupérer les informations du clan."),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await message.reply({
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
description: `### ✅ Informations du clan\n\n**Nom:** \`\`\`${clan.name}\`\`\`\n**Tag:** \`\`\`${clan.tag}\`\`\``,
|
||||||
|
color: 65280,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
21
apps/discord-bot/src/commands/index.ts
Normal file
21
apps/discord-bot/src/commands/index.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import type { Message, OmitPartialGroupDMChannel } from "discord.js";
|
||||||
|
import { pingCommand } from "./ping";
|
||||||
|
import { trackCommand } from "./track";
|
||||||
|
import { tejtrackCommand } from "./tejtrack";
|
||||||
|
import { iconeCommand } from "./icone";
|
||||||
|
import { gemmesCommand } from "./gemmes";
|
||||||
|
import { resultCommand } from "./result";
|
||||||
|
|
||||||
|
export type Command = (
|
||||||
|
message: OmitPartialGroupDMChannel<Message<boolean>>,
|
||||||
|
args: Array<string>,
|
||||||
|
) => Promise<void> | void;
|
||||||
|
|
||||||
|
export const commands: Record<string, Command> = {
|
||||||
|
ping: pingCommand,
|
||||||
|
track: trackCommand,
|
||||||
|
tejtrack: tejtrackCommand,
|
||||||
|
icone: iconeCommand,
|
||||||
|
gemmes: gemmesCommand,
|
||||||
|
result: resultCommand,
|
||||||
|
};
|
||||||
5
apps/discord-bot/src/commands/ping.ts
Normal file
5
apps/discord-bot/src/commands/ping.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import type { Command } from "~/commands";
|
||||||
|
|
||||||
|
export const pingCommand: Command = async (message, args) => {
|
||||||
|
await message.reply("pong");
|
||||||
|
};
|
||||||
9
apps/discord-bot/src/commands/result.ts
Normal file
9
apps/discord-bot/src/commands/result.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import type { Command } from "~/commands";
|
||||||
|
import { getLatestQuest } from "~/services/wov";
|
||||||
|
import { askForGrinders } from "~/utils/quest";
|
||||||
|
|
||||||
|
export const resultCommand: Command = async (message, args) => {
|
||||||
|
const client = message.client;
|
||||||
|
const quest = await getLatestQuest();
|
||||||
|
await askForGrinders(quest, client);
|
||||||
|
};
|
||||||
65
apps/discord-bot/src/commands/tejtrack.ts
Normal file
65
apps/discord-bot/src/commands/tejtrack.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import type { Command } from "~/commands";
|
||||||
|
import { untrackWovPlayer } from "~/services/tracking";
|
||||||
|
import { searchPlayer } from "~/services/wov";
|
||||||
|
import { createErrorEmbed, createInfoEmbed } from "~/utils/discord";
|
||||||
|
import { env } from "~/env";
|
||||||
|
|
||||||
|
const STAFF_ROLE_ID = "1147963065640439900";
|
||||||
|
|
||||||
|
export const tejtrackCommand: Command = async (message, args) => {
|
||||||
|
const client = message.client;
|
||||||
|
if (!message.member) return;
|
||||||
|
if (!message.member.roles.cache.has(STAFF_ROLE_ID)) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed("Tu t'es cru chez mémé ou quoi faut être staff"),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let playerName = args[0];
|
||||||
|
if (!playerName) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Usage:`@LBF untrack NOM_JOUEUR`, exemple: `@LBF untrack Yuno`.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const player = await searchPlayer(playerName);
|
||||||
|
if (!player) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Cette personne n'existe pas.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await untrackWovPlayer(player.id);
|
||||||
|
switch (res.event) {
|
||||||
|
case "notTracked": {
|
||||||
|
await message.reply(
|
||||||
|
createInfoEmbed(
|
||||||
|
`Pas de tracker pour \`${playerName}\` [\`${player.id}\`]`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "trackerRemoved": {
|
||||||
|
await message.reply(
|
||||||
|
createInfoEmbed(
|
||||||
|
`Tracker enlevé pour \`${playerName}\` [\`${player.id}\`]`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const chan = client.channels.cache.get(env.DISCORD_TRACKING_CHANNEL);
|
||||||
|
if (!chan?.isSendable()) throw "Invalid tracking channel";
|
||||||
|
|
||||||
|
await chan.send(
|
||||||
|
createInfoEmbed(`### [REMOVED] \`${playerName}\` [\`${player.id}\`]`),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
78
apps/discord-bot/src/commands/track.ts
Normal file
78
apps/discord-bot/src/commands/track.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import type { Command } from "~/commands";
|
||||||
|
import { trackWovPlayer } from "~/services/tracking";
|
||||||
|
import { searchPlayer } from "~/services/wov";
|
||||||
|
import { createErrorEmbed, createInfoEmbed } from "~/utils/discord";
|
||||||
|
import { env } from "~/env";
|
||||||
|
|
||||||
|
const STAFF_ROLE_ID = "1147963065640439900";
|
||||||
|
|
||||||
|
export const trackCommand: Command = async (message, args) => {
|
||||||
|
const client = message.client;
|
||||||
|
if (!message.member) return;
|
||||||
|
if (!message.member.roles.cache.has(STAFF_ROLE_ID)) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed("Tu t'es cru chez mémé ou quoi faut être staff"),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let playerName = args[0];
|
||||||
|
if (!playerName) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Usage:`@LBF track NOM_JOUEUR`, exemple: `@LBF track Yuno`.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const player = await searchPlayer(playerName);
|
||||||
|
if (!player) {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Cette personne n'existe pas.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await trackWovPlayer(player.id);
|
||||||
|
switch (res.event) {
|
||||||
|
case "notFound": {
|
||||||
|
await message.reply(
|
||||||
|
createErrorEmbed(
|
||||||
|
"Cette personne n'existe pas.\n**Attention les majuscules sont importantes**",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "registered": {
|
||||||
|
await message.reply(
|
||||||
|
createInfoEmbed(
|
||||||
|
`Tracker enregistré pour \`${playerName}\` [\`${player.id}\`]`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const chan = client.channels.cache.get(env.DISCORD_TRACKING_CHANNEL);
|
||||||
|
if (!chan?.isSendable()) throw "Invalid tracking channel";
|
||||||
|
|
||||||
|
await chan.send(
|
||||||
|
createInfoEmbed(`### [NEW] \`${playerName}\` [\`${player.id}\`]`),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case "none": {
|
||||||
|
await message.reply(
|
||||||
|
createInfoEmbed(
|
||||||
|
`Tracker déjà enregistré pour \`${playerName}\` [\`${player.id}\`]`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case "changed": {
|
||||||
|
// ignored
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,29 +1,16 @@
|
|||||||
import { getAccountBalance, initAccounts, setAccountBalance } from "./account";
|
import { initAccounts } from "~/services/account";
|
||||||
import { makeResultEmbed } from "./discordUtils";
|
import { env } from "~/env";
|
||||||
import { env } from "./env";
|
|
||||||
import {
|
import {
|
||||||
initTracking,
|
initTracking,
|
||||||
listTrackedPlayers,
|
listTrackedPlayers,
|
||||||
trackWovPlayer,
|
trackWovPlayer,
|
||||||
untrackWovPlayer,
|
} from "~/services/tracking";
|
||||||
} from "./tracking";
|
import { checkForNewQuest } from "~/services/wov";
|
||||||
import {
|
import { createInfoEmbed } from "~/utils/discord";
|
||||||
checkForNewQuest,
|
import { askForGrinders } from "~/utils/quest";
|
||||||
getClanInfos,
|
import { commands } from "~/commands";
|
||||||
getClanMembers,
|
|
||||||
getLatestQuest,
|
|
||||||
searchPlayer,
|
|
||||||
type QuestResult,
|
|
||||||
} from "./wov";
|
|
||||||
|
|
||||||
import {
|
import { ChannelType, Client, GatewayIntentBits, Partials } from "discord.js";
|
||||||
ChannelType,
|
|
||||||
Client,
|
|
||||||
EmbedBuilder,
|
|
||||||
GatewayIntentBits,
|
|
||||||
Message,
|
|
||||||
Partials,
|
|
||||||
} from "discord.js";
|
|
||||||
import * as readline from "node:readline";
|
import * as readline from "node:readline";
|
||||||
|
|
||||||
// user mode = write in console, send in channel
|
// user mode = write in console, send in channel
|
||||||
@@ -53,121 +40,10 @@ const client = new Client({
|
|||||||
partials: [Partials.Message, Partials.Channel],
|
partials: [Partials.Message, Partials.Channel],
|
||||||
});
|
});
|
||||||
|
|
||||||
const askForGrinders = async (quest: QuestResult) => {
|
const questCheckCron = async () => {
|
||||||
const adminChannel = await client.channels.fetch(env.DISCORD_ADMIN_CHANNEL);
|
|
||||||
if (!adminChannel || adminChannel.type !== ChannelType.GuildText)
|
|
||||||
throw "Invalid admin channel provided";
|
|
||||||
|
|
||||||
const top10 = quest.participants
|
|
||||||
.filter((x) => !env.QUEST_EXCLUDE.includes(x.username))
|
|
||||||
.sort((a, b) => b.xp - a.xp)
|
|
||||||
.slice(0, 10)
|
|
||||||
.map((p, i) => `${i + 1}. ${p.username} - ${p.xp}xp`)
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
const color = parseInt(quest.quest.promoImagePrimaryColor.substring(1), 16);
|
|
||||||
|
|
||||||
await adminChannel.send({
|
|
||||||
content: `-# ||${env.DISCORD_ADMIN_MENTION}||`,
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
title: "Quête terminée !",
|
|
||||||
color,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Top 10 XP",
|
|
||||||
description: top10,
|
|
||||||
color,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Qui a grind ?",
|
|
||||||
description:
|
|
||||||
"Merci d'entrer les pseudos des joueurs qui ont grind.\n\nFormat:```@LBF laulau,Yuno,...```\n**Attention les majuscules comptent**\nPour entrer la liste des joueurs, il faut __mentionner le bot__, si personne n'a grind, `@LBF tg`",
|
|
||||||
color,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const filter = (msg: Message) =>
|
|
||||||
msg.channel.id === adminChannel.id &&
|
|
||||||
!msg.author.bot &&
|
|
||||||
msg.content.startsWith(`<@${client.user!.id}>`);
|
|
||||||
|
|
||||||
let confirmed = false;
|
|
||||||
let answer: string | null = null;
|
|
||||||
while (!confirmed) {
|
|
||||||
const collected = await adminChannel.awaitMessages({ filter, max: 1 });
|
|
||||||
answer = collected.first()?.content || null;
|
|
||||||
if (!answer) continue;
|
|
||||||
|
|
||||||
answer = answer.replace(`<@${client.user!.id}>`, "").trim();
|
|
||||||
if (answer.toLowerCase() === "tg") {
|
|
||||||
answer = "";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const players = answer
|
|
||||||
.split(",")
|
|
||||||
.map((x) => x.trim())
|
|
||||||
.filter(Boolean);
|
|
||||||
await adminChannel.send({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
title: "Joueurs entrés",
|
|
||||||
description: players.length
|
|
||||||
? players.map((name) => `- ${name}`).join("\n")
|
|
||||||
: "*Aucun joueur entré*",
|
|
||||||
color,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
content: `Est-ce correct ? (oui/non)`,
|
|
||||||
});
|
|
||||||
const confirmFilter = (msg: Message) =>
|
|
||||||
msg.channel.id === adminChannel.id &&
|
|
||||||
!msg.author.bot &&
|
|
||||||
["oui", "non", "yes", "no"].includes(msg.content.toLowerCase());
|
|
||||||
const confirmCollected = await adminChannel.awaitMessages({
|
|
||||||
filter: confirmFilter,
|
|
||||||
max: 1,
|
|
||||||
});
|
|
||||||
const confirmation = confirmCollected.first()?.content.toLowerCase();
|
|
||||||
if (confirmation === "oui" || confirmation === "yes") {
|
|
||||||
confirmed = true;
|
|
||||||
await adminChannel.send({ content: "Ok" });
|
|
||||||
} else {
|
|
||||||
await adminChannel.send({
|
|
||||||
content: "D'accord, veuillez réessayer. Qui a grind ?",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (answer === null) throw "unreachable";
|
|
||||||
|
|
||||||
const exclude = answer
|
|
||||||
.split(",")
|
|
||||||
.map((x) => x.trim())
|
|
||||||
.filter(Boolean);
|
|
||||||
const embed = await makeResultEmbed(quest, [
|
|
||||||
...env.QUEST_EXCLUDE,
|
|
||||||
...exclude,
|
|
||||||
]);
|
|
||||||
const rewardChannel = await client.channels.fetch(
|
|
||||||
env.DISCORD_REWARDS_CHANNEL,
|
|
||||||
);
|
|
||||||
if (rewardChannel && rewardChannel.type === ChannelType.GuildText) {
|
|
||||||
await rewardChannel.send(embed);
|
|
||||||
} else {
|
|
||||||
throw "Invalid reward channel";
|
|
||||||
}
|
|
||||||
|
|
||||||
await adminChannel.send("Envoyé !");
|
|
||||||
console.log(`Quest result posted at: ${new Date().toISOString()}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fn = async () => {
|
|
||||||
const quest = await checkForNewQuest();
|
const quest = await checkForNewQuest();
|
||||||
if (quest) {
|
if (quest) {
|
||||||
await askForGrinders(quest);
|
await askForGrinders(quest, client);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -182,21 +58,11 @@ const trackingCron = async () => {
|
|||||||
|
|
||||||
const lastUsername = res.oldUsernames[res.oldUsernames.length - 1];
|
const lastUsername = res.oldUsernames[res.oldUsernames.length - 1];
|
||||||
|
|
||||||
await chan.send({
|
await chan.send(
|
||||||
embeds: [
|
createInfoEmbed(
|
||||||
{
|
`### [UPDATE] \`${lastUsername}\` -> \`${res.newUsername}\` [\`${playerId}\`]\n\n**Nouveau pseudo:** \`${res.newUsername}\`\n**Anciens pseudos:**\n${res.oldUsernames.map((x) => `- \`${x}\``).join("\n")}`,
|
||||||
description: `### [UPDATE] \`${lastUsername}\` -> \`${res.newUsername}\` [\`${playerId}\`]`,
|
),
|
||||||
fields: [
|
);
|
||||||
{ name: "Nouveau pseudo", value: `\`${res.newUsername}\`` },
|
|
||||||
{
|
|
||||||
name: "Anciens pseudos",
|
|
||||||
value: res.oldUsernames.map((x) => `- \`${x}\``).join("\n"),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
color: 0x89cff0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -230,8 +96,8 @@ client.on("ready", async (client) => {
|
|||||||
await initAccounts();
|
await initAccounts();
|
||||||
await initTracking();
|
await initTracking();
|
||||||
|
|
||||||
await fn();
|
await questCheckCron();
|
||||||
setInterval(fn, env.WOV_FETCH_INTERVAL);
|
setInterval(questCheckCron, env.WOV_FETCH_INTERVAL);
|
||||||
|
|
||||||
await trackingCron();
|
await trackingCron();
|
||||||
setInterval(trackingCron, env.WOV_TRACKING_INTERVAL);
|
setInterval(trackingCron, env.WOV_TRACKING_INTERVAL);
|
||||||
@@ -241,320 +107,15 @@ client.on("ready", async (client) => {
|
|||||||
client.on("messageCreate", async (message) => {
|
client.on("messageCreate", async (message) => {
|
||||||
if (message.author.bot || userMode.enabled) return;
|
if (message.author.bot || userMode.enabled) return;
|
||||||
|
|
||||||
const displayName = message.member?.displayName || message.author.username;
|
|
||||||
|
|
||||||
if (message.content.startsWith(`<@${client.user!.id}>`)) {
|
if (message.content.startsWith(`<@${client.user!.id}>`)) {
|
||||||
const [command, ...args] = message.content
|
const [command, ...args] = message.content
|
||||||
.replace(`<@${client.user!.id}>`, "")
|
.replace(`<@${client.user!.id}>`, "")
|
||||||
.trim()
|
.trim()
|
||||||
.split(" ");
|
.split(" ");
|
||||||
if (command === "ping") {
|
|
||||||
await message.reply("pong");
|
|
||||||
} else if (command === "tejtrack") {
|
|
||||||
if (!message.member) return;
|
|
||||||
if (!message.member.roles.cache.has("1147963065640439900")) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description:
|
|
||||||
"### ❌ Erreur\n\n\nTu t'es cru chez mémé ou quoi faut être staff",
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let playerName = args[0];
|
const commandHandler = commands[command];
|
||||||
if (!playerName) {
|
if (commandHandler) {
|
||||||
await message.reply({
|
await commandHandler(message, args);
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nUsage:\`@LBF untrack NOM_JOUEUR\`, exemple: \`@LBF untrack Yuno\`.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const player = await searchPlayer(playerName);
|
|
||||||
if (!player) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nCette personne n'existe pas.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await untrackWovPlayer(player.id);
|
|
||||||
switch (res.event) {
|
|
||||||
case "notTracked": {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `Pas de tracker pour \`${playerName}\` [\`${player.id}\`]`,
|
|
||||||
color: 0x89cff0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "trackerRemoved": {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `Tracker enlevé pour \`${playerName}\` [\`${player.id}\`]`,
|
|
||||||
color: 0x89cff0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const chan = client.channels.cache.get(env.DISCORD_TRACKING_CHANNEL);
|
|
||||||
if (!chan?.isSendable()) throw "Invalid tracking channel";
|
|
||||||
|
|
||||||
await chan.send({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### [REMOVED] \`${playerName}\` [\`${player.id}\`]`,
|
|
||||||
color: 0x89cff0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (command === "track") {
|
|
||||||
if (!message.member) return;
|
|
||||||
if (!message.member.roles.cache.has("1147963065640439900")) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description:
|
|
||||||
"### ❌ Erreur\n\n\nTu t'es cru chez mémé ou quoi faut être staff",
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let playerName = args[0];
|
|
||||||
if (!playerName) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nUsage:\`@LBF track NOM_JOUEUR\`, exemple: \`@LBF track Yuno\`.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const player = await searchPlayer(playerName);
|
|
||||||
if (!player) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nCette personne n'existe pas.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await trackWovPlayer(player.id);
|
|
||||||
switch (res.event) {
|
|
||||||
case "notFound": {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nCette personne n'existe pas.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "registered": {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `Tracker enregistré pour \`${playerName}\` [\`${player.id}\`]`,
|
|
||||||
color: 0x89cff0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const chan = client.channels.cache.get(env.DISCORD_TRACKING_CHANNEL);
|
|
||||||
if (!chan?.isSendable()) throw "Invalid tracking channel";
|
|
||||||
|
|
||||||
await chan.send({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### [NEW] \`${playerName}\` [\`${player.id}\`]`,
|
|
||||||
color: 0x89cff0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case "none": {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `Tracker déjà enregistré pour \`${playerName}\` [\`${player.id}\`]`,
|
|
||||||
color: 0x89cff0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case "changed": {
|
|
||||||
// ignored
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (command === "icone") {
|
|
||||||
let playerName = args[0];
|
|
||||||
if (!playerName) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nUsage:\`@LBF icone NOM_JOUEUR\`, exemple: \`@LBF icone Yuno\`.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const player = await searchPlayer(playerName);
|
|
||||||
if (!player) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nJoueur·euse non trouvé·e.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.clanId) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nCette personne __n'a pas de clan__ ou __a caché son clan__.\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const clan = await getClanInfos(player.clanId);
|
|
||||||
if (!clan) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\nImpossible de récupérer les informations du clan.`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ✅ Informations du clan\n\n**Nom:** \`\`\`${clan.name}\`\`\`\n**Tag:** \`\`\`${clan.tag}\`\`\``,
|
|
||||||
color: 65280,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
} else if (command === "result") {
|
|
||||||
const quest = await getLatestQuest();
|
|
||||||
await askForGrinders(quest);
|
|
||||||
} else if (command === "gemmes") {
|
|
||||||
let playerName = displayName.replace("🕸 |", "").trim();
|
|
||||||
if (args.length >= 1) {
|
|
||||||
playerName = args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const clanMembers = await getClanMembers();
|
|
||||||
|
|
||||||
let clanMember = clanMembers.find((x) => x.username === playerName);
|
|
||||||
if (!clanMember) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### ❌ Erreur\n\n\n\`${playerName}\` n'est pas dans le clan (la honte).\n**Attention les majuscules sont importantes**`,
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (args.length === 2 && message.member) {
|
|
||||||
if (!message.member.roles.cache.has("1147963065640439900")) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description:
|
|
||||||
"### ❌ Erreur\n\n\nTu t'es cru chez mémé ou quoi faut être staff",
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
(args[1][0] !== "+" && args[1][0] !== "-") ||
|
|
||||||
!args[1] ||
|
|
||||||
isNaN(Number(args[1].substring(1)))
|
|
||||||
) {
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description:
|
|
||||||
"### ❌ Erreur\n\n\nFormat: \`@LBF gemmes <pseudo> <+GEMMES|-GEMMES>\`\nExemple:\`@LBF gemmes Yuno -10000\`\n**Attention les majuscules sont importantes**",
|
|
||||||
color: 15335424,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mult = args[1][0] === "+" ? 1 : -1;
|
|
||||||
const delta = Number(args[1].substring(1)) * mult;
|
|
||||||
const balance = await getAccountBalance(clanMember.playerId);
|
|
||||||
await setAccountBalance(
|
|
||||||
clanMember.playerId,
|
|
||||||
Math.max(0, balance + delta),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const balance = await getAccountBalance(clanMember.playerId);
|
|
||||||
// await message.reply(`Gemmes accumulées par ${playerName}: ${balance}`);
|
|
||||||
await message.reply({
|
|
||||||
embeds: [
|
|
||||||
{
|
|
||||||
description: `### 💎 Compte de ${playerName}\n\n\nGemmes disponibles: **${balance}**\n\n-# Voir avec <@294871767820795904> pour échanger contre skin/carte etc`,
|
|
||||||
color: 4360641,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { getPlayer } from "./wov";
|
import { getPlayer } from "~/services/wov";
|
||||||
import { readFile, writeFile, access } from "node:fs/promises";
|
import { readFile, writeFile, access } from "node:fs/promises";
|
||||||
import { constants } from "node:fs";
|
import { constants } from "node:fs";
|
||||||
|
import type { TrackedPlayers } from "~/types";
|
||||||
|
|
||||||
const TRACKED_PLAYER_FILE = "./.cache/tracked.json";
|
const TRACKED_PLAYER_FILE = "./.cache/tracked.json";
|
||||||
|
|
||||||
type TrackedPlayers = Record<string, string[]>;
|
|
||||||
|
|
||||||
export async function initTracking(): Promise<void> {
|
export async function initTracking(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await access(TRACKED_PLAYER_FILE, constants.F_OK);
|
await access(TRACKED_PLAYER_FILE, constants.F_OK);
|
||||||
@@ -1,21 +1,7 @@
|
|||||||
import { env } from "./env";
|
import { env } from "~/env";
|
||||||
import { mkdir, readFile, writeFile, access } from "node:fs/promises";
|
import { mkdir, readFile, writeFile, access } from "node:fs/promises";
|
||||||
import { constants } from "node:fs";
|
import { constants } from "node:fs";
|
||||||
|
import type { QuestResult } from "~/types";
|
||||||
export type QuestResult = {
|
|
||||||
quest: {
|
|
||||||
id: string;
|
|
||||||
promoImageUrl: string;
|
|
||||||
promoImagePrimaryColor: string;
|
|
||||||
};
|
|
||||||
participants: Array<QuestParticipant>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type QuestParticipant = {
|
|
||||||
playerId: string;
|
|
||||||
username: string;
|
|
||||||
xp: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getLatestQuest = async (): Promise<QuestResult> => {
|
export const getLatestQuest = async (): Promise<QuestResult> => {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
@@ -49,6 +35,7 @@ export const checkForNewQuest = async (): Promise<QuestResult | null> => {
|
|||||||
await writeFile(cacheFilePath, lastId);
|
await writeFile(cacheFilePath, lastId);
|
||||||
return lastQuest;
|
return lastQuest;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getClanMembers = async (): Promise<
|
export const getClanMembers = async (): Promise<
|
||||||
Array<{ playerId: string; username: string }>
|
Array<{ playerId: string; username: string }>
|
||||||
> => {
|
> => {
|
||||||
30
apps/discord-bot/src/types/index.ts
Normal file
30
apps/discord-bot/src/types/index.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export type QuestResult = {
|
||||||
|
quest: {
|
||||||
|
id: string;
|
||||||
|
promoImageUrl: string;
|
||||||
|
promoImagePrimaryColor: string;
|
||||||
|
};
|
||||||
|
participants: Array<QuestParticipant>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type QuestParticipant = {
|
||||||
|
playerId: string;
|
||||||
|
username: string;
|
||||||
|
xp: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DiscordMessage = {
|
||||||
|
content: string;
|
||||||
|
embeds: Array<DiscordEmbed>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DiscordEmbed = {
|
||||||
|
title?: string;
|
||||||
|
description: string;
|
||||||
|
image?: {
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
color: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TrackedPlayers = Record<string, string[]>;
|
||||||
@@ -1,20 +1,6 @@
|
|||||||
import { getAccountBalance, setAccountBalance } from "./account";
|
import { getAccountBalance, setAccountBalance } from "~/services/account";
|
||||||
import { env } from "./env";
|
import { env } from "~/env";
|
||||||
import type { QuestResult } from "./wov";
|
import type { QuestResult, DiscordMessage, DiscordEmbed } from "~/types";
|
||||||
|
|
||||||
export type DiscordMessage = {
|
|
||||||
content: string;
|
|
||||||
embeds: Array<DiscordEmbed>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type DiscordEmbed = {
|
|
||||||
title?: string;
|
|
||||||
description: string;
|
|
||||||
image?: {
|
|
||||||
url: string;
|
|
||||||
};
|
|
||||||
color: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const makeResultEmbed = async (
|
export const makeResultEmbed = async (
|
||||||
result: QuestResult,
|
result: QuestResult,
|
||||||
@@ -82,3 +68,30 @@ export const makeResultEmbed = async (
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createErrorEmbed = (message: string, color = 15335424) => ({
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
description: `### ❌ Erreur\n\n\n${message}`,
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createSuccessEmbed = (message: string, color = 65280) => ({
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
description: `### ✅ ${message}`,
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createInfoEmbed = (message: string, color = 0x89cff0) => ({
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
description: message,
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
115
apps/discord-bot/src/utils/quest.ts
Normal file
115
apps/discord-bot/src/utils/quest.ts
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import { ChannelType, type Client, type Message } from "discord.js";
|
||||||
|
import { env } from "~/env";
|
||||||
|
import { makeResultEmbed } from "~/utils/discord";
|
||||||
|
import type { QuestResult } from "~/types";
|
||||||
|
|
||||||
|
export const askForGrinders = async (quest: QuestResult, client: Client) => {
|
||||||
|
const adminChannel = await client.channels.fetch(env.DISCORD_ADMIN_CHANNEL);
|
||||||
|
if (!adminChannel || adminChannel.type !== ChannelType.GuildText)
|
||||||
|
throw "Invalid admin channel provided";
|
||||||
|
|
||||||
|
const top10 = quest.participants
|
||||||
|
.filter((x) => !env.QUEST_EXCLUDE.includes(x.username))
|
||||||
|
.sort((a, b) => b.xp - a.xp)
|
||||||
|
.slice(0, 10)
|
||||||
|
.map((p, i) => `${i + 1}. ${p.username} - ${p.xp}xp`)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
const color = parseInt(quest.quest.promoImagePrimaryColor.substring(1), 16);
|
||||||
|
|
||||||
|
await adminChannel.send({
|
||||||
|
content: `-# ||${env.DISCORD_ADMIN_MENTION}||`,
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
title: "Quête terminée !",
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Top 10 XP",
|
||||||
|
description: top10,
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Qui a grind ?",
|
||||||
|
description:
|
||||||
|
"Merci d'entrer les pseudos des joueurs qui ont grind.\n\nFormat:```@LBF laulau,Yuno,...```\n**Attention les majuscules comptent**\nPour entrer la liste des joueurs, il faut __mentionner le bot__, si personne n'a grind, `@LBF tg`",
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const filter = (msg: Message) =>
|
||||||
|
msg.channel.id === adminChannel.id &&
|
||||||
|
!msg.author.bot &&
|
||||||
|
msg.content.startsWith(`<@${client.user!.id}>`);
|
||||||
|
|
||||||
|
let confirmed = false;
|
||||||
|
let answer: string | null = null;
|
||||||
|
while (!confirmed) {
|
||||||
|
const collected = await adminChannel.awaitMessages({ filter, max: 1 });
|
||||||
|
answer = collected.first()?.content || null;
|
||||||
|
if (!answer) continue;
|
||||||
|
|
||||||
|
answer = answer.replace(`<@${client.user!.id}>`, "").trim();
|
||||||
|
if (answer.toLowerCase() === "tg") {
|
||||||
|
answer = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const players = answer
|
||||||
|
.split(",")
|
||||||
|
.map((x) => x.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
await adminChannel.send({
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
title: "Joueurs entrés",
|
||||||
|
description: players.length
|
||||||
|
? players.map((name) => `- ${name}`).join("\n")
|
||||||
|
: "*Aucun joueur entré*",
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
content: `Est-ce correct ? (oui/non)`,
|
||||||
|
});
|
||||||
|
const confirmFilter = (msg: Message) =>
|
||||||
|
msg.channel.id === adminChannel.id &&
|
||||||
|
!msg.author.bot &&
|
||||||
|
["oui", "non", "yes", "no"].includes(msg.content.toLowerCase());
|
||||||
|
const confirmCollected = await adminChannel.awaitMessages({
|
||||||
|
filter: confirmFilter,
|
||||||
|
max: 1,
|
||||||
|
});
|
||||||
|
const confirmation = confirmCollected.first()?.content.toLowerCase();
|
||||||
|
if (confirmation === "oui" || confirmation === "yes") {
|
||||||
|
confirmed = true;
|
||||||
|
await adminChannel.send({ content: "Ok" });
|
||||||
|
} else {
|
||||||
|
await adminChannel.send({
|
||||||
|
content: "D'accord, veuillez réessayer. Qui a grind ?",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (answer === null) throw "unreachable";
|
||||||
|
|
||||||
|
const exclude = answer
|
||||||
|
.split(",")
|
||||||
|
.map((x) => x.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
const embed = await makeResultEmbed(quest, [
|
||||||
|
...env.QUEST_EXCLUDE,
|
||||||
|
...exclude,
|
||||||
|
]);
|
||||||
|
const rewardChannel = await client.channels.fetch(
|
||||||
|
env.DISCORD_REWARDS_CHANNEL,
|
||||||
|
);
|
||||||
|
if (rewardChannel && rewardChannel.type === ChannelType.GuildText) {
|
||||||
|
await rewardChannel.send(embed);
|
||||||
|
} else {
|
||||||
|
throw "Invalid reward channel";
|
||||||
|
}
|
||||||
|
|
||||||
|
await adminChannel.send("Envoyé !");
|
||||||
|
console.log(`Quest result posted at: ${new Date().toISOString()}`);
|
||||||
|
};
|
||||||
@@ -1,16 +1,14 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"noEmit": false,
|
|
||||||
"noEmitOnError": true,
|
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src",
|
"declaration": true,
|
||||||
"sourceMap": true
|
"declarationMap": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"removeComments": false
|
||||||
},
|
},
|
||||||
"tsc-alias": {
|
"tsc-alias": {
|
||||||
"resolveFullPaths": true,
|
"resolveFullPaths": true
|
||||||
"verbose": false
|
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"]
|
||||||
"exclude": ["node_modules", "dist"]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"lib": ["ESNext"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "Bundler",
|
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
"allowJs": true,
|
|
||||||
|
|
||||||
"esModuleInterop": true,
|
"moduleResolution": "bundler",
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowImportingTsExtensions": false,
|
||||||
"resolveJsonModule": true,
|
"baseUrl": ".",
|
||||||
"noEmit": true,
|
"paths": {
|
||||||
|
"~/*": ["./src/*"],
|
||||||
|
"~": ["./src/index"]
|
||||||
|
},
|
||||||
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
|
||||||
"noUnusedLocals": false,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": false,
|
"noUnusedParameters": false,
|
||||||
"noPropertyAccessFromIndexSignature": false,
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
},
|
||||||
"baseUrl": ".",
|
"include": ["src"],
|
||||||
"paths": {
|
"exclude": ["node_modules", "dist"]
|
||||||
"~/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user