mirror of
https://github.com/cassoule/flopobot_v2.git
synced 2026-01-18 16:37:40 +01:00
CASE OPENING AND MARKETPLACE
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
import { InteractionResponseType, InteractionResponseFlags } from "discord-interactions";
|
||||
import { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
|
||||
|
||||
import { postAPOBuy } from "../../utils/index.js";
|
||||
import { InteractionResponseFlags, InteractionResponseType } from "discord-interactions";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
|
||||
import { DiscordRequest } from "../../api/discord.js";
|
||||
import { getAllAvailableSkins, getUser, insertLog, updateSkin, updateUserCoins } from "../../database/index.js";
|
||||
import { skins } from "../../game/state.js";
|
||||
@@ -14,6 +12,14 @@ import { skins } from "../../game/state.js";
|
||||
* @param {object} client - The Discord.js client instance.
|
||||
*/
|
||||
export async function handleValorantCommand(req, res, client) {
|
||||
return res.send({
|
||||
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data: {
|
||||
content: `L'ouverture de caisses Valorant en commande discord est désactivée. Tu peux aller en ouvrir sur FlopoSite.`,
|
||||
flags: InteractionResponseFlags.EPHEMERAL,
|
||||
},
|
||||
});
|
||||
|
||||
const { member, token } = req.body;
|
||||
const userId = member.user.id;
|
||||
const valoPrice = parseInt(process.env.VALO_PRICE, 10) || 500;
|
||||
@@ -125,8 +131,7 @@ export async function handleValorantCommand(req, res, client) {
|
||||
await DiscordRequest(webhookEndpoint, {
|
||||
method: "PATCH",
|
||||
body: {
|
||||
content:
|
||||
"Oups, il y a eu un petit problème lors de l'ouverture de la caisse. L'administrateur a été notifié.",
|
||||
content: "Oups, il y a eu un petit problème lors de l'ouverture de la caisse.",
|
||||
embeds: [],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -691,6 +691,12 @@ export const updateMarketOffer = flopoDB.prepare(`
|
||||
WHERE id = @id
|
||||
`);
|
||||
|
||||
export const deleteMarketOffer = flopoDB.prepare(`
|
||||
DELETE
|
||||
FROM market_offers
|
||||
WHERE id = ?
|
||||
`);
|
||||
|
||||
/* -------------------------
|
||||
BIDS
|
||||
----------------------------*/
|
||||
@@ -721,6 +727,12 @@ export const insertBid = flopoDB.prepare(`
|
||||
VALUES (@id, @bidder_id, @market_offer_id, @offer_amount)
|
||||
`);
|
||||
|
||||
export const deleteBid = flopoDB.prepare(`
|
||||
DELETE
|
||||
FROM bids
|
||||
WHERE id = ?
|
||||
`);
|
||||
|
||||
/* -------------------------
|
||||
BULK TRANSACTIONS (synchronous)
|
||||
----------------------------*/
|
||||
|
||||
@@ -4,12 +4,12 @@ import { sleep } from "openai/core";
|
||||
// --- Database Imports ---
|
||||
import {
|
||||
getAllAkhys,
|
||||
getAllAvailableSkins,
|
||||
getAllUsers,
|
||||
getLogs,
|
||||
getMarketOffersBySkin,
|
||||
getOfferBids,
|
||||
getSkin,
|
||||
getAllAvailableSkins,
|
||||
getUser,
|
||||
getUserElo,
|
||||
getUserGames,
|
||||
@@ -20,8 +20,8 @@ import {
|
||||
insertUser,
|
||||
pruneOldLogs,
|
||||
queryDailyReward,
|
||||
updateUserCoins,
|
||||
updateSkin,
|
||||
updateUserCoins,
|
||||
} from "../../database/index.js";
|
||||
|
||||
// --- Game State Imports ---
|
||||
@@ -34,6 +34,7 @@ import { DiscordRequest } from "../../api/discord.js";
|
||||
// --- Discord.js Builder Imports ---
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
|
||||
import { emitDataUpdated, socketEmit } from "../socket.js";
|
||||
import { handleCaseOpening } from "../../utils/marketNotifs.js";
|
||||
|
||||
// Create a new router instance
|
||||
const router = express.Router();
|
||||
@@ -116,12 +117,12 @@ export function apiRoutes(client, io) {
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/open-case", (req, res) => {
|
||||
router.post("/open-case", async (req, res) => {
|
||||
const { userId, caseType } = req.body;
|
||||
|
||||
let caseTypeVal, tierWeights;
|
||||
switch (caseType) {
|
||||
case "standard":
|
||||
case "standard":
|
||||
caseTypeVal = 1;
|
||||
tierWeights = {
|
||||
"12683d76-48d7-84a3-4e09-6985794f0445": 50, // Select
|
||||
@@ -129,9 +130,9 @@ export function apiRoutes(client, io) {
|
||||
"60bca009-4182-7998-dee7-b8a2558dc369": 15, // Premium
|
||||
"e046854e-406c-37f4-6607-19a9ba8426fc": 4, // Exclusive
|
||||
"411e4a55-4e59-7757-41f0-86a53f101bb5": 1, // Ultra
|
||||
}
|
||||
};
|
||||
break;
|
||||
case "premium":
|
||||
case "premium":
|
||||
caseTypeVal = 2;
|
||||
tierWeights = {
|
||||
"12683d76-48d7-84a3-4e09-6985794f0445": 35, // Select
|
||||
@@ -139,9 +140,9 @@ export function apiRoutes(client, io) {
|
||||
"60bca009-4182-7998-dee7-b8a2558dc369": 30, // Premium
|
||||
"e046854e-406c-37f4-6607-19a9ba8426fc": 4, // Exclusive
|
||||
"411e4a55-4e59-7757-41f0-86a53f101bb5": 1, // Ultra
|
||||
}
|
||||
};
|
||||
break;
|
||||
case "ultra":
|
||||
case "ultra":
|
||||
caseTypeVal = 4;
|
||||
tierWeights = {
|
||||
"12683d76-48d7-84a3-4e09-6985794f0445": 33, // Select
|
||||
@@ -149,22 +150,19 @@ export function apiRoutes(client, io) {
|
||||
"60bca009-4182-7998-dee7-b8a2558dc369": 28, // Premium
|
||||
"e046854e-406c-37f4-6607-19a9ba8426fc": 8, // Exclusive
|
||||
"411e4a55-4e59-7757-41f0-86a53f101bb5": 3, // Ultra
|
||||
}
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return res.status(400).json({ error: "Invalid case type." });
|
||||
};
|
||||
|
||||
}
|
||||
const commandUser = getUser.get(userId);
|
||||
if (!commandUser) return res.status(404).json({ error: "User not found." });
|
||||
const valoPrice = (parseInt(process.env.VALO_PRICE, 10) || 500) * caseTypeVal;
|
||||
if (commandUser.coins < valoPrice) return res.status(403).json({ error: "Not enough FlopoCoins." });
|
||||
|
||||
|
||||
try {
|
||||
const dbSkins = getAllAvailableSkins.all();
|
||||
const filteredSkins = skins.filter(
|
||||
(s) => dbSkins.find((dbSkin) => dbSkin.uuid === s.uuid),
|
||||
);
|
||||
const filteredSkins = skins.filter((s) => dbSkins.find((dbSkin) => dbSkin.uuid === s.uuid));
|
||||
filteredSkins.forEach((s) => {
|
||||
let dbSkin = getSkin.get(s.uuid);
|
||||
s.tierColor = dbSkin?.tierColor;
|
||||
@@ -252,8 +250,11 @@ export function apiRoutes(client, io) {
|
||||
currentPrice: finalPrice,
|
||||
});
|
||||
|
||||
console.log(`[${Date.now()}] ${userId} opened a Valorant case and received skin ${randomSelectedSkinUuid}`);
|
||||
console.log(
|
||||
`[${Date.now()}] ${userId} opened a ${caseType} Valorant case and received skin ${randomSelectedSkinUuid}`,
|
||||
);
|
||||
const updatedSkin = getSkin.get(randomSkinData.uuid);
|
||||
await handleCaseOpening(caseType, userId, randomSelectedSkinUuid, client);
|
||||
res.json({ selectedSkins, randomSelectedSkinUuid, randomSelectedSkinIndex, updatedSkin });
|
||||
} catch (error) {
|
||||
console.error("Error fetching skins:", error);
|
||||
@@ -343,6 +344,15 @@ export function apiRoutes(client, io) {
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/user/:id/coins", async (req, res) => {
|
||||
try {
|
||||
const user = getUser.get(req.params.id);
|
||||
res.json({ coins: user.coins });
|
||||
} catch (error) {
|
||||
res.status(404).json({ error: "User not found." });
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/user/:id/sparkline", (req, res) => {
|
||||
try {
|
||||
const logs = getUserLogs.all({ user_id: req.params.id });
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ButtonStyle } from "discord.js";
|
||||
import {
|
||||
getMarketOfferById,
|
||||
getMarketOffers,
|
||||
getMarketOffersBySkin,
|
||||
getOfferBids,
|
||||
getSkin,
|
||||
getUser,
|
||||
@@ -17,6 +18,7 @@ import {
|
||||
updateUserCoins,
|
||||
} from "../../database/index.js";
|
||||
import { emitMarketUpdate } from "../socket.js";
|
||||
import { handleNewMarketOffer, handleNewMarketOfferBid } from "../../utils/marketNotifs.js";
|
||||
|
||||
// Create a new router instance
|
||||
const router = express.Router();
|
||||
@@ -78,11 +80,20 @@ export function marketRoutes(client, io) {
|
||||
if (!seller) return res.status(404).send({ error: "Seller not found" });
|
||||
if (skin.user_id !== seller.id) return res.status(403).send({ error: "You do not own this skin" });
|
||||
|
||||
const existingOffers = getMarketOffersBySkin.all(skin.uuid);
|
||||
if (
|
||||
existingOffers.length > 0 &&
|
||||
existingOffers.some((offer) => offer.status === "open" || offer.status === "pending")
|
||||
) {
|
||||
return res.status(403).send({ error: "This skin already has an open or pending offer." });
|
||||
}
|
||||
|
||||
const opening_at = now + delay;
|
||||
const closing_at = opening_at + duration;
|
||||
|
||||
const offerId = Date.now() + "-" + seller.id + "-" + skin.uuid;
|
||||
insertMarketOffer.run({
|
||||
id: Date.now() + '-' + seller.id + '-' + skin.uuid,
|
||||
id: offerId,
|
||||
skin_uuid: skin.uuid,
|
||||
seller_id: seller.id,
|
||||
starting_price: starting_price,
|
||||
@@ -91,12 +102,11 @@ export function marketRoutes(client, io) {
|
||||
opening_at: opening_at,
|
||||
closing_at: closing_at,
|
||||
});
|
||||
// Placeholder for placing an offer logic
|
||||
// Extract data from req.body and process accordingly
|
||||
await emitMarketUpdate();
|
||||
await handleNewMarketOffer(offerId, client);
|
||||
res.status(200).send({ message: "Offre créée avec succès" });
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
console.log(e);
|
||||
return res.status(500).send({ error: e });
|
||||
}
|
||||
});
|
||||
@@ -130,8 +140,9 @@ export function marketRoutes(client, io) {
|
||||
if (bidder.coins < bid_amount)
|
||||
return res.status(403).send({ error: "You do not have enough coins to place this bid" });
|
||||
|
||||
const bidId = Date.now() + "-" + buyer_id + "-" + offer.id;
|
||||
insertBid.run({
|
||||
id: Date.now(),
|
||||
id: bidId,
|
||||
bidder_id: buyer_id,
|
||||
market_offer_id: offer.id,
|
||||
offer_amount: bid_amount,
|
||||
@@ -162,6 +173,7 @@ export function marketRoutes(client, io) {
|
||||
});
|
||||
}
|
||||
|
||||
await handleNewMarketOfferBid(offer.id, bidId, client);
|
||||
await emitMarketUpdate();
|
||||
res.status(200).send({ error: "Bid placed successfully" });
|
||||
} catch (e) {
|
||||
|
||||
@@ -6,6 +6,8 @@ import { getSkinTiers, getValorantSkins } from "../api/valorant.js";
|
||||
import { DiscordRequest } from "../api/discord.js";
|
||||
import { initTodaysSOTD } from "../game/points.js";
|
||||
import {
|
||||
deleteBid,
|
||||
deleteMarketOffer,
|
||||
getAllAkhys,
|
||||
getAllUsers,
|
||||
getMarketOffers,
|
||||
@@ -22,6 +24,8 @@ import {
|
||||
} from "../database/index.js";
|
||||
import { activeInventories, activePredis, activeSearchs, pokerRooms, skins } from "../game/state.js";
|
||||
import { emitMarketUpdate } from "../server/socket.js";
|
||||
import { handleMarketOfferClosing, handleMarketOfferOpening } from "./marketNotifs.js";
|
||||
import { client } from "../bot/client.js";
|
||||
|
||||
export async function InstallGlobalCommands(appId, commands) {
|
||||
// API endpoint to overwrite global commands
|
||||
@@ -121,7 +125,6 @@ export async function getAkhys(client) {
|
||||
export function setupCronJobs(client, io) {
|
||||
// Every 5 minutes: Update market offers
|
||||
cron.schedule("* * * * *", () => {
|
||||
console.log("[Cron] Checking market offers for updates...");
|
||||
handleMarketOffersUpdate();
|
||||
});
|
||||
|
||||
@@ -180,6 +183,23 @@ export function setupCronJobs(client, io) {
|
||||
} catch (e) {
|
||||
console.error("[Cron] Error during daily reset:", e);
|
||||
}
|
||||
try {
|
||||
const offers = getMarketOffers.all();
|
||||
const now = Date.now();
|
||||
const TWO_DAYS = 2 * 24 * 60 * 60 * 1000;
|
||||
for (const offer of offers) {
|
||||
if (now >= offer.closing_at + TWO_DAYS) {
|
||||
const offerBids = getOfferBids.all(offer.id);
|
||||
for (const bid of offerBids) {
|
||||
deleteBid.run(bid.id);
|
||||
}
|
||||
deleteMarketOffer.run(offer.id);
|
||||
console.log(`[Cron] Deleted expired market offer ID: ${offer.id}`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("[Cron] Error during Market Offers clean up:", e);
|
||||
}
|
||||
});
|
||||
|
||||
// Daily at 7 AM: Re-sync users and skins
|
||||
@@ -262,7 +282,7 @@ function handleMarketOffersUpdate() {
|
||||
offers.forEach(async (offer) => {
|
||||
if (now >= offer.opening_at && offer.status === "pending") {
|
||||
updateMarketOffer.run({ id: offer.id, final_price: null, buyer_id: null, status: "open" });
|
||||
//TODO: Maybe notify seller that their offer is now open
|
||||
await handleMarketOfferOpening(offer.id, client);
|
||||
await emitMarketUpdate();
|
||||
}
|
||||
if (now >= offer.closing_at && offer.status !== "closed") {
|
||||
@@ -301,13 +321,12 @@ function handleMarketOffersUpdate() {
|
||||
});
|
||||
const newUserCoins = seller.coins + lastBid.offer_amount;
|
||||
updateUserCoins.run({ id: seller.id, coins: newUserCoins });
|
||||
//TODO: Notify users in DMs
|
||||
await emitMarketUpdate();
|
||||
} catch (e) {
|
||||
console.error(`[Market Cron] Error processing offer ID: ${offer.id}`, e);
|
||||
}
|
||||
}
|
||||
|
||||
await handleMarketOfferClosing(offer.id, client);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
401
src/utils/marketNotifs.js
Normal file
401
src/utils/marketNotifs.js
Normal file
@@ -0,0 +1,401 @@
|
||||
import { getMarketOfferById, getOfferBids, getSkin, getUser } from "../database/index.js";
|
||||
import { EmbedBuilder } from "discord.js";
|
||||
|
||||
export async function handleNewMarketOffer(offerId, client) {
|
||||
const offer = getMarketOfferById.get(offerId);
|
||||
if (!offer) return;
|
||||
const skin = getSkin.get(offer.skin_uuid);
|
||||
|
||||
const discordUserSeller = await client.users.fetch(offer.seller_id);
|
||||
try {
|
||||
const userSeller = getUser.get(offer.seller_id);
|
||||
if (discordUserSeller && userSeller?.isAkhy) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Offre créée")
|
||||
.setDescription(`Ton offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** a bien été créée !`)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.addFields(
|
||||
{
|
||||
name: "📌 Statut",
|
||||
value: `\`${offer.status}\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "💰 Prix de départ",
|
||||
value: `\`${offer.starting_price} coins\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Ouverture",
|
||||
value: `<t:${Math.floor(offer.opening_at / 1000)}:F>`,
|
||||
},
|
||||
{
|
||||
name: "⏰ Fermeture",
|
||||
value: `<t:${Math.floor(offer.closing_at / 1000)}:F>`,
|
||||
},
|
||||
{
|
||||
name: "🆔 ID de l’offre",
|
||||
value: `\`${offer.id}\``,
|
||||
inline: false,
|
||||
},
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
discordUserSeller.send({ embeds: [embed] }).catch(console.error);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
// Send notification in guild channel
|
||||
|
||||
try {
|
||||
const guildChannel = await client.channels.fetch(process.env.BOT_CHANNEL_ID);
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Nouvelle offre")
|
||||
.setDescription(`Une offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** a été créée !`)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.addFields(
|
||||
{
|
||||
name: "💰 Prix de départ",
|
||||
value: `\`${offer.starting_price} coins\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Ouverture",
|
||||
value: `<t:${Math.floor(offer.opening_at / 1000)}:F>`,
|
||||
},
|
||||
{
|
||||
name: "⏰ Fermeture",
|
||||
value: `<t:${Math.floor(offer.closing_at / 1000)}:F>`,
|
||||
},
|
||||
{
|
||||
name: "Créée par",
|
||||
value: `<@${offer.seller_id}> ${discordUserSeller ? "(" + discordUserSeller.username + ")" : ""}`,
|
||||
},
|
||||
)
|
||||
.setTimestamp();
|
||||
guildChannel.send({ embeds: [embed] }).catch(console.error);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleMarketOfferOpening(offerId, client) {
|
||||
const offer = getMarketOfferById.get(offerId);
|
||||
if (!offer) return;
|
||||
const skin = getSkin.get(offer.skin_uuid);
|
||||
|
||||
try {
|
||||
const discordUserSeller = await client.users.fetch(offer.seller_id);
|
||||
const userSeller = getUser.get(offer.seller_id);
|
||||
if (discordUserSeller && userSeller?.isAkhy) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Début des enchères")
|
||||
.setDescription(
|
||||
`Les enchères sur ton offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** viennent de commencer !`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.addFields(
|
||||
{
|
||||
name: "📌 Statut",
|
||||
value: `\`${offer.status}\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "💰 Prix de départ",
|
||||
value: `\`${offer.starting_price} coins\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Fermeture",
|
||||
value: `<t:${Math.floor(offer.closing_at / 1000)}:F>`,
|
||||
},
|
||||
{
|
||||
name: "🆔 ID de l’offre",
|
||||
value: `\`${offer.id}\``,
|
||||
inline: false,
|
||||
},
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
discordUserSeller.send({ embeds: [embed] }).catch(console.error);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
// Send notification in guild channel
|
||||
|
||||
try {
|
||||
const guildChannel = await client.channels.fetch(process.env.BOT_CHANNEL_ID);
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Début des enchères")
|
||||
.setDescription(
|
||||
`Les enchères sur l'offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** viennent de commencer !`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.addFields(
|
||||
{
|
||||
name: "💰 Prix de départ",
|
||||
value: `\`${offer.starting_price} coins\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Fermeture",
|
||||
value: `<t:${Math.floor(offer.closing_at / 1000)}:F>`,
|
||||
},
|
||||
)
|
||||
.setTimestamp();
|
||||
guildChannel.send({ embeds: [embed] }).catch(console.error);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleMarketOfferClosing(offerId, client) {
|
||||
const offer = getMarketOfferById.get(offerId);
|
||||
if (!offer) return;
|
||||
const skin = getSkin.get(offer.skin_uuid);
|
||||
const bids = getOfferBids.all(offer.id);
|
||||
|
||||
const discordUserSeller = await client.users.fetch(offer.seller_id);
|
||||
try {
|
||||
const userSeller = getUser.get(offer.seller_id);
|
||||
if (discordUserSeller && userSeller?.isAkhy) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Fin des enchères")
|
||||
.setDescription(
|
||||
`Les enchères sur ton offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** viennent de se terminer !`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.setTimestamp();
|
||||
|
||||
if (bids.length === 0) {
|
||||
embed.addFields(
|
||||
{
|
||||
name: "❌ Aucune enchère n'a été placée sur cette offre.",
|
||||
value: "Tu conserves ce skin dans ton inventaire.",
|
||||
},
|
||||
{
|
||||
name: "🆔 ID de l’offre",
|
||||
value: `\`${offer.id}\``,
|
||||
inline: false,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
const highestBid = bids[0];
|
||||
const highestBidderUser = await client.users.fetch(highestBid.bidder_id);
|
||||
embed.addFields(
|
||||
{
|
||||
name: "✅ Enchères terminées avec succès !",
|
||||
value: `Ton skin a été vendu pour \`${highestBid.offer_amount} coins\` à <@${highestBid.bidder_id}> ${highestBidderUser ? "(" + highestBidderUser.username + ")" : ""}.`,
|
||||
},
|
||||
{
|
||||
name: "🆔 ID de l’offre",
|
||||
value: `\`${offer.id}\``,
|
||||
inline: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
discordUserSeller.send({ embeds: [embed] }).catch(console.error);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
// Send notification in guild channel
|
||||
|
||||
try {
|
||||
const guildChannel = await client.channels.fetch(process.env.BOT_CHANNEL_ID);
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Fin des enchères")
|
||||
.setDescription(
|
||||
`Les enchères sur l'offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** viennent de se terminer !`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.setTimestamp();
|
||||
|
||||
if (bids.length === 0) {
|
||||
embed.addFields({
|
||||
name: "❌ Aucune enchère n'a été placée sur cette offre.",
|
||||
value: "",
|
||||
});
|
||||
} else {
|
||||
const highestBid = bids[0];
|
||||
const highestBidderUser = await client.users.fetch(highestBid.bidder_id);
|
||||
embed.addFields({
|
||||
name: "✅ Enchères terminées avec succès !",
|
||||
value: `Le skin de <@${offer.seller_id}> ${discordUserSeller ? "(" + discordUserSeller.username + ")" : ""} a été vendu pour \`${highestBid.offer_amount} coins\` à <@${highestBid.bidder_id}> ${highestBidderUser ? "(" + highestBidderUser.username + ")" : ""}.`,
|
||||
});
|
||||
const discordUserBidder = await client.users.fetch(highestBid.bidder_id);
|
||||
const userBidder = getUser.get(highestBid.bidder_id);
|
||||
if (discordUserBidder && userBidder?.isAkhy) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Fin des enchères")
|
||||
.setDescription(
|
||||
`Les enchères sur l'offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** viennent de se terminer !`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.setTimestamp();
|
||||
const highestBid = bids[0];
|
||||
embed.addFields({
|
||||
name: "✅ Enchères terminées avec succès !",
|
||||
value: `Tu as acheté ce skin pour \`${highestBid.offer_amount} coins\` à <@${offer.seller_id}> ${discordUserSeller ? "(" + discordUserSeller.username + ")" : ""}. Il a été ajouté à ton inventaire.`,
|
||||
});
|
||||
|
||||
discordUserBidder.send({ embeds: [embed] }).catch(console.error);
|
||||
}
|
||||
}
|
||||
guildChannel.send({ embeds: [embed] }).catch(console.error);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleNewMarketOfferBid(offerId, bidId, client) {
|
||||
// Notify Seller and Bidder
|
||||
const offer = getMarketOfferById.get(offerId);
|
||||
if (!offer) return;
|
||||
const bid = getOfferBids.get(offerId);
|
||||
if (!bid) return;
|
||||
const skin = getSkin.get(offer.skin_uuid);
|
||||
|
||||
const bidderUser = client.users.fetch(bid.bidder_id);
|
||||
try {
|
||||
const discordUserSeller = await client.users.fetch(offer.seller_id);
|
||||
const userSeller = getUser.get(offer.seller_id);
|
||||
|
||||
if (discordUserSeller && userSeller?.isAkhy) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Nouvelle enchère")
|
||||
.setDescription(
|
||||
`Il y a eu une nouvelle enchère sur ton offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}**.`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.addFields(
|
||||
{
|
||||
name: "👤 Enchérisseur",
|
||||
value: `<@${bid.bidder_id}> ${bidderUser ? "(" + bidderUser.username + ")" : ""}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "💰 Montant de l’enchère",
|
||||
value: `\`${bid.offer_amount} coins\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Fermeture",
|
||||
value: `<t:${Math.floor(offer.closing_at / 1000)}:F>`,
|
||||
},
|
||||
{
|
||||
name: "🆔 ID de l’offre",
|
||||
value: `\`${offer.id}\``,
|
||||
inline: false,
|
||||
},
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
discordUserSeller.send({ embeds: [embed] }).catch(console.error);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Erreur lors de la notification du vendeur : ${e}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const discordUserNewBidder = await client.users.fetch(bid.bidder_id);
|
||||
const userNewBidder = getUser.get(bid.bidder_id);
|
||||
if (discordUserNewBidder && userNewBidder?.isAkhy) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Nouvelle enchère")
|
||||
.setDescription(
|
||||
`Ton enchère sur l'offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}** a bien été placée!`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.addFields({
|
||||
name: "💰 Montant de l’enchère",
|
||||
value: `\`${bid.offer_amount} coins\``,
|
||||
inline: true,
|
||||
})
|
||||
.setTimestamp();
|
||||
|
||||
discordUserNewBidder.send({ embeds: [embed] }).catch(console.error);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Erreur lors de la notification de l'enchérriseur : ${e}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const offerBids = getOfferBids.all(offer.id);
|
||||
if (offerBids.length < 2) return; // No previous bidder to notify
|
||||
|
||||
const discordUserPreviousBidder = await client.users.fetch(offerBids[1].bidder_id);
|
||||
const userPreviousBidder = getUser.get(offerBids[1].bidder_id);
|
||||
if (discordUserPreviousBidder && userPreviousBidder?.isAkhy) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Nouvelle enchère")
|
||||
.setDescription(
|
||||
`Quelqu'un a surenchéri sur l'offre pour le skin **${skin ? skin.displayName : offer.skin_uuid}**, tu n'es plus le meilleur enchérisseur !`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(0x5865f2) // Discord blurple
|
||||
.addFields(
|
||||
{
|
||||
name: "👤 Enchérisseur",
|
||||
value: `<@${bid.bidder_id}> ${bidderUser ? "(" + bidderUser.username + ")" : ""}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "💰 Montant de l’enchère",
|
||||
value: `\`${bid.offer_amount} coins\``,
|
||||
inline: true,
|
||||
},
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
discordUserPreviousBidder.send({ embeds: [embed] }).catch(console.error);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
// Notify previous highest bidder
|
||||
}
|
||||
|
||||
export async function handleCaseOpening(caseType, userId, skinUuid, client) {
|
||||
const discordUser = await client.users.fetch(userId);
|
||||
const skin = getSkin.get(skinUuid);
|
||||
try {
|
||||
const guildChannel = await client.channels.fetch(process.env.BOT_CHANNEL_ID);
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("🔔 Ouverture de caisse")
|
||||
.setDescription(
|
||||
`${discordUser ? discordUser.username : "Un utilisateur"} vient d'ouvrir une caisse **${caseType}** et a obtenu le skin **${skin.displayName}** !`,
|
||||
)
|
||||
.setThumbnail(skin.displayIcon)
|
||||
.setColor(skin.tierColor) // Discord blurple
|
||||
.addFields(
|
||||
{
|
||||
name: "💰 Valeur estimée",
|
||||
value: `\`${skin.currentPrice} coins\``,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Level",
|
||||
value: `${skin.currentLvl}`,
|
||||
},
|
||||
)
|
||||
.setTimestamp();
|
||||
guildChannel.send({ embeds: [embed] }).catch(console.error);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user