mirror of
https://github.com/cassoule/flopobot_v2.git
synced 2026-03-18 21:40:27 +01:00
@@ -19,6 +19,7 @@ import {
|
||||
import { getShuffledOptions, getResult } from './game.js';
|
||||
import { Client, GatewayIntentBits } from 'discord.js';
|
||||
import cron from 'node-cron';
|
||||
import { flopoDB, insertUser, insertManyUsers, updateUser, updateManyUsers, getUser, getAllUsers, stmt } from './init_database.js';
|
||||
|
||||
// Create an express app
|
||||
const app = express();
|
||||
@@ -39,12 +40,52 @@ const client = new Client({
|
||||
]
|
||||
});
|
||||
|
||||
const requestTimestamps = new Map(); // userId => [timestamp1, timestamp2, ...]
|
||||
const MAX_REQUESTS_PER_INTERVAL = parseInt(process.env.MAX_REQUESTS || "5");
|
||||
|
||||
const akhysData= new Map()
|
||||
|
||||
async function getAkhys() {
|
||||
try {
|
||||
stmt.run();
|
||||
const guild = await client.guilds.fetch(process.env.GUILD_ID);
|
||||
const members = await guild.members.fetch(); // Fetch all members
|
||||
|
||||
const akhys = members.filter(m => !m.user.bot && m.roles.cache.has(process.env.VOTING_ROLE_ID));
|
||||
|
||||
akhys.forEach(akhy => {
|
||||
akhysData.set(akhy.user.id, {
|
||||
id: akhy.user.id,
|
||||
username: akhy.user.username,
|
||||
globalName: akhy.user.globalName,
|
||||
warned: false,
|
||||
warns: 0,
|
||||
allTimeWarns: 0,
|
||||
totalRequests: 0,
|
||||
});
|
||||
insertManyUsers([
|
||||
{
|
||||
id: akhy.user.id,
|
||||
username: akhy.user.username,
|
||||
globalName: akhy.user.globalName,
|
||||
warned: 0,
|
||||
warns: 0,
|
||||
allTimeWarns: 0,
|
||||
totalRequests: 0
|
||||
},
|
||||
]);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error while counting akhys:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function getOnlineUsersWithRole(guild_id=process.env.GUILD_ID, role_id=process.env.VOTING_ROLE_ID) {
|
||||
try {
|
||||
const guild = await client.guilds.fetch(guild_id);
|
||||
const members = await guild.members.fetch(); // Fetch all members
|
||||
|
||||
const online = members.filter(m => !m.user.bot && (m.presence?.status === 'online' || m.presence?.status === 'dnd') && m.roles.cache.has(role_id));
|
||||
const online = members.filter(m => !m.user.bot && m.presence?.status && m.roles.cache.has(role_id));
|
||||
return online
|
||||
} catch (err) {
|
||||
console.error('Error while counting online members:', err);
|
||||
@@ -62,16 +103,84 @@ client.on('messageCreate', async (message) => {
|
||||
// Check if the message content includes the word "quoi" (case-insensitive)
|
||||
if (message.content.toLowerCase().includes("quoi")) {
|
||||
let prob = Math.random()
|
||||
console.log(`feur ? ${prob} ${process.env.FEUR_PROB}`)
|
||||
console.log(`feur ${prob}`)
|
||||
if (prob < process.env.FEUR_PROB) {
|
||||
console.log('feur!')
|
||||
// Send a message "feur" to the same channel
|
||||
message.channel.send(`feur`)
|
||||
.catch(console.error);
|
||||
}
|
||||
}
|
||||
else if (message.content.toLowerCase().startsWith(`<@${process.env.APP_ID}>`) || message.mentions.repliedUser?.id === process.env.APP_ID) {
|
||||
//let akhyAuthor = akhysData.get(message.author.id)
|
||||
let akhyAuthor = getUser.get(message.author.id)
|
||||
|
||||
const now = Date.now();
|
||||
const timestamps = requestTimestamps.get(message.author.id) || [];
|
||||
|
||||
// Remove timestamps older than SPAM_INTERVAL seconds
|
||||
const updatedTimestamps = timestamps.filter(ts => now - ts < process.env.SPAM_INTERVAL);
|
||||
|
||||
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.channel.send(`T'abuses fréro, attends un peu ⏳`);
|
||||
// akhyAuthor.warned = true;
|
||||
// akhyAuthor.warns++;
|
||||
// akhyAuthor.allTimeWarns++;
|
||||
updateManyUsers([
|
||||
{
|
||||
id: akhyAuthor.id,
|
||||
username: akhyAuthor.username,
|
||||
globalName: akhyAuthor.globalName,
|
||||
warned: 1, // true
|
||||
warns: akhyAuthor.warns + 1,
|
||||
allTimeWarns: akhyAuthor.allTimeWarns + 1,
|
||||
totalRequests: akhyAuthor.totalRequests
|
||||
},
|
||||
])
|
||||
akhyAuthor = getUser.get(akhyAuthor.id)
|
||||
if (akhyAuthor.warns > process.env.MAX_WARNS ?? 10) {
|
||||
const guild = await client.guilds.fetch(process.env.GUILD_ID);
|
||||
const time = parseInt(process.env.SPAM_TIMEOUT_TIME)
|
||||
try {
|
||||
await guild.members.edit(akhyAuthor.id, {
|
||||
communication_disabled_until: new Date(Date.now() + time).toISOString(),
|
||||
reason: 'Dose le spam fdp',
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Tried timeout for AI spam : ', e)
|
||||
message.channel.send(`<@${akhyAuthor.id}> tu me fais chier !! T'as de la chance que je puisse pas te timeout 🔪`)
|
||||
.catch(console.error);
|
||||
return
|
||||
}
|
||||
message.channel.send(`Ce bouffon de <@${akhyAuthor.id}> a été timeout pendant ${formatTime(time/1000)}, il me cassait les couilles 🤫`)
|
||||
.catch(console.error);
|
||||
return
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Track this new usage
|
||||
updatedTimestamps.push(now);
|
||||
requestTimestamps.set(message.author.id, updatedTimestamps);
|
||||
|
||||
// Proceed with your logic
|
||||
// akhyAuthor.warned = false;
|
||||
// akhyAuthor.warns = 0;
|
||||
// akhyAuthor.totalRequests++;
|
||||
updateManyUsers([
|
||||
{
|
||||
id: akhyAuthor.id,
|
||||
username: akhyAuthor.username,
|
||||
globalName: akhyAuthor.globalName,
|
||||
warned: 0, // false
|
||||
warns: 0, // reset
|
||||
allTimeWarns: akhyAuthor.allTimeWarns,
|
||||
totalRequests: akhyAuthor.totalRequests + 1
|
||||
},
|
||||
])
|
||||
akhyAuthor = getUser.get(akhyAuthor.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: 50 });
|
||||
@@ -129,7 +238,9 @@ client.on('messageCreate', async (message) => {
|
||||
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}`
|
||||
});
|
||||
|
||||
const reply = 'Je chill zbi (ntm a vouloir gaspiller les token)'//await gork(formatted); IA en pause
|
||||
// 'Je chill zbi (ntm a vouloir gaspiller les token)' // IA en pause
|
||||
// await gork(formatted); IA en marche
|
||||
const reply = await gork(formatted);
|
||||
|
||||
// Send response to the channel
|
||||
await message.channel.send(reply);
|
||||
@@ -138,6 +249,14 @@ client.on('messageCreate', async (message) => {
|
||||
await message.channel.send("Oups, y'a eu un problème!");
|
||||
}
|
||||
}
|
||||
else if (message.content.toLowerCase().startsWith('membres')) {
|
||||
let content = ``
|
||||
const allAkhys = getAllUsers.all()
|
||||
allAkhys.forEach((akhy) => content += `> ### ${akhy.globalName} \n > **${akhy.totalRequests}** requests \n > **${akhy.warns}** warns \n > **${akhy.allTimeWarns}** all-time warns \n\n`);
|
||||
|
||||
message.channel.send(`${content}`)
|
||||
.catch(console.error);
|
||||
}
|
||||
});
|
||||
|
||||
// Once bot is ready
|
||||
@@ -147,6 +266,8 @@ client.once('ready', async () => {
|
||||
const randomHour = Math.floor(Math.random() * (18 - 8 + 1)) + 8;
|
||||
todaysHydrateCron = `${randomMinute} ${randomHour} * * *`
|
||||
console.log(todaysHydrateCron)
|
||||
await getAkhys();
|
||||
console.log('Akhys ready')
|
||||
|
||||
// ─── 💀 Midnight Chaos Timer ──────────────────────
|
||||
cron.schedule(process.env.CRON_EXPR, async () => {
|
||||
@@ -156,7 +277,7 @@ client.once('ready', async () => {
|
||||
|
||||
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);
|
||||
const members = await getOnlineUsersWithRole(process.env.GUILD_ID, roleId);
|
||||
|
||||
const prob = Math.random();
|
||||
if (members.size === 0 || prob > process.env.CHAOS_PROB) {
|
||||
@@ -164,7 +285,7 @@ client.once('ready', async () => {
|
||||
return
|
||||
}
|
||||
|
||||
const randomMember = eligible[Math.floor(Math.random() * members.size)];
|
||||
const randomMember = members[Math.floor(Math.random() * members.size)];
|
||||
|
||||
const timeoutUntil = new Date(Date.now() + 12 * 60 * 60 * 1000).toISOString();
|
||||
|
||||
@@ -200,7 +321,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()}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -312,29 +433,6 @@ app.post('/interactions', verifyKeyMiddleware(process.env.PUBLIC_KEY), async fun
|
||||
const requiredMajority = Math.max(parseInt(process.env.MIN_VOTES), Math.floor(onlineEligibleUsers.size / 2) + 1);
|
||||
const votesNeeded = Math.max(0, requiredMajority - activePolls[id].for);
|
||||
|
||||
// Set a timeout for 5 minutes to end the poll if no majority is reached
|
||||
/* setTimeout(async () => {
|
||||
if (activePolls[id]) {
|
||||
// Poll has expired without enough votes
|
||||
// Send a notification to the channel that the vote failed
|
||||
try {
|
||||
await DiscordRequest(
|
||||
`webhooks/${process.env.APP_ID}/${req.body.token}/messages/@original`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
body: {
|
||||
content: `Le vote pour timeout de <@${activePolls[id].toUserId}> a expiré sans atteindre la majorité.`,
|
||||
components: [] // remove the buttons
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
console.error('Error sending vote failure message:', err);
|
||||
}
|
||||
// Clear the poll
|
||||
delete activePolls[id];
|
||||
}
|
||||
}, process.env.POLL_TIME * 1000);*/
|
||||
activePolls[id].endTime = Date.now() + process.env.POLL_TIME * 1000;
|
||||
activePolls[id].requiredMajority = requiredMajority;
|
||||
|
||||
43
init_database.js
Normal file
43
init_database.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import Database from "better-sqlite3";
|
||||
|
||||
|
||||
export const flopoDB = new Database('flopobot.db');
|
||||
|
||||
export const stmt = flopoDB.prepare(`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id TEXT PRIMARY KEY,
|
||||
username TEXT NOT NULL,
|
||||
globalName TEXT,
|
||||
warned BOOLEAN DEFAULT 0,
|
||||
warns INTEGER DEFAULT 0,
|
||||
allTimeWarns INTEGER DEFAULT 0,
|
||||
totalRequests INTEGER DEFAULT 0
|
||||
)
|
||||
`);
|
||||
stmt.run();
|
||||
|
||||
export const insertUser = flopoDB.prepare('INSERT INTO users (id, username, globalName, warned, warns, allTimeWarns, totalRequests) VALUES (@id, @username, @globalName, @warned, @warns, @allTimeWarns, @totalRequests)');
|
||||
export const updateUser = flopoDB.prepare('UPDATE users SET warned = @warned, warns = @warns, allTimeWarns = @allTimeWarns, totalRequests = @totalRequests WHERE id = @id');
|
||||
export const getUser = flopoDB.prepare('SELECT * FROM users WHERE id = ?');
|
||||
export const getAllUsers = flopoDB.prepare('SELECT * FROM users');
|
||||
|
||||
export const insertManyUsers = flopoDB.transaction((users) => {
|
||||
for (const user of users) try { insertUser.run(user) } catch (e) { console.log('users insert failed') };
|
||||
});
|
||||
export const updateManyUsers = flopoDB.transaction((users) => {
|
||||
for (const user of users) try { updateUser.run(user) } catch (e) { console.log('users update failed') };
|
||||
});
|
||||
//const getManyUsers = flopoDB.transaction(())
|
||||
|
||||
|
||||
// insertManyUsers([
|
||||
// { id: '1234', username: 'Username', globalName: 'GlobalName', warned: 0, warns: 0, allTimeWarns: 0, totalRequests: 0 },
|
||||
// { id: '12345', username: 'Username', globalName: 'GlobalName', warned: 0, warns: 0, allTimeWarns: 0, totalRequests: 0 },
|
||||
// ]);
|
||||
|
||||
|
||||
// updateManyUsers([
|
||||
// { id: '1234', username: 'Username', globalName: 'GlobalName', warned: 0, warns: 0, allTimeWarns: 0, totalRequests: 0 },
|
||||
// ]);
|
||||
|
||||
//console.log(getUser.get('12345'))
|
||||
Reference in New Issue
Block a user