From 237d14c7559a5ef9f768402a00a492109b7acfc2 Mon Sep 17 00:00:00 2001 From: Milo Date: Sat, 8 Nov 2025 00:29:28 +0100 Subject: [PATCH 1/4] tiny market offers update --- src/database/index.js | 19 +++++-------------- src/server/routes/market.js | 7 ++++++- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/database/index.js b/src/database/index.js index 04c5e3b..e69a4c0 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -137,17 +137,8 @@ export const stmtBids = flopoDB.prepare(` stmtBids.run(); export const getMarketOffers = flopoDB.prepare(` - SELECT market_offers.*, - skins.displayName AS skinName, - skins.displayIcon AS skinIcon, - seller.username AS sellerName, - seller.globalName AS sellerGlobalName, - buyer.username AS buyerName, - buyer.globalName AS buyerGlobalName + SELECT * FROM market_offers - JOIN skins ON skins.uuid = market_offers.skin_uuid - JOIN users AS seller ON seller.id = market_offers.seller_id - LEFT JOIN users AS buyer ON buyer.id = market_offers.buyer_id ORDER BY market_offers.posted_at DESC `); @@ -332,14 +323,14 @@ export const stmtSOTDStats = flopoDB.prepare(` stmtSOTDStats.run(); export const getAllSOTDStats = flopoDB.prepare(`SELECT sotd_stats.*, users.globalName - FROM sotd_stats - JOIN users ON users.id = sotd_stats.user_id - ORDER BY score DESC, moves ASC, time ASC`); + FROM sotd_stats + JOIN users ON users.id = sotd_stats.user_id + ORDER BY score DESC, moves ASC, time ASC`); export const getUserSOTDStats = flopoDB.prepare(`SELECT * FROM sotd_stats WHERE user_id = ?`); export const insertSOTDStats = flopoDB.prepare(`INSERT INTO sotd_stats (id, user_id, time, moves, score) - VALUES (@id, @user_id, @time, @moves, @score)`); + VALUES (@id, @user_id, @time, @moves, @score)`); export const clearSOTDStats = flopoDB.prepare(`DELETE FROM sotd_stats`); export const deleteUserSOTDStats = flopoDB.prepare(`DELETE diff --git a/src/server/routes/market.js b/src/server/routes/market.js index 8b55d30..40747e7 100644 --- a/src/server/routes/market.js +++ b/src/server/routes/market.js @@ -5,7 +5,7 @@ import express from "express"; // --- Utility and API Imports --- // --- Discord.js Builder Imports --- import { ButtonStyle } from "discord.js"; -import { getMarketOfferById, getMarketOffers, getOfferBids } from "../../database/index.js"; +import { getMarketOfferById, getMarketOffers, getOfferBids, getSkin, getUser } from "../../database/index.js"; // Create a new router instance const router = express.Router(); @@ -20,6 +20,11 @@ export function marketRoutes(client, io) { router.get("/offers", async (req, res) => { try { const offers = getMarketOffers.all(); + offers.forEach((offer) => { + offer.skin = getSkin.get(offer.skin_uuid); + offer.seller = getUser.get(offer.seller_id); + offer.buyer = getUser.get(offer.buyer_id) || null; + }); res.status(200).send({ offers }); } catch (e) { res.status(500).send({ error: e }); From 0e690aebfc0cdaff7fa75a313e0815b0d9d8dec2 Mon Sep 17 00:00:00 2001 From: Milo Date: Sat, 8 Nov 2025 11:05:27 +0100 Subject: [PATCH 2/4] logs tiny fix --- src/bot/handlers/messageCreate.js | 23 +++++++++++------------ src/database/index.js | 5 +++-- src/game/points.js | 19 +++++++++++-------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/bot/handlers/messageCreate.js b/src/bot/handlers/messageCreate.js index cba5b46..595e72f 100644 --- a/src/bot/handlers/messageCreate.js +++ b/src/bot/handlers/messageCreate.js @@ -10,24 +10,23 @@ import { stripMentionsOfBot, } from "../../utils/ai.js"; import { - formatTime, - postAPOBuy, - getAPOUsers, - getAkhys, calculateBasePrice, calculateMaxPrice, + formatTime, + getAkhys, + getAPOUsers, + postAPOBuy, } from "../../utils/index.js"; -import { channelPointsHandler, slowmodesHandler, randomSkinPrice, initTodaysSOTD } from "../../game/points.js"; -import { requestTimestamps, activeSlowmodes, activePolls, skins, activeSolitaireGames } from "../../game/state.js"; +import { channelPointsHandler, initTodaysSOTD, randomSkinPrice, slowmodesHandler } from "../../game/points.js"; +import { activePolls, activeSlowmodes, requestTimestamps, skins } from "../../game/state.js"; import { flopoDB, - getUser, - getAllUsers, - updateManyUsers, - insertUser, - updateUserAvatar, getAllSkins, + getAllUsers, + getUser, hardUpdateSkin, + updateManyUsers, + updateUserAvatar, } from "../../database/index.js"; import { client } from "../client.js"; import { autoSolveMoves } from "../../game/solitaire.js"; @@ -57,7 +56,7 @@ export async function handleMessageCreate(message, client, io) { // --- Main Guild Features (Points & Slowmode) --- if (message.guildId === process.env.GUILD_ID) { // Award points for activity - const pointsAwarded = await channelPointsHandler(message); + const pointsAwarded = channelPointsHandler(message); if (pointsAwarded) { io.emit("data-updated", { table: "users", action: "update" }); } diff --git a/src/database/index.js b/src/database/index.js index e69a4c0..9121633 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -225,7 +225,8 @@ export const stmtLogs = flopoDB.prepare(` action TEXT, target_user_id TEXT REFERENCES users, coins_amount INTEGER, - user_new_amount INTEGER + user_new_amount INTEGER, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) `); stmtLogs.run(); @@ -358,7 +359,7 @@ export async function pruneOldLogs() { FROM logs WHERE id IN (SELECT id FROM (SELECT id, - ROW_NUMBER() OVER (ORDER BY id DESC) AS rn + ROW_NUMBER() OVER (ORDER BY created_at DESC) AS rn FROM logs WHERE user_id = ?) WHERE rn > ${process.env.LOGS_BY_USER}) diff --git a/src/game/points.js b/src/game/points.js index 69b59cc..d5a4493 100644 --- a/src/game/points.js +++ b/src/game/points.js @@ -1,16 +1,17 @@ import { - getUser, - updateUserCoins, - insertLog, - getAllSkins, - insertSOTD, clearSOTDStats, - getAllSOTDStats, deleteSOTD, + getAllSkins, + getAllSOTDStats, + getUser, insertGame, + insertLog, + insertSOTD, + pruneOldLogs, + updateUserCoins } from "../database/index.js"; -import { messagesTimestamps, activeSlowmodes, skins } from "./state.js"; -import { deal, createSeededRNG, seededShuffle, createDeck } from "./solitaire.js"; +import { activeSlowmodes, messagesTimestamps, skins } from "./state.js"; +import { createDeck, createSeededRNG, deal, seededShuffle } from "./solitaire.js"; /** * Handles awarding points (coins) to users for their message activity. @@ -65,6 +66,8 @@ export async function channelPointsHandler(message) { user_new_amount: newCoinTotal, }); + await pruneOldLogs(); + return true; // Indicate that points were awarded } From 8672c90fe2b80bf5e95cea0feaaa6fdf2cd5623c Mon Sep 17 00:00:00 2001 From: Milo Date: Mon, 10 Nov 2025 01:28:24 +0100 Subject: [PATCH 3/4] market offer route data change --- src/server/routes/market.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/server/routes/market.js b/src/server/routes/market.js index 40747e7..2bd2090 100644 --- a/src/server/routes/market.js +++ b/src/server/routes/market.js @@ -24,6 +24,10 @@ export function marketRoutes(client, io) { offer.skin = getSkin.get(offer.skin_uuid); offer.seller = getUser.get(offer.seller_id); offer.buyer = getUser.get(offer.buyer_id) || null; + offer.bids = getOfferBids.all(offer.id) || {}; + offer.bids.forEach((bid) => { + bid.bidder = getUser.get(bid.bidder_id); + }); }); res.status(200).send({ offers }); } catch (e) { From 789f7cadb77d631409b172777c72295f65f1ac85 Mon Sep 17 00:00:00 2001 From: Milo Date: Mon, 24 Nov 2025 10:17:01 +0100 Subject: [PATCH 4/4] feat: market place foundations --- src/database/index.js | 15 +++++++++++++++ src/server/routes/api.js | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/database/index.js b/src/database/index.js index 9121633..2bbe183 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -157,6 +157,21 @@ export const getMarketOfferById = flopoDB.prepare(` WHERE market_offers.id = ? `); +export const getMarketOffersBySkin = flopoDB.prepare(` + SELECT market_offers.*, + skins.displayName AS skinName, + skins.displayIcon AS skinIcon, + seller.username AS sellerName, + seller.globalName AS sellerGlobalName, + buyer.username AS buyerName, + buyer.globalName AS buyerGlobalName + FROM market_offers + JOIN skins ON skins.uuid = market_offers.skin_uuid + JOIN users AS seller ON seller.id = market_offers.seller_id + LEFT JOIN users AS buyer ON buyer.id = market_offers.buyer_id + WHERE market_offers.skin_uuid = ? +`); + export const insertMarketOffer = flopoDB.prepare(` INSERT INTO market_offers (id, skin_uuid, seller_id, starting_price, buyout_price, status, opening_at, closing_at) VALUES (@id, @skin_uuid, @seller_id, @starting_price, @buyout_price, @status, @opening_at, @closing_at) diff --git a/src/server/routes/api.js b/src/server/routes/api.js index f18b33d..a91e003 100644 --- a/src/server/routes/api.js +++ b/src/server/routes/api.js @@ -6,6 +6,9 @@ import { getAllAkhys, getAllUsers, getLogs, + getMarketOffersBySkin, + getOfferBids, + getSkin, getUser, getUserElo, getUserGames, @@ -219,6 +222,19 @@ export function apiRoutes(client, io) { router.get("/user/:id/inventory", (req, res) => { try { const inventory = getUserInventory.all({ user_id: req.params.id }); + inventory.forEach((skin) => { + const marketOffers = getMarketOffersBySkin.all(skin.uuid); + marketOffers.forEach((offer) => { + offer.skin = getSkin.get(offer.skin_uuid); + offer.seller = getUser.get(offer.seller_id); + offer.buyer = getUser.get(offer.buyer_id) || null; + offer.bids = getOfferBids.all(offer.id) || {}; + offer.bids.forEach((bid) => { + bid.bidder = getUser.get(bid.bidder_id); + }); + }); + skin.offers = marketOffers || {}; + }); res.json({ inventory }); } catch (error) { res.status(500).json({ error: "Failed to fetch inventory." });