From 68f6f95c88209362837a3f64302273c4bb7cb54e Mon Sep 17 00:00:00 2001 From: milo Date: Tue, 22 Apr 2025 21:59:08 +0200 Subject: [PATCH 1/4] new command register --- commands.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/commands.js b/commands.js index 01b1a6b..f5ff6e4 100644 --- a/commands.js +++ b/commands.js @@ -108,6 +108,14 @@ const INVENTORY_COMMAND = { contexts: [0, 2], } -const ALL_COMMANDS = [/*TEST_COMMAND, CHALLENGE_COMMAND, */TIMEOUT_COMMAND, INVENTORY_COMMAND, VALORANT_COMMAND]; +const INFO_COMMAND = { + name: 'info', + description: 'Qui est time out ?', + type: 1, + integration_types: [0, 1], + contexts: [0, 2], +} + +const ALL_COMMANDS = [TIMEOUT_COMMAND, INVENTORY_COMMAND, VALORANT_COMMAND, INFO_COMMAND]; InstallGlobalCommands(process.env.APP_ID, ALL_COMMANDS); From 88c61a131156f7ce45139f05f5a8a7928585e88a Mon Sep 17 00:00:00 2001 From: milo Date: Tue, 22 Apr 2025 21:59:24 +0200 Subject: [PATCH 2/4] new T12 custom emojis list --- utils.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/utils.js b/utils.js index d22ac67..f42ae32 100644 --- a/utils.js +++ b/utils.js @@ -40,8 +40,28 @@ export async function InstallGlobalCommands(appId, commands) { } // Simple method that returns a random emoji from list -export function getRandomEmoji() { - const emojiList = ['😭','πŸ˜„','😌','πŸ€“','😎','😀','πŸ€–','πŸ˜Άβ€πŸŒ«οΈ','🌏','πŸ“Έ','πŸ’Ώ','πŸ‘‹','🌊','✨']; +export function getRandomEmoji(list=0) { + let emojiList + + switch (list) { + case 0: + emojiList = ['😭','πŸ˜„','😌','πŸ€“','😎','😀','πŸ€–','πŸ˜Άβ€πŸŒ«οΈ','🌏','πŸ“Έ','πŸ’Ώ','πŸ‘‹','🌊','✨'] + break + case 1: + emojiList = [ + '<:CAUGHT:1323810730155446322>', + '<:hinhinhin:1072510144933531758>', + '<:o7:1290773422451986533>', + '<:zhok:1115221772623683686>', + '<:nice:1154049521110765759>', + '<:nerd~1:1087658195603951666>', + '<:peepSelfie:1072508131839594597>', + ] + break + default: + emojiList = [''] + break + } return emojiList[Math.floor(Math.random() * emojiList.length)]; } export function getRandomHydrateText() { From 39dd999e8ba6e276078ab3f878a1e73a55a19f4c Mon Sep 17 00:00:00 2001 From: milo Date: Tue, 22 Apr 2025 21:59:36 +0200 Subject: [PATCH 3/4] new stuffs --- index.js | 186 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 61 deletions(-) diff --git a/index.js b/index.js index 692e25b..1ef26bf 100644 --- a/index.js +++ b/index.js @@ -295,7 +295,11 @@ client.on('messageCreate', async (message) => { if (updatedTimestamps.length >= MAX_REQUESTS_PER_INTERVAL) { console.log(akhyAuthor.warned ? `${message.author.username} is restricted : ${updatedTimestamps}` : `Rate limit exceeded for ${message.author.username}`); - if (!akhyAuthor.warned) message.reply(`T'abuses frΓ©ro, attends un peu ⏳`); + if (!akhyAuthor.warned) { + await message.reply(`T'abuses frΓ©ro, attends un peu ⏳`) + } else if (akhyAuthor.warns === Math.max(1, process.env.MAX_WARNS - 3)) { + await message.author.send("Attention si tu continues de spam tu vas te faire timeout 🀯") + } // akhyAuthor.warned = true; // akhyAuthor.warns++; // akhyAuthor.allTimeWarns++; @@ -365,8 +369,6 @@ client.on('messageCreate', async (message) => { })); const allAkhys = await getAllUsers.all() if (process.env.MODEL === 'OpenAI' || process.env.MODEL === 'Gemini') { - - formatted.push({ role: 'developer', content: `Les prochaines entrΓ©es sont les diffΓ©rents utilisateurs prΓ©sents. Chaque entrΓ©e comporte l'id, le nom sur le serveur et le nom sur discord d'un utilisateur`, @@ -497,6 +499,20 @@ client.once('ready', async () => { await getAkhys(); console.log('Ready') + // every 5 minutes + cron.schedule('*/5 * * * *', async () => { + const FIVE_MINUTES = 5 * 60 * 1000; + + // clean 5 minutes old inventories + for (const id in activeInventories) { + const inventory = activeInventories[id]; + if (Date.now() >= inventory.timestamp + FIVE_MINUTES) { + console.log(`Removing expired inventory : ${id}`); + delete activeInventories[id]; + } + } + }); + // ─── πŸ’€ Midnight Chaos Timer ────────────────────── cron.schedule(process.env.CRON_EXPR, async () => { const randomMinute = Math.floor(Math.random() * 60); @@ -549,7 +565,7 @@ client.once('ready', async () => { if (generalChannel && generalChannel.isTextBased()) { generalChannel.send( - `${getRandomHydrateText()} <@&${process.env.VOTING_ROLE_ID}> ${getRandomEmoji()}` + `${getRandomHydrateText()} <@&${process.env.VOTING_ROLE_ID}> ${getRandomEmoji(1)}` ); } @@ -597,6 +613,28 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun const fromMember = await guild.members.fetch(userId); const toMember = await guild.members.fetch(akhy); + const already = Object.values(activePolls).find(poll => poll.toUsername === toMember.user); + + if (already) { + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `Impossible de timeout **${toMember.user}** car un vote est dΓ©jΓ  en cours`, + flags: InteractionResponseFlags.EPHEMERAL, + } + }); + } + + if (toMember.communicationDisabledUntilTimestamp > Date.now()) { + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `**${toMember.user}** est dΓ©jΓ  timeout`, + flags: InteractionResponseFlags.EPHEMERAL, + } + }); + } + // Save the poll information along with channel ID so we can notify later activePolls[id] = { id: userId, @@ -645,7 +683,7 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun body: { embeds: [ { - title: `Le vote pour timeout ${poll.toUsername} pendant ${poll.time_display} a Γ©chouΓ© πŸ˜”`, + title: `Le vote pour timeout ${poll.toUsername.username} pendant ${poll.time_display} a Γ©chouΓ© πŸ˜”`, description: `Il manquait **${votesNeeded}** vote(s)`, fields: [ { @@ -826,9 +864,11 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun activeInventories[id] = { akhyId: akhy, + userId: userId, page: 0, amount: invSkins.length, endpoint: `webhooks/${process.env.APP_ID}/${req.body.token}/messages/@original`, + timestamp: Date.now(), }; if (invSkins.length === 0) { @@ -904,10 +944,6 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun }); } - if (name === 'others_inventory') { - // TODO - } - if (name === 'valorant') { // First, send the initial response immediately const initialEmbed = new EmbedBuilder() @@ -1111,6 +1147,51 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun return; } + if (name === 'info') { + const guild = await client.guilds.fetch(req.body.guild_id); + + await guild.members.fetch() + + const timedOutMembers = guild.members.cache.filter( + (member) => + member.communicationDisabledUntil && + member.communicationDisabledUntil > new Date() + ); + + if (timedOutMembers.size === 0) { + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + embeds: [ + { + title: `Membres timeout`, + description: "Aucun membre n'est actuellement timeout.", + color: 0xF2F3F3, + }, + ], + }, + }); + } + + const list = timedOutMembers.map( + (member) => + `**${member.user.tag}** (jusqu'Γ  ${member.communicationDisabledUntil.toLocaleString()})` + ).join("\n"); + + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + embeds: [ + { + title: `Membres timeout`, + description: `${list}`, + color: 0xF2F3F3, + }, + ], + }, + }); + } + console.error(`unknown command: ${name}`); return res.status(400).json({ error: 'unknown command' }); } @@ -1152,50 +1233,6 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun console.error('Error sending message:', err); } } - else if (componentId.startsWith('select_choice_')) { - // get the associated game ID - const gameId = componentId.replace('select_choice_', ''); - - if (activeGames[gameId]) { - // Interaction context - const context = req.body.context; - // Get user ID and object choice for responding user - // User ID is in user field for (G)DMs, and member for servers - const userId = context === 0 ? req.body.member.user.id : req.body.user.id; - - // User's object choice - const objectName = data.values[0]; - - // Calculate result from helper function - const resultStr = getResult(activeGames[gameId], { - id: userId, - objectName, - }); - - // Remove game from storage - delete activeGames[gameId]; - // Update message with token in request body - const endpoint = `webhooks/${process.env.APP_ID}/${req.body.token}/messages/${req.body.message.id}`; - - try { - // Send results - await res.send({ - type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, - data: { content: resultStr }, - }); - // Update ephemeral message - await DiscordRequest(endpoint, { - method: 'PATCH', - body: { - content: 'Nice choice ' + getRandomEmoji(), - components: [] - } - }); - } catch (err) { - console.error('Error sending message:', err); - } - } - } else if (componentId.startsWith('vote_')) { let gameId, isVotingFor; @@ -1366,8 +1403,13 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun // User ID is in user field for (G)DMs, and member for servers const userId = context === 0 ? req.body.member.user.id : req.body.user.id; - const guild = await client.guilds.fetch(req.body.guild_id); - const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); + try { + const guild = await client.guilds.fetch(req.body.guild_id); + const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); + } catch (e) { + console.error(e); + return + } const invSkins = getUserInventory.all({user_id: activeInventories[invId].akhyId}); @@ -1407,13 +1449,21 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun }) }) - if (activeInventories[invId] && activeInventories[invId].akhyId === req.body.member.user.id) { + if (activeInventories[invId] && activeInventories[invId].userId === req.body.member.user.id) { if (activeInventories[invId].page === 0) { activeInventories[invId].page = activeInventories[invId].amount-1 } else { activeInventories[invId].page-- } - } else {return } + } else { + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `Tu n'est pas Γ  l'origine de cette commande /inventory`, + flags: InteractionResponseFlags.EPHEMERAL, + }, + }); + } const trueSkin = skins.find((s) => s.uuid === invSkins[activeInventories[invId].page].uuid); const imageUrl = () => { @@ -1469,8 +1519,14 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun // User ID is in user field for (G)DMs, and member for servers const userId = context === 0 ? req.body.member.user.id : req.body.user.id; - const guild = await client.guilds.fetch(req.body.guild_id); - const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); + try { + const guild = await client.guilds.fetch(req.body.guild_id); + const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); + } catch (e) { + console.error(e); + return + } + const invSkins = getUserInventory.all({user_id: activeInventories[invId].akhyId}); @@ -1510,13 +1566,21 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun }) }) - if (activeInventories[invId] && activeInventories[invId].akhyId === req.body.member.user.id) { + if (activeInventories[invId] && activeInventories[invId].userId === req.body.member.user.id) { if (activeInventories[invId].page === activeInventories[invId].amount-1) { activeInventories[invId].page = 0 } else { activeInventories[invId].page++ } - } else {return } + } else { + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `Tu n'est pas Γ  l'origine de cette commande /inventory`, + flags: InteractionResponseFlags.EPHEMERAL, + }, + }); + } const trueSkin = skins.find((s) => s.uuid === invSkins[activeInventories[invId].page].uuid); const imageUrl = () => { From 9357c7e82f1f1c2ac58f21d988a69efd1f8252cb Mon Sep 17 00:00:00 2001 From: milo Date: Tue, 22 Apr 2025 22:14:50 +0200 Subject: [PATCH 4/4] inventories cleaner --- index.js | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/index.js b/index.js index 1ef26bf..8f4df67 100644 --- a/index.js +++ b/index.js @@ -506,6 +506,8 @@ client.once('ready', async () => { // clean 5 minutes old inventories for (const id in activeInventories) { const inventory = activeInventories[id]; + console.log(Date.now()) + console.log(inventory.timestamp + FIVE_MINUTES) if (Date.now() >= inventory.timestamp + FIVE_MINUTES) { console.log(`Removing expired inventory : ${id}`); delete activeInventories[id]; @@ -1403,13 +1405,17 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun // User ID is in user field for (G)DMs, and member for servers const userId = context === 0 ? req.body.member.user.id : req.body.user.id; - try { - const guild = await client.guilds.fetch(req.body.guild_id); - const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); - } catch (e) { - console.error(e); - return + const guild = await client.guilds.fetch(req.body.guild_id); + if (!activeInventories[invId]) { + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `Oups, cet inventaire n'est plus actif.\nRelance la commande pour avoir un nouvel inventaire interactif`, + flags: InteractionResponseFlags.EPHEMERAL, + }, + }); } + const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); const invSkins = getUserInventory.all({user_id: activeInventories[invId].akhyId}); @@ -1519,14 +1525,17 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun // User ID is in user field for (G)DMs, and member for servers const userId = context === 0 ? req.body.member.user.id : req.body.user.id; - try { - const guild = await client.guilds.fetch(req.body.guild_id); - const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); - } catch (e) { - console.error(e); - return + const guild = await client.guilds.fetch(req.body.guild_id); + if (!activeInventories[invId]) { + return res.send({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `Oups, cet inventaire n'est plus actif.\nRelance la commande pour avoir un nouvel inventaire interactif`, + flags: InteractionResponseFlags.EPHEMERAL, + }, + }); } - + const completeAkhy = await guild.members.fetch(activeInventories[invId].akhyId); const invSkins = getUserInventory.all({user_id: activeInventories[invId].akhyId});