diff --git a/app.js b/app.js index ae9bdc7..c91f9b2 100644 --- a/app.js +++ b/app.js @@ -8,18 +8,26 @@ import { MessageComponentTypes, verifyKeyMiddleware, } from 'discord-interactions'; -import { getRandomEmoji, DiscordRequest, getOnlineUsersWithRole, formatTime, gork } from './utils.js'; +import { + getRandomEmoji, + DiscordRequest, + getOnlineUsersWithRole, + formatTime, + gork, + getRandomHydrateText +} from './utils.js'; import { getShuffledOptions, getResult } from './game.js'; import { Client, GatewayIntentBits } from 'discord.js'; import cron from 'node-cron'; // Create an express app const app = express(); -// Get port, or default to 3000 +// Get port, or default to 25578 const PORT = process.env.PORT || 25578; // To keep track of our active games const activeGames = {}; const activePolls = {}; +let todaysHydrateCron = '' const client = new Client({ intents: [ @@ -49,48 +57,64 @@ client.on('messageCreate', async (message) => { } } - if (message.content.toLowerCase().startsWith(`<@${process.env.APP_ID}>`)) { + if (message.content.toLowerCase().startsWith(`<@${process.env.APP_ID}>`) || message.mentions.repliedUser?.id === process.env.APP_ID) { try { // Fetch last 10 messages from the channel - const fetched = await message.channel.messages.fetch({ limit: 100 }); + const fetched = await message.channel.messages.fetch({ limit: 50 }); const messagesArray = Array.from(fetched.values()).reverse(); // oldest to newest - const requestMessage = message.content.replace('@gork', '') + const requestMessage = message.content.replace(`<@${process.env.APP_ID}>`, '') // Map to OpenAI format let formatted = messagesArray.map(msg => ({ role: msg.author.bot ? "assistant" : "user", - content: msg.content, - author: msg.author.username, + content: `${msg.author.id} | ${msg.content} | ${msg.id}`, })); const members = await getOnlineUsersWithRole(process.env.GUILD_ID, process.env.VOTING_ROLE_ID); + 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`, + }) + members.forEach(member => { + formatted.push({ + role: 'developer', + content: `${member.user.id} : ${member.user.global_name}, ${member.user.username}`, + }) + }) + // Add a final user prompt to clarify the request formatted.push( { - role: "system", - content: "Sachant que les 'author' sont les pseudos des personnes ayant écrit chaque message. Adopte une attitude détendu et répond comme si tu participais à la conversation, essaye d'imiter au mieux la façon de parler des utilisateurs. Soit malpoli, grossier, aigri etc, n'hésites pas à utiliser des abréviations mais sans en abuser. Manque de respect quand tu le peux, sauf contre-indications de l'utilisateur, fait plutôt court, une ou deux phrases maximum " + role: "developer", + content: "Sachant que chaque message d'utilisateur comporte l'id de l'utilisateur ayant écrit le message au début de l'entrée, le contenu du message, et l'id du message pour finir (formaté comme suit : user_id | content | message_id). Adopte une attitude détendue et répond comme si tu participais à la conversation, essaye d'imiter au mieux la façon de parler des utilisateurs et/ou d'un utilisateur de twitter (X). N'hésites pas à utiliser des abréviations mais sans en abuser. Fait plutôt court, une ou deux phrases maximum " }, { - role: "system", - content: `Voici la liste des principaux utilisateurs : ${members}` - }, - { - role: "system", - content: `L'utilisateur qui s'adresse a toi dans la prochaine phrase est : ${message.author}` + role: "developer", + content: `L'utilisateur qui s'adresse a toi dans la prochaine phrase est : ${message.author}, si le message de l'utilisateur est vide et/ou ne comporte que ton ID, agis comme s'il voulait savoir si tu es présent, et réponds de manière très très courte dans ce cas, 2 ou 3 mots` }, { role: "user", - content: requestMessage.length > 1 ? requestMessage : 'Répond de manière approprié aux derniers messages de cette conversation.', + content: requestMessage.length > 1 ? requestMessage : 'Répond de manière approprié aux derniers messages de cette conversation. Sans prendre en compte mon dernier message vide', }, { - role: "system", - content: 'En te basant sur la liste des utilisateurs, lorsque tu parles d\'un utilisateur présent dans cette liste que ce soit via son \'user.global_name\', son \'user.username\' ou son \'user.id\' , identifie le avec son \'user.id\' plutôt que d\'utiliser son \'user.global_name\', ça doit ressembler à ça en remplaçant \'ID\' <@ID>. Fait le la première fois que tu évoques l\'utilisateur mais donne juste son \'user.global_name\' ensuite', + role: 'developer', + content: message.mentions.repliedUser?.id ? `La phrase de l'utilisateur répond à un message de ${message.mentions.repliedUser?.id === process.env.APP_ID ? 'toi-même' : message.mentions.repliedUser?.id}, l'id du message est : ${message.reference?.messageId}` : '', + }, + { + role: "developer", + content: "Considère chaque messages d'utilisateurs afin d'établir un contexte de la situation, si tu ne comprends pas le dernière demande utilisateur analyse le reste des demandes." + }, + { + role: "developer", + content: 'En te basant sur la liste des utilisateurs et des id utilisateurs présent au début de chaque message, lorsque tu parles d\'un utilisateur présent dans cette liste que ce soit via son \'user.global_name\', son \'user.username\' ou son \'user.id\' , identifie le avec son \'user.id\' plutôt que d\'utiliser son \'user.global_name\', ça doit ressembler à ça en remplaçant \'ID\' <@ID>. Fait le la première fois que tu évoques l\'utilisateur mais donne juste son \'user.global_name\' ensuite', + }, + { + role: "developer", + content: `Ton id est : ${process.env.APP_ID}, évite de l'utiliser et ne formatte pas tes messages avec ton propre id, si jamais tu utilises un id formatte le comme suit : <@ID>, en remplacant ID par l'id. Ton username et global_name sont : ${process.env.APP_NAME}` }); - formatted = formatted.filter(e => e.role !== 'assistant'); - const reply = await gork(formatted); // Send response to the channel @@ -105,9 +129,17 @@ client.on('messageCreate', async (message) => { // Once bot is ready client.once('ready', () => { console.log(`Logged in as ${client.user.tag}`); + const randomMinute = Math.floor(Math.random() * 60); + const randomHour = Math.floor(Math.random() * (18 - 8 + 1)) + 8; + todaysHydrateCron = `${randomMinute} ${randomHour} * * *` + console.log(todaysHydrateCron) // ─── 💀 Midnight Chaos Timer ────────────────────── cron.schedule(process.env.CRON_EXPR, async () => { + const randomMinute = Math.floor(Math.random() * 60); + const randomHour = Math.floor(Math.random() * (18 - 8 + 1)) + 8; + todaysHydrateCron = `${randomMinute} ${randomHour} * * *` + const guild = await client.guilds.fetch(process.env.GUILD_ID); const roleId = process.env.VOTING_ROLE_ID; // Set this in your .env file const members = await getOnlineUsersWithRole(guild.id, roleId); @@ -146,6 +178,26 @@ client.once('ready', () => { console.error('Failed to timeout random member:', err); } }); + + cron.schedule(todaysHydrateCron, async () => { + const guild = await client.guilds.fetch(process.env.GUILD_ID); + + try { + const generalChannel = guild.channels.cache.find( + ch => ch.name === 'général' || ch.name === 'general' + ); + + if (generalChannel && generalChannel.isTextBased()) { + generalChannel.send( + `${getRandomHydrateText()} <@${process.env.VOTING_ROLE_ID}> ${getRandomEmoji()}` + ); + } + + console.log(`Message hydratation`); + } catch (err) { + console.error('Message hydratation:', err); + } + }); }); /** @@ -155,7 +207,6 @@ client.once('ready', () => { app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async function (req, res) { // Interaction id, type and data const { id, type, data } = req.body; - console.log(id); /** * Handle verification requests diff --git a/commands.js b/commands.js index 6f02bef..22465d7 100644 --- a/commands.js +++ b/commands.js @@ -61,7 +61,7 @@ const CHALLENGE_COMMAND = { // Timeout vote command const TIMEOUT_COMMAND = { name: 'timeout', - description: 'Vote démocratique pour time out un boug', + description: 'Vote démocratique pour timeout un boug', options: [ { type: 6, diff --git a/utils.js b/utils.js index 3fd681b..e839cab 100644 --- a/utils.js +++ b/utils.js @@ -42,6 +42,36 @@ export function getRandomEmoji() { const emojiList = ['😭','😄','😌','🤓','😎','😤','🤖','😶‍🌫️','🌏','📸','💿','👋','🌊','✨']; return emojiList[Math.floor(Math.random() * emojiList.length)]; } +export function getRandomHydrateText() { + const texts = [ + `Hydratez-vous`, + `Pensez à vous hydratez`, + `Vous vous êtes hydratez aujourd'hui ?`, + `Buvez de l'eau la team`, + `#etsi vous vous hydratiez`, + `Oubliez pas de vous hydratez`, + `Hydratez vous la team`, + `Hydratez vous c'est important`, + `Hydratez-vous`, + `Pensez à vous hydratez`, + `Vous vous êtes hydratez aujourd'hui ?`, + `Buvez de l'eau la team`, + `#etsi vous vous hydratiez`, + `Oubliez pas de vous hydratez`, + `Hydratez vous la team`, + `Hydratez vous c'est important`, + `Hydratez-vous`, + `Pensez à vous hydratez`, + `Vous vous êtes hydratez aujourd'hui ?`, + `Buvez de l'eau la team`, + `#etsi vous vous hydratiez`, + `Oubliez pas de vous hydratez`, + `Hydratez vous la team`, + `Hydratez vous c'est important`, + `nsm ojd ça s'hydrate pas`, + ]; + return texts[Math.floor(Math.random() * texts.length)]; +} export function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1);