Trade: Properly handle trade cancellation and timeouts
- Trade finishing states are now handled properly. - Deferring cancel button press - A user is on a 2 minute cooldown after a trade finishes or cancels if he is the one who initiated it. - Updated emote IDs
This commit is contained in:
@@ -3,7 +3,9 @@ const { Card, User, Character } = require("../models");
|
|||||||
const { UserUtils, CardUtils } = require("../util");
|
const { UserUtils, CardUtils } = require("../util");
|
||||||
const { TradeStore } = require("../stores");
|
const { TradeStore } = require("../stores");
|
||||||
|
|
||||||
const tradeTimeout = 90000;
|
const tradeExpiry = 920000; //When an active trade expires automatically
|
||||||
|
const tradeTimeout = 120000; //Time until user can start a new trade
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName("trade")
|
.setName("trade")
|
||||||
@@ -44,6 +46,10 @@ module.exports = {
|
|||||||
switch (interaction.options.getSubcommand()) {
|
switch (interaction.options.getSubcommand()) {
|
||||||
case "start":
|
case "start":
|
||||||
let user2 = await UserUtils.getUserByDiscordId(interaction.options.getUser("user").id);
|
let user2 = await UserUtils.getUserByDiscordId(interaction.options.getUser("user").id);
|
||||||
|
if (!user2) {
|
||||||
|
await interaction.editReply({ content: "You can't trade with an unregistered user!" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
//Attach usernames for convenience
|
//Attach usernames for convenience
|
||||||
user2.name = interaction.options.getUser("user").username;
|
user2.name = interaction.options.getUser("user").username;
|
||||||
user1.name = interaction.member.user.username;
|
user1.name = interaction.member.user.username;
|
||||||
@@ -72,6 +78,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async startTrade(interaction, user1, user2) {
|
async startTrade(interaction, user1, user2) {
|
||||||
|
//user1 is the user who started the trade, user2 is the user who is being traded with
|
||||||
if (!user2) {
|
if (!user2) {
|
||||||
await interaction.editReply({ content: "This User is not registered yet!" });
|
await interaction.editReply({ content: "This User is not registered yet!" });
|
||||||
return;
|
return;
|
||||||
@@ -80,12 +87,22 @@ module.exports = {
|
|||||||
await interaction.editReply({ content: "You can't trade with yourself!" });
|
await interaction.editReply({ content: "You can't trade with yourself!" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (await TradeStore.getTradeByUser(user1.id)) {
|
|
||||||
|
let user1Trade = await TradeStore.getTradeByUser(user1.id);
|
||||||
|
if (user1Trade) {
|
||||||
|
if (user1Trade.state <= 1) {
|
||||||
await interaction.editReply({ content: "You are already in a Trade!" });
|
await interaction.editReply({ content: "You are already in a Trade!" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (await TradeStore.getTradeByUser(user2.id)) {
|
//If the initiating user still has a finished or cancelled trade in store, he's on a timeout
|
||||||
await interaction.editReply({ content: "This User is already in a Trade!" });
|
if (user1Trade.state >= 2 && user1Trade.user1.id === user1.id) {
|
||||||
|
await interaction.editReply({ content: `You need to wait ${tradeTimeout / 1000 / 60 } minutes before staring a new trade` });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let user2Trade = await TradeStore.getTradeByUser(user2.id);
|
||||||
|
if (user2Trade) {
|
||||||
|
await interaction.editReply({ content: `This User is ${(user2Trade.state <= 1 ) ? "already in a trade" : "on cooldown!" }` });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let trade = new TradeStore.Trade(CardUtils.generateIdentifier(), user1, user2);
|
let trade = new TradeStore.Trade(CardUtils.generateIdentifier(), user1, user2);
|
||||||
@@ -176,9 +193,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trade.embed = reply;
|
trade.embed = reply;
|
||||||
if (trade.cancelled || trade.expired) {
|
|
||||||
await TradeStore.removeTrade(trade);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
addComponentsToRow(row, trade) {
|
addComponentsToRow(row, trade) {
|
||||||
@@ -232,13 +246,36 @@ module.exports = {
|
|||||||
.setDisabled(true)
|
.setDisabled(true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if trade is cancelled, add a button to finalize it
|
||||||
|
if (trade.state === TradeStore.States.CANCELLED) {
|
||||||
|
row.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId(`trade-cancelled-${trade.id}`)
|
||||||
|
.setLabel('Cancelled')
|
||||||
|
.setStyle(ButtonStyle.Danger)
|
||||||
|
.setDisabled(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if trade is expired, add a button to finalize it
|
||||||
|
if (trade.state === TradeStore.States.EXPIRED) {
|
||||||
|
row.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId(`trade-expired-${trade.id}`)
|
||||||
|
.setLabel(`Expired after ${tradeExpiry / 1000 / 60} minutes`)
|
||||||
|
.setStyle(ButtonStyle.Danger)
|
||||||
|
.setDisabled(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
},
|
},
|
||||||
|
|
||||||
async attachCollectors(trade, reply, interaction) {
|
async attachCollectors(trade, reply, interaction) {
|
||||||
//button collector
|
//button collector
|
||||||
const filter = (button) => button.user.id === trade.user1.discordId || button.user.id === trade.user2.discordId;
|
const filter = (button) => button.user.id === trade.user1.discordId || button.user.id === trade.user2.discordId;
|
||||||
const collector = reply.createMessageComponentCollector({ filter, time: tradeTimeout });
|
const collector = reply.createMessageComponentCollector({ filter, time: tradeExpiry });
|
||||||
|
|
||||||
collector.on('collect', async (button) => {
|
collector.on('collect', async (button) => {
|
||||||
//if interaction member is neither user1 nor user2, ignore
|
//if interaction member is neither user1 nor user2, ignore
|
||||||
@@ -247,6 +284,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (button.customId === `cancel-trade-${trade.id}`) {
|
if (button.customId === `cancel-trade-${trade.id}`) {
|
||||||
|
button.deferUpdate();
|
||||||
collector.stop("cancel");
|
collector.stop("cancel");
|
||||||
}
|
}
|
||||||
if (button.customId === `lock-trade-${trade.id}`) {
|
if (button.customId === `lock-trade-${trade.id}`) {
|
||||||
@@ -299,6 +337,13 @@ module.exports = {
|
|||||||
//TODO: perform trade on database
|
//TODO: perform trade on database
|
||||||
}
|
}
|
||||||
await this.viewTrade(interaction, trade);
|
await this.viewTrade(interaction, trade);
|
||||||
|
await this.endTrade(trade);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async endTrade(trade) {
|
||||||
|
setTimeout(async () => {
|
||||||
|
await TradeStore.removeTrade(trade);
|
||||||
|
}, tradeTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,11 +17,11 @@ const QUALITY_NAMES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QUALITY_SYMBOLS = {
|
const QUALITY_SYMBOLS = {
|
||||||
1 : "<a:shyyOrcaTrain:1005123718542020729><:shyyDead:859552234697916426><:shyyDead:859552234697916426><:shyyDead:859552234697916426><:shyyDead:859552234697916426>",
|
1 : "<a:shyyOrcaTrain:1059541149611733002><:shyyDead:1059541444110581780><:shyyDead:1059541444110581780><:shyyDead:1059541444110581780><:shyyDead:1059541444110581780>",
|
||||||
2 : "<a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><:shyyDead:859552234697916426><:shyyDead:859552234697916426><:shyyDead:859552234697916426>",
|
2 : "<a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><:shyyDead:1059541444110581780><:shyyDead:1059541444110581780><:shyyDead:1059541444110581780>",
|
||||||
3 : "<a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><:shyyDead:859552234697916426><:shyyDead:859552234697916426>",
|
3 : "<a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><:shyyDead:1059541444110581780><:shyyDead:1059541444110581780>",
|
||||||
4 : "<a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><:shyyDead:859552234697916426>",
|
4 : "<a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><:shyyDead:1059541444110581780>",
|
||||||
5 : "<a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729><a:shyyOrcaTrain:1005123718542020729>",
|
5 : "<a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002><a:shyyOrcaTrain:1059541149611733002>",
|
||||||
6 : "⭐⭐⭐⭐⭐"
|
6 : "⭐⭐⭐⭐⭐"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user