mirror of
https://github.com/cassoule/flopobot_v2.git
synced 2026-01-18 16:37:40 +01:00
some bug fixes and changes
This commit is contained in:
@@ -36,7 +36,7 @@ export async function DiscordRequest(endpoint, options) {
|
||||
} catch (err) {
|
||||
data = res;
|
||||
}
|
||||
console.error(`[${Date.now()}] Discord API Error on endpoint ${endpoint}:`, res.status, data);
|
||||
console.error(`Discord API Error on endpoint ${endpoint}:`, res.status, data);
|
||||
throw new Error(JSON.stringify(data));
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ async function handleAiMention(message, client, io) {
|
||||
const timestamps = (requestTimestamps.get(authorId) || []).filter((ts) => now - ts < SPAM_INTERVAL);
|
||||
|
||||
if (timestamps.length >= MAX_REQUESTS_PER_INTERVAL) {
|
||||
console.log(`[${Date.now()}] Rate limit exceeded for ${authorDB.username}`);
|
||||
console.log(`Rate limit exceeded for ${authorDB.username}`);
|
||||
if (!authorDB.warned) {
|
||||
await message.reply(`T'abuses fréro, attends un peu ⏳`).catch(console.error);
|
||||
}
|
||||
|
||||
@@ -748,7 +748,7 @@ export const updateManyUsers = flopoDB.transaction((users) => {
|
||||
try {
|
||||
updateUser.run(user);
|
||||
} catch (e) {
|
||||
console.log(`[${Date.now()}] user update failed`);
|
||||
console.log(`User update failed`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export async function eloHandler(p1Id, p2Id, p1Score, p2Score, type) {
|
||||
const p1DB = getUser.get(p1Id);
|
||||
const p2DB = getUser.get(p2Id);
|
||||
if (!p1DB || !p2DB) {
|
||||
console.error(`[${Date.now()}] Elo Handler: Could not find user data for ${p1Id} or ${p2Id}.`);
|
||||
console.error(`Elo Handler: Could not find user data for ${p1Id} or ${p2Id}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ export async function eloHandler(p1Id, p2Id, p1Score, p2Score, type) {
|
||||
const finalP1Elo = Math.max(0, p1NewElo);
|
||||
const finalP2Elo = Math.max(0, p2NewElo);
|
||||
|
||||
console.log(`[${Date.now()}] Elo Update (${type}) for ${p1DB.globalName}: ${p1CurrentElo} -> ${finalP1Elo}`);
|
||||
console.log(`[${Date.now()}] Elo Update (${type}) for ${p2DB.globalName}: ${p2CurrentElo} -> ${finalP2Elo}`);
|
||||
console.log(`Elo Update (${type}) for ${p1DB.globalName}: ${p1CurrentElo} -> ${finalP1Elo}`);
|
||||
console.log(`Elo Update (${type}) for ${p2DB.globalName}: ${p2CurrentElo} -> ${finalP2Elo}`);
|
||||
try {
|
||||
const generalChannel = await client.channels.fetch(process.env.BOT_CHANNEL_ID);
|
||||
const user1 = await client.users.fetch(p1Id);
|
||||
@@ -70,7 +70,7 @@ export async function eloHandler(p1Id, p2Id, p1Score, p2Score, type) {
|
||||
.setColor("#5865f2");
|
||||
await generalChannel.send({ embeds: [embed] });
|
||||
} catch (e) {
|
||||
console.error(`[${Date.now()}] Failed to post elo update message`, e);
|
||||
console.error(`Failed to post elo update message`, e);
|
||||
}
|
||||
|
||||
// --- 4. Update Database ---
|
||||
@@ -156,7 +156,7 @@ export async function pokerEloHandler(room) {
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
} else {
|
||||
console.error(`[${Date.now()}] Error calculating new Elo for ${player.globalName}.`);
|
||||
console.error(`Error calculating new Elo for ${player.globalName}.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@ import {
|
||||
pruneOldLogs,
|
||||
updateUserCoins
|
||||
} from "../database/index.js";
|
||||
import { activeSlowmodes, messagesTimestamps, skins } from "./state.js";
|
||||
import { activeSlowmodes, activeSolitaireGames, messagesTimestamps, skins } from "./state.js";
|
||||
import { createDeck, createSeededRNG, deal, seededShuffle } from "./solitaire.js";
|
||||
import { emitSolitaireUpdate } from "../server/socket.js";
|
||||
|
||||
/**
|
||||
* Handles awarding points (coins) to users for their message activity.
|
||||
@@ -88,7 +89,7 @@ export async function slowmodesHandler(message) {
|
||||
|
||||
// Check if the slowmode duration has passed
|
||||
if (now > authorSlowmode.endAt) {
|
||||
console.log(`[${Date.now()}] Slowmode for ${author.username} has expired.`);
|
||||
console.log(`Slowmode for ${author.username} has expired.`);
|
||||
delete activeSlowmodes[author.id];
|
||||
return { deleted: false, expired: true };
|
||||
}
|
||||
@@ -97,10 +98,10 @@ export async function slowmodesHandler(message) {
|
||||
if (authorSlowmode.lastMessage && now - authorSlowmode.lastMessage < 60 * 1000) {
|
||||
try {
|
||||
await message.delete();
|
||||
console.log(`[${Date.now()}] Deleted a message from slowmoded user: ${author.username}`);
|
||||
console.log(`Deleted a message from slowmoded user: ${author.username}`);
|
||||
return { deleted: true, expired: false };
|
||||
} catch (err) {
|
||||
console.error(`[${Date.now()}] Failed to delete slowmode message:`, err);
|
||||
console.error(`Failed to delete slowmode message:`, err);
|
||||
return { deleted: false, expired: false };
|
||||
}
|
||||
} else {
|
||||
@@ -144,16 +145,20 @@ export function randomSkinPrice() {
|
||||
* This function clears previous stats, awards the winner, and generates a new daily seed.
|
||||
*/
|
||||
export function initTodaysSOTD() {
|
||||
console.log(`[${Date.now()}] Initializing new Solitaire of the Day...`);
|
||||
console.log(`Initializing new Solitaire of the Day...`);
|
||||
|
||||
// 1. Award previous day's winner
|
||||
const rankings = getAllSOTDStats.all();
|
||||
if (rankings.length > 0) {
|
||||
const winnerId = rankings[0].user_id;
|
||||
const secondPlaceId = rankings[1] ? rankings[1].user_id : null;
|
||||
const thirdPlaceId = rankings[2] ? rankings[2].user_id : null;
|
||||
const winnerUser = getUser.get(winnerId);
|
||||
const secondPlaceUser = secondPlaceId ? getUser.get(secondPlaceId) : null;
|
||||
const thirdPlaceUser = thirdPlaceId ? getUser.get(thirdPlaceId) : null;
|
||||
|
||||
if (winnerUser) {
|
||||
const reward = 1000;
|
||||
const reward = 2500;
|
||||
const newCoinTotal = winnerUser.coins + reward;
|
||||
updateUserCoins.run({ id: winnerId, coins: newCoinTotal });
|
||||
insertLog.run({
|
||||
@@ -165,21 +170,40 @@ export function initTodaysSOTD() {
|
||||
user_new_amount: newCoinTotal,
|
||||
});
|
||||
console.log(
|
||||
`[${Date.now()}] ${winnerUser.globalName || winnerUser.username} won the previous SOTD and received ${reward} coins.`,
|
||||
`${winnerUser.globalName || winnerUser.username} won the previous SOTD and received ${reward} coins.`,
|
||||
);
|
||||
insertGame.run({
|
||||
id: `${winnerId}-${Date.now()}`,
|
||||
p1: winnerId,
|
||||
p2: null,
|
||||
p1_score: rankings[0].score,
|
||||
p2_score: null,
|
||||
p1_elo: winnerUser.elo,
|
||||
p2_elo: null,
|
||||
p1_new_elo: winnerUser.elo,
|
||||
p2_new_elo: null,
|
||||
type: "SOTD",
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
if (secondPlaceUser) {
|
||||
const reward = 1500;
|
||||
const newCoinTotal = secondPlaceUser.coins + reward;
|
||||
updateUserCoins.run({ id: secondPlaceId, coins: newCoinTotal });
|
||||
insertLog.run({
|
||||
id: `${secondPlaceId}-sotd-second-${Date.now()}`,
|
||||
target_user_id: null,
|
||||
user_id: secondPlaceId,
|
||||
action: "SOTD_SECOND_PLACE",
|
||||
coins_amount: reward,
|
||||
user_new_amount: newCoinTotal,
|
||||
});
|
||||
console.log(
|
||||
`${secondPlaceUser.globalName || secondPlaceUser.username} got second place in the previous SOTD and received ${reward} coins.`,
|
||||
);
|
||||
}
|
||||
if (thirdPlaceUser) {
|
||||
const reward = 750;
|
||||
const newCoinTotal = thirdPlaceUser.coins + reward;
|
||||
updateUserCoins.run({ id: thirdPlaceId, coins: newCoinTotal });
|
||||
insertLog.run({
|
||||
id: `${thirdPlaceId}-sotd-third-${Date.now()}`,
|
||||
target_user_id: null,
|
||||
user_id: thirdPlaceId,
|
||||
action: "SOTD_THIRD_PLACE",
|
||||
coins_amount: reward,
|
||||
user_new_amount: newCoinTotal,
|
||||
});
|
||||
console.log(
|
||||
`${thirdPlaceUser.globalName || thirdPlaceUser.username} got third place in the previous SOTD and received ${reward} coins.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,8 +230,15 @@ export function initTodaysSOTD() {
|
||||
wastePile: JSON.stringify(todaysSOTD.wastePile),
|
||||
seed: newRandomSeed,
|
||||
});
|
||||
console.log(`[${Date.now()}] Today's SOTD is ready with a new seed.`);
|
||||
for (const [userId, gameData] of Object.entries(activeSolitaireGames)) {
|
||||
if (gameData.isSOTD) {
|
||||
delete activeSolitaireGames[userId];
|
||||
emitSolitaireUpdate(userId);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Today's SOTD is ready with a new seed.`);
|
||||
} catch (e) {
|
||||
console.error(`[${Date.now()}] Error saving new SOTD to database:`, e);
|
||||
console.error(`Error saving new SOTD to database:`, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import { activePolls, activePredis, activeSlowmodes, skins } from "../../game/state.js";
|
||||
|
||||
// --- Utility and API Imports ---
|
||||
import { formatTime } from "../../utils/index.js";
|
||||
import { formatTime, isMeleeSkin, isVCTSkin, isChampionsSkin, getVCTRegion } from "../../utils/index.js";
|
||||
import { DiscordRequest } from "../../api/discord.js";
|
||||
|
||||
// --- Discord.js Builder Imports ---
|
||||
@@ -99,11 +99,11 @@ export function apiRoutes(client, io) {
|
||||
user_new_amount: 5000,
|
||||
});
|
||||
|
||||
console.log(`[${Date.now()}] New registered user: ${discordUser.username} (${discordUser.id})`);
|
||||
console.log(`New registered user: ${discordUser.username} (${discordUser.id})`);
|
||||
|
||||
res.status(200).json({ message: `Bienvenue ${discordUser.username} !` });
|
||||
} catch (e) {
|
||||
console.log(`[${Date.now()}] Failed to register user ${discordUser.username} (${discordUser.id})`, e);
|
||||
console.log(`Failed to register user ${discordUser.username} (${discordUser.id})`, e);
|
||||
res.status(500).json({ error: "Erreur lors de la création du nouvel utilisateur." });
|
||||
}
|
||||
});
|
||||
@@ -173,8 +173,18 @@ export function apiRoutes(client, io) {
|
||||
);
|
||||
const updatedSkin = getSkin.get(result.randomSkinData.uuid);
|
||||
await handleCaseOpening(caseType, userId, result.randomSelectedSkinUuid, client);
|
||||
|
||||
const contentSkins = selectedSkins.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
isMelee: isMeleeSkin(item.displayName),
|
||||
isVCT: isVCTSkin(item.displayName),
|
||||
isChampions: isChampionsSkin(item.displayName),
|
||||
vctRegion: getVCTRegion(item.displayName),
|
||||
}
|
||||
});
|
||||
res.json({
|
||||
selectedSkins,
|
||||
selectedSkins: contentSkins,
|
||||
randomSelectedSkinUuid: result.randomSelectedSkinUuid,
|
||||
randomSelectedSkinIndex: result.randomSelectedSkinIndex,
|
||||
updatedSkin,
|
||||
@@ -475,6 +485,10 @@ export function apiRoutes(client, io) {
|
||||
});
|
||||
});
|
||||
skin.offers = marketOffers || {};
|
||||
skin.isMelee = isMeleeSkin(skin.displayName);
|
||||
skin.isVCT = isVCTSkin(skin.displayName);
|
||||
skin.isChampions = isChampionsSkin(skin.displayName);
|
||||
skin.vctRegion = getVCTRegion(skin.displayName);
|
||||
});
|
||||
res.json({ inventory });
|
||||
} catch (error) {
|
||||
@@ -560,7 +574,7 @@ export function apiRoutes(client, io) {
|
||||
user_new_amount: newCoins,
|
||||
});
|
||||
|
||||
console.log(`[${Date.now()}] ${commandUserId} change nickname of ${userId}: ${old_nickname} -> ${nickname}`);
|
||||
console.log(`${commandUserId} change nickname of ${userId}: ${old_nickname} -> ${nickname}`);
|
||||
|
||||
try {
|
||||
const generalChannel = await guild.channels.fetch(process.env.GENERAL_CHANNEL_ID);
|
||||
@@ -1065,7 +1079,7 @@ export function apiRoutes(client, io) {
|
||||
user_new_amount: tempUser.coins + v.amount,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`[${Date.now()}] Impossible de rembourser ${v.id} (${v.amount} coins)`);
|
||||
console.log(`Impossible de rembourser ${v.id} (${v.amount} coins)`);
|
||||
}
|
||||
});
|
||||
activePredis[predi].options[1].votes.forEach((v) => {
|
||||
@@ -1084,7 +1098,7 @@ export function apiRoutes(client, io) {
|
||||
user_new_amount: tempUser.coins + v.amount,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`[${Date.now()}] Impossible de rembourser ${v.id} (${v.amount} coins)`);
|
||||
console.log(`Impossible de rembourser ${v.id} (${v.amount} coins)`);
|
||||
}
|
||||
});
|
||||
activePredis[predi].closed = true;
|
||||
@@ -1110,7 +1124,7 @@ export function apiRoutes(client, io) {
|
||||
user_new_amount: tempUser.coins + v.amount * (1 + ratio),
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`[${Date.now()}] Impossible de créditer ${v.id} (${v.amount} coins pariés, *${1 + ratio})`);
|
||||
console.log(`Impossible de créditer ${v.id} (${v.amount} coins pariés, *${1 + ratio})`);
|
||||
}
|
||||
});
|
||||
activePredis[predi].paidTime = new Date();
|
||||
|
||||
@@ -83,12 +83,12 @@ export function blackjackRoutes(io) {
|
||||
h.surrendered = true;
|
||||
h.stood = true;
|
||||
h.hasActed = true;
|
||||
room.leavingAfterRound[p.id] = true; // kick at end of round
|
||||
//room.leavingAfterRound[p.id] = true; // kick at end of round
|
||||
emitToast({ type: "player-timeout", userId: p.id });
|
||||
changed = true;
|
||||
} else if (h.hasActed && !h.stood) {
|
||||
h.stood = true;
|
||||
room.leavingAfterRound[p.id] = true; // kick at end of round
|
||||
//room.leavingAfterRound[p.id] = true; // kick at end of round
|
||||
emitToast({ type: "player-auto-stand", userId: p.id });
|
||||
changed = true;
|
||||
}
|
||||
@@ -183,7 +183,7 @@ export function blackjackRoutes(io) {
|
||||
|
||||
router.post("/leave", async (req, res) => {
|
||||
const { userId } = req.body;
|
||||
if (!userId || !room.players[userId]) return res.status(404).json({ message: "not in room" });
|
||||
if (!userId || !room.players[userId]) return res.status(403).json({ message: "not in room" });
|
||||
|
||||
try {
|
||||
const guild = await client.guilds.fetch(process.env.GUILD_ID);
|
||||
@@ -211,7 +211,7 @@ export function blackjackRoutes(io) {
|
||||
}
|
||||
|
||||
const p = room.players[userId];
|
||||
if (p.inRound) {
|
||||
if (p?.inRound) {
|
||||
// leave after round to avoid abandoning an active bet
|
||||
room.leavingAfterRound[userId] = true;
|
||||
return res.status(200).json({ message: "will-leave-after-round" });
|
||||
|
||||
@@ -446,3 +446,51 @@ function formatTierText(rank, displayName) {
|
||||
if (displayName.toLowerCase().includes("champions")) res += " | Champions";
|
||||
return res;
|
||||
}
|
||||
|
||||
export function isMeleeSkin(skinName) {
|
||||
const name = skinName.toLowerCase();
|
||||
return !(name.includes("classic") || name.includes("shorty") || name.includes("frenzy") || name.includes("ghost") || name.includes("sheriff") || name.includes("stinger") || name.includes("spectre") ||
|
||||
name.includes("bucky") || name.includes("judge") || name.includes("bulldog") || name.includes("guardian") ||
|
||||
name.includes("vandal") || name.includes("phantom") || name.includes("marshal") || name.includes("outlaw") ||
|
||||
name.includes("operator") || name.includes("ares") || name.includes("odin"));
|
||||
}
|
||||
|
||||
export function isVCTSkin(skinName) {
|
||||
const name = skinName.toLowerCase();
|
||||
return name.includes("vct");
|
||||
}
|
||||
|
||||
const VCT_TEAMS = {
|
||||
"vct-am": [
|
||||
/x 100t\)$/g, /x c9\)$/g, /x eg\)$/g, /x fur\)$/g, /x krü\)$/g, /x lev\)$/g, /x loud\)$/g,
|
||||
/x mibr\)$/g, /x sen\)$/g, /x nrg\)$/g, /x g2\)$/g, /x nv\)$/g, /x 2g\)$/g
|
||||
],
|
||||
"vct-emea": [
|
||||
/x bbl\)$/g, /x fnc\)$/g, /x fut\)$/g, /x m8\)$/g, /x gx\)$/g, /x kc\)$/g, /x navi\)$/g,
|
||||
/x th\)$/g, /x tl\)$/g, /x vit\)$/g, /x ulf\)$/g, /x pcf\)$/g, /x koi\)$/g, /x apk\)$/g
|
||||
],
|
||||
"vct-pcf": [
|
||||
/x dfm\)$/g, /x drx\)$/g, /x fs\)$/g, /x gen\)$/g, /x ge\)$/g, /x prx\)$/g, /x rrq\)$/g,
|
||||
/x t1\)$/g, /x ts\)$/g, /x zeta\)$/g, /x vl\)$/g, /x ns\)$/g, /x tln\)$/g, /x boom\)$/g, /x bld\)$/g
|
||||
],
|
||||
"vct-cn": [
|
||||
/x ag\)$/g, /x blg\)$/g, /x edg\)$/g, /x fpx\)$/g, /x jdg\)$/g, /x nova\)$/g, /x tec\)$/g,
|
||||
/x te\)$/g, /x tyl\)$/g, /x wol\)$/g, /x xlg\)$/g, /x xlg\)$/g, /x drg\)$/g, /x drg\)$/g
|
||||
]
|
||||
};
|
||||
|
||||
export function getVCTRegion(skinName) {
|
||||
if (!isVCTSkin(skinName)) return null;
|
||||
const name = skinName.toLowerCase().trim();
|
||||
for (const [region, regexes] of Object.entries(VCT_TEAMS)) {
|
||||
if (regexes.some(regex => regex.test(name))) {
|
||||
return region;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isChampionsSkin(skinName) {
|
||||
const name = skinName.toLowerCase();
|
||||
return name.includes("champions");
|
||||
}
|
||||
Reference in New Issue
Block a user