Improved auctions
- Added Starting Bid (only for first bid) - Fixed missing $'s in messages - Improved the way numbers are displayed in auctions for readability - Added AuctionActions to store bids by users - Removed as much code that was relying on text being in embeds as possible - Improved structure of code related to auctions
This commit is contained in:
parent
5d8368d0e5
commit
723847a3be
|
|
@ -4,11 +4,9 @@ import com.alttd.AltitudeBot;
|
|||
import com.alttd.commandManager.CommandManager;
|
||||
import com.alttd.commandManager.DiscordCommand;
|
||||
import com.alttd.database.queries.QueriesAuctions.Auction;
|
||||
import com.alttd.database.queries.QueriesAuctions.QueriesAuction;
|
||||
import com.alttd.database.queries.commandOutputChannels.CommandOutputChannels;
|
||||
import com.alttd.database.queries.commandOutputChannels.OutputType;
|
||||
import com.alttd.schedulers.AuctionScheduler;
|
||||
import com.alttd.selectMenuManager.DiscordSelectMenu;
|
||||
import com.alttd.selectMenuManager.SelectMenuManager;
|
||||
import com.alttd.util.Logger;
|
||||
import com.alttd.util.Util;
|
||||
|
|
@ -28,13 +26,11 @@ import net.dv8tion.jda.api.interactions.commands.OptionType;
|
|||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
|
||||
import net.dv8tion.jda.api.utils.AttachedFile;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
|
@ -94,54 +90,17 @@ public class CommandAuction extends DiscordCommand {
|
|||
if (messageEmbed == null)
|
||||
return;
|
||||
ReplyCallbackAction replyCallbackAction = event.deferReply(true);
|
||||
textChannel.sendMessageEmbeds(messageEmbed).queue(success -> {
|
||||
Message.Attachment screenshot = event.getOption("screenshot", OptionMapping::getAsAttachment);
|
||||
if (screenshot != null) {
|
||||
String dataFolder = AltitudeBot.getInstance().getDataFolder();
|
||||
Path parent = Path.of(dataFolder).getParent();
|
||||
Path path = Path.of(parent.toString() + UUID.randomUUID() + "." + screenshot.getFileExtension());
|
||||
screenshot.getProxy().downloadToFile(path.toFile()).whenComplete((file, throwable) ->
|
||||
success.editMessageAttachments(AttachedFile.fromData(file)).queue(done -> file.delete(), failed -> {
|
||||
Util.handleFailure(failed);
|
||||
file.delete();
|
||||
}))
|
||||
.exceptionally(e -> {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
DiscordSelectMenu discordAuction = selectMenuManager.getDiscordSelectMenuFor("auction");
|
||||
if (discordAuction == null) {
|
||||
replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to find select menu for your auction, removing message..."))
|
||||
.queue();
|
||||
success.delete().queue();
|
||||
return;
|
||||
}
|
||||
SelectMenu selectMenu;
|
||||
Integer instaBuy = event.getOption("insta-buy", OptionMapping::getAsInt);
|
||||
int mediumIncrease = minimumIncrease * 5;
|
||||
if (instaBuy != null) {
|
||||
if (mediumIncrease == instaBuy)
|
||||
mediumIncrease += 1;
|
||||
selectMenu = discordAuction.getSelectMenu(
|
||||
SelectOption.of("Increase bid by: " + minimumIncrease, "" + minimumIncrease),
|
||||
SelectOption.of("Increase bid by: " + mediumIncrease, "" + mediumIncrease),
|
||||
SelectOption.of("Insta Buy: " + instaBuy, "" + instaBuy)
|
||||
);
|
||||
} else {
|
||||
selectMenu = discordAuction.getSelectMenu(
|
||||
SelectOption.of("Increase bid by: " + minimumIncrease, "" + minimumIncrease),
|
||||
SelectOption.of("Increase bid by: " + mediumIncrease, "" + mediumIncrease)
|
||||
);
|
||||
textChannel.sendMessageEmbeds(messageEmbed).queue(
|
||||
success -> onSuccessSendAuctionMessage(event, success, replyCallbackAction, minimumIncrease),
|
||||
error -> replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to send your auction to the auction channel"))
|
||||
.queue());
|
||||
}
|
||||
|
||||
if (selectMenu == null) {
|
||||
replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to add select menu to your auction, removing message..."))
|
||||
.queue();
|
||||
success.delete().queue();
|
||||
return;
|
||||
}
|
||||
success.editMessageComponents().setActionRow(selectMenu).queue();
|
||||
private void onSuccessSendAuctionMessage(SlashCommandInteractionEvent event, Message message, ReplyCallbackAction replyCallbackAction, int minimumIncrease) {
|
||||
Message.Attachment screenshot = event.getOption("screenshot", OptionMapping::getAsAttachment);
|
||||
if (screenshot != null)
|
||||
addScreenshot(screenshot, message);
|
||||
|
||||
Integer startingPrice = event.getOption("starting-price", OptionMapping::getAsInt);
|
||||
if (startingPrice == null) {
|
||||
Logger.severe("Starting price magically became null");
|
||||
|
|
@ -149,22 +108,51 @@ public class CommandAuction extends DiscordCommand {
|
|||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
Auction auction = new Auction(
|
||||
event.getUser().getIdLong(),
|
||||
message,
|
||||
message.getChannel().getIdLong(),
|
||||
message.getGuild().getIdLong(),
|
||||
startingPrice,
|
||||
Instant.now().toEpochMilli() + TimeUnit.DAYS.toMillis(1),
|
||||
minimumIncrease,
|
||||
event.getOption("insta-buy", OptionMapping::getAsInt));
|
||||
|
||||
SelectMenu selectMenu = auction.getSelectMenu(selectMenuManager, false);
|
||||
if (selectMenu == null) {
|
||||
replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to find select menu for your auction, removing message..."))
|
||||
.queue();
|
||||
message.delete().queue();
|
||||
return;
|
||||
}
|
||||
|
||||
message.editMessageComponents().setActionRow(selectMenu).queue();
|
||||
|
||||
AuctionScheduler auctionScheduler = AuctionScheduler.getInstance();
|
||||
if (auctionScheduler == null) {
|
||||
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Error", "Failed to store auction in scheduler"))
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
auctionScheduler.addAuction(new Auction(
|
||||
success,
|
||||
success.getChannel().getIdLong(),
|
||||
success.getGuild().getIdLong(),
|
||||
startingPrice,
|
||||
Instant.now().toEpochMilli() + TimeUnit.DAYS.toMillis(1)));
|
||||
auctionScheduler.addAuction(auction);
|
||||
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "Your auction was created"))
|
||||
.queue();
|
||||
}, error -> replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to send your auction to the auction channel"))
|
||||
.queue());
|
||||
}
|
||||
|
||||
private void addScreenshot(Message.Attachment screenshot, Message message) {
|
||||
String dataFolder = AltitudeBot.getInstance().getDataFolder();
|
||||
Path parent = Path.of(dataFolder).getParent();
|
||||
Path path = Path.of(parent.toString() + UUID.randomUUID() + "." + screenshot.getFileExtension());
|
||||
screenshot.getProxy().downloadToFile(path.toFile()).whenComplete((file, throwable) ->
|
||||
message.editMessageAttachments(AttachedFile.fromData(file)).queue(done -> file.delete(), failed -> {
|
||||
Util.handleFailure(failed);
|
||||
file.delete();
|
||||
}))
|
||||
.exceptionally(e -> {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private MessageEmbed buildAuctionEmbed(SlashCommandInteractionEvent event, int minimumIncrease) {
|
||||
|
|
@ -183,18 +171,18 @@ public class CommandAuction extends DiscordCommand {
|
|||
Integer amount = event.getOption("amount", OptionMapping::getAsInt);
|
||||
if (amount == null)
|
||||
return handleBuildEmbedError(event, "Missing required amount option");
|
||||
embedBuilder.appendDescription("\n**Amount**: " + amount);
|
||||
embedBuilder.appendDescription("\n**Amount**: " + Util.formatNumber(amount));
|
||||
|
||||
Integer startingPrice = event.getOption("starting-price", OptionMapping::getAsInt);
|
||||
if (startingPrice == null)
|
||||
return handleBuildEmbedError(event, "Missing required starting price option");
|
||||
embedBuilder.appendDescription("\n**Starting Price**: $" + startingPrice);
|
||||
embedBuilder.appendDescription("\n**Starting Price**: $" + Util.formatNumber(startingPrice));
|
||||
|
||||
Integer instaBuy = event.getOption("insta-buy", OptionMapping::getAsInt);
|
||||
if (instaBuy != null) {
|
||||
if (instaBuy == minimumIncrease)
|
||||
return handleBuildEmbedError(event, "Insta buy can't be the same as minimum increase");
|
||||
embedBuilder.appendDescription("\n**Insta Buy**: $" + instaBuy);
|
||||
embedBuilder.appendDescription("\n**Insta Buy**: $" + Util.formatNumber(instaBuy));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -137,11 +137,14 @@ public class DatabaseTables {
|
|||
|
||||
private void createAuctionTable() {
|
||||
String sql = "CREATE TABLE IF NOT EXISTS auctions(" +
|
||||
"user_id BIGINT NOT NULL, " +
|
||||
"message_id BIGINT NOT NULL, " +
|
||||
"channel_id BIGINT NOT NULL, " +
|
||||
"guild_id BIGINT NOT NULL, " +
|
||||
"starting_price INT NOT NULL, " +
|
||||
"expire_time BIGINT NOT NULL, " +
|
||||
"minimum_increase INT NOT NULL, " +
|
||||
"insta_buy INT NULL, " +
|
||||
"PRIMARY KEY (message_id)" +
|
||||
")";
|
||||
try {
|
||||
|
|
@ -152,6 +155,23 @@ public class DatabaseTables {
|
|||
}
|
||||
}
|
||||
|
||||
private void createAuctionActionsTable() {
|
||||
String sql = "CREATE TABLE IF NOT EXISTS auction_actions(" +
|
||||
"message_id BIGINT NOT NULL, " +
|
||||
"action_type VARCHAR(32) NOT NULL, " +
|
||||
"user_id BIGINT NOT NULL, " +
|
||||
"price INT NOT NULL, " +
|
||||
"action_time BIGINT NOT NULL, " +
|
||||
"PRIMARY KEY (message_id, action_time)" +
|
||||
")";
|
||||
try {
|
||||
connection.prepareStatement(sql).executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
Logger.sql(e);
|
||||
Logger.severe("Unable to create auction action table, shutting down...");
|
||||
}
|
||||
}
|
||||
|
||||
public static void createTables(Connection connection) {
|
||||
if (instance == null)
|
||||
instance = new DatabaseTables(connection);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.alttd.database.queries.QueriesAuctionActions;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record AuctionAction(AuctionType auctionType, long userId, long messageId, int price, long time) implements Comparable<AuctionAction> {
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull AuctionAction auctionAction) {
|
||||
return Long.compare(this.time(), auctionAction.time());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.alttd.database.queries.QueriesAuctionActions;
|
||||
|
||||
public enum AuctionType {
|
||||
BID,
|
||||
STARTING_BID,
|
||||
INSTA_BUY
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package com.alttd.database.queries.QueriesAuctionActions;
|
||||
|
||||
import com.alttd.database.Database;
|
||||
import com.alttd.database.queries.QueriesAuctions.Auction;
|
||||
import com.alttd.util.Logger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class QueriesAuctionAction {
|
||||
public static boolean saveAuctionAction(AuctionAction auctionAction) {
|
||||
String sql = "INSERT INTO auction_actions " +
|
||||
"(message_id, action_type, user_id, price, action_time) " +
|
||||
"VALUES (?, ?, ?, ?, ?) ";
|
||||
try {
|
||||
PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
statement.setLong(1, auctionAction.messageId());
|
||||
statement.setString(2, auctionAction.auctionType().toString());
|
||||
statement.setLong(3, auctionAction.userId());
|
||||
statement.setInt(4, auctionAction.price());
|
||||
statement.setLong(5, auctionAction.time());
|
||||
|
||||
return statement.executeUpdate() == 1;
|
||||
} catch (SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean loadAuctionAction(Auction auction) {
|
||||
String sql = "SELECT * FROM auction_actions " +
|
||||
"WHERE message_id = ?";
|
||||
long messageId = auction.getMessageId();
|
||||
|
||||
try {
|
||||
PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
statement.setLong(1, messageId);
|
||||
ResultSet resultSet = statement.executeQuery();
|
||||
|
||||
LinkedList<AuctionAction> actions = new LinkedList<>();
|
||||
while (resultSet.next()) {
|
||||
long userId = resultSet.getLong("user_id");
|
||||
long actionTime = resultSet.getLong("action_time");
|
||||
int price = resultSet.getInt("price");
|
||||
String actionTypeString = resultSet.getString("action_type");
|
||||
AuctionType auctionType;
|
||||
|
||||
try {
|
||||
auctionType = AuctionType.valueOf(actionTypeString);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Logger.warning("Invalid auction type found in database for message: % at time: %", messageId + "", actionTime + "");
|
||||
continue;
|
||||
}
|
||||
actions.add(new AuctionAction(auctionType, userId, messageId, price, actionTime));
|
||||
}
|
||||
auction.resetActions(actions);
|
||||
return true;
|
||||
} catch (SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +1,76 @@
|
|||
package com.alttd.database.queries.QueriesAuctions;
|
||||
|
||||
import com.alttd.AltitudeBot;
|
||||
import com.alttd.database.queries.QueriesAuctionActions.AuctionAction;
|
||||
import com.alttd.database.queries.QueriesAuctionActions.QueriesAuctionAction;
|
||||
import com.alttd.selectMenuManager.DiscordSelectMenu;
|
||||
import com.alttd.selectMenuManager.SelectMenuManager;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Auction implements Comparable {
|
||||
private final long messageId, channelId, guildId;
|
||||
private final int startingPrice;
|
||||
private final long userId, messageId, channelId, guildId;
|
||||
private final Integer instaBuy;
|
||||
private final int startingPrice, minimumIncrease;
|
||||
|
||||
private long expireTime;
|
||||
|
||||
public Auction(long messageId, long channelId, long guildId, int startingPrice, long expireTime) {
|
||||
private final LinkedList<AuctionAction> actions = new LinkedList<>();
|
||||
|
||||
public Auction(long userId, long messageId, long channelId, long guildId, int startingPrice, long expireTime, int minimumIncrease, Integer instaBuy) {
|
||||
this.userId = userId;
|
||||
this.messageId = messageId;
|
||||
this.channelId = channelId;
|
||||
this.guildId = guildId;
|
||||
this.startingPrice = startingPrice;
|
||||
this.expireTime = expireTime;
|
||||
this.minimumIncrease = minimumIncrease;
|
||||
this.instaBuy = instaBuy;
|
||||
}
|
||||
|
||||
public Auction(@NotNull Message message, long channelId, long guildId, int startingPrice, long expireTime) {
|
||||
public Auction(long userId, @NotNull Message message, long channelId, long guildId, int startingPrice, long expireTime, int minimumIncrease, Integer instaBuy) {
|
||||
this.userId = userId;
|
||||
this.messageId = message.getIdLong();
|
||||
this.channelId = channelId;
|
||||
this.guildId = guildId;
|
||||
this.startingPrice = startingPrice;
|
||||
this.expireTime = expireTime;
|
||||
this.minimumIncrease = minimumIncrease;
|
||||
this.instaBuy = instaBuy;
|
||||
}
|
||||
|
||||
public void resetActions(LinkedList<AuctionAction> newAuctionActions) {
|
||||
actions.clear();
|
||||
actions.addAll(newAuctionActions);
|
||||
actions.sort(AuctionAction::compareTo);
|
||||
}
|
||||
|
||||
public void addAction(AuctionAction auctionAction) {
|
||||
actions.add(auctionAction);
|
||||
QueriesAuctionAction.saveAuctionAction(auctionAction);
|
||||
}
|
||||
|
||||
public AuctionAction getLastAction() {
|
||||
if (actions.size() == 0)
|
||||
return null;
|
||||
return actions.getLast();
|
||||
}
|
||||
|
||||
public LinkedList<AuctionAction> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void updateMessage(Consumer<? super Message> success, @Nullable Consumer<? super String> failure) {
|
||||
|
|
@ -54,6 +94,10 @@ public class Auction implements Comparable {
|
|||
});
|
||||
}
|
||||
|
||||
public long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public long getExpireTime() {
|
||||
return expireTime;
|
||||
}
|
||||
|
|
@ -74,6 +118,14 @@ public class Auction implements Comparable {
|
|||
return startingPrice;
|
||||
}
|
||||
|
||||
public int getMinimumIncrease() {
|
||||
return minimumIncrease;
|
||||
}
|
||||
|
||||
public Integer getInstaBuy() {
|
||||
return instaBuy;
|
||||
}
|
||||
|
||||
public boolean updateExpiry() {
|
||||
long future = Instant.now().toEpochMilli() + TimeUnit.MINUTES.toMillis(5);
|
||||
if (expireTime < future) {
|
||||
|
|
@ -88,4 +140,28 @@ public class Auction implements Comparable {
|
|||
Auction o1 = (Auction) o;
|
||||
return Long.compare(expireTime, o1.getExpireTime());
|
||||
}
|
||||
|
||||
public SelectMenu getSelectMenu(SelectMenuManager selectMenuManager, boolean startingBidFinished) {
|
||||
DiscordSelectMenu discordAuction = selectMenuManager.getDiscordSelectMenuFor("auction");
|
||||
if (discordAuction == null)
|
||||
return null;
|
||||
int mediumIncrease = minimumIncrease * 5;
|
||||
List<SelectOption> selectOptionList = new ArrayList<>();
|
||||
|
||||
if (startingBidFinished)
|
||||
selectOptionList.add(SelectOption.of("Increase bid by: $" + Util.formatNumber(minimumIncrease), "" + minimumIncrease));
|
||||
else
|
||||
selectOptionList.add(SelectOption.of("Starting Bid: $" + Util.formatNumber(startingPrice), "" + startingPrice));
|
||||
if (instaBuy != null) {
|
||||
if (mediumIncrease == instaBuy)
|
||||
mediumIncrease += 1;
|
||||
if (startingBidFinished)
|
||||
selectOptionList.add(SelectOption.of("Increase bid by: $" + Util.formatNumber(mediumIncrease), "" + mediumIncrease));
|
||||
selectOptionList.add(SelectOption.of("Insta Buy: $" + Util.formatNumber(instaBuy), "" + instaBuy));
|
||||
} else if (startingBidFinished) {
|
||||
selectOptionList.add(SelectOption.of("Increase bid by: $" + Util.formatNumber(mediumIncrease), "" + mediumIncrease));
|
||||
}
|
||||
|
||||
return discordAuction.getSelectMenu(selectOptionList);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.alttd.database.queries.QueriesAuctions;
|
||||
|
||||
import com.alttd.database.Database;
|
||||
import com.alttd.database.queries.QueriesAuctionActions.QueriesAuctionAction;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
|
@ -20,9 +21,15 @@ public class QueriesAuction {
|
|||
long messageId = resultSet.getLong("message_id");
|
||||
long channelId = resultSet.getLong("channel_id");
|
||||
long guildId = resultSet.getLong("guild_id");
|
||||
long userId = resultSet.getLong("user_id");
|
||||
int startingPrice = resultSet.getInt("starting_price");
|
||||
long expireTime = resultSet.getLong("expire_time");
|
||||
auctions.put(messageId, new Auction(messageId, channelId, guildId, startingPrice, expireTime));
|
||||
int minimumIncrease = resultSet.getInt("minimum_increase");
|
||||
Integer instaBuy = resultSet.getInt("insta_buy");
|
||||
instaBuy = instaBuy == -1 ? null : instaBuy; //Make sure the object is null if price was null or 0
|
||||
Auction auction = new Auction(userId, messageId, channelId, guildId, startingPrice, expireTime, minimumIncrease, instaBuy);
|
||||
QueriesAuctionAction.loadAuctionAction(auction);
|
||||
auctions.put(messageId, auction);
|
||||
}
|
||||
} catch (SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
|
|
@ -33,17 +40,20 @@ public class QueriesAuction {
|
|||
|
||||
public static boolean saveAuction(Auction auction) {
|
||||
String sql = "INSERT INTO auctions " +
|
||||
"(message_id, channel_id, guild_id, starting_price, expire_time) " +
|
||||
"VALUES (?, ?, ?, ?, ?) " +
|
||||
"(message_id, channel_id, guild_id, user_id, starting_price, expire_time, minimum_increase, insta_buy) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE expire_time = ?";
|
||||
try {
|
||||
PreparedStatement statement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
statement.setLong(1, auction.getMessageId());
|
||||
statement.setLong(2, auction.getChannelId());
|
||||
statement.setLong(3, auction.getGuildId());
|
||||
statement.setInt(4, auction.getStartingPrice());
|
||||
statement.setLong(5, auction.getExpireTime());
|
||||
statement.setLong(4, auction.getUserId());
|
||||
statement.setInt(5, auction.getStartingPrice());
|
||||
statement.setLong(6, auction.getExpireTime());
|
||||
statement.setInt(7, auction.getMinimumIncrease());
|
||||
statement.setInt(8, auction.getInstaBuy() == null ? -1 : auction.getInstaBuy());
|
||||
statement.setLong(9, auction.getExpireTime());
|
||||
|
||||
return statement.executeUpdate() == 1;
|
||||
} catch (SQLException exception) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
import java.awt.*;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
@ -108,6 +109,7 @@ public class AuctionScheduler {
|
|||
embedBuilder.addField("Winning Bid", "Insta bought by " + instaBuy.getAsMention(), false);
|
||||
else if (!fields.isEmpty()) {
|
||||
MessageEmbed.Field field = fields.get(0);
|
||||
|
||||
if (field.getName() != null && field.getName().equals("Current Bid") && field.getValue() != null) {
|
||||
embedBuilder.addField("Winning Bid", field.getValue(), false);
|
||||
} else if (fields.size() == 2) {
|
||||
|
|
@ -116,6 +118,13 @@ public class AuctionScheduler {
|
|||
embedBuilder.addField("Winning Bid", field.getValue(), false);
|
||||
}
|
||||
}
|
||||
|
||||
String description = embed.getDescription();
|
||||
if (description != null) {
|
||||
embedBuilder.setDescription(description.substring(0, description.lastIndexOf("Closes")));
|
||||
embedBuilder.appendDescription("Closed <t:" + Instant.now().getEpochSecond() + ":R>");
|
||||
}
|
||||
|
||||
if (embedBuilder.getFields().size() != 0)
|
||||
embedBuilder.setColor(Color.GREEN);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
package com.alttd.selectMenuManager;
|
||||
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.component.SelectMenuInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class DiscordSelectMenu {
|
||||
|
||||
public abstract String getSelectMenuId();
|
||||
|
||||
public abstract void execute(SelectMenuInteractionEvent event);
|
||||
|
||||
public abstract SelectMenu getSelectMenu(SelectOption ...selectOptions);
|
||||
public abstract SelectMenu getSelectMenu(List<SelectOption> selectOptions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class SelectMenuManager extends ListenerAdapter {
|
|||
private final List<DiscordSelectMenu> buttons;
|
||||
|
||||
public SelectMenuManager() {
|
||||
buttons = List.of(new SelectMenuAuction());
|
||||
buttons = List.of(new SelectMenuAuction(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,26 +1,33 @@
|
|||
package com.alttd.selectMenuManager.selectMenus;
|
||||
|
||||
import com.alttd.database.queries.QueriesAuctionActions.AuctionAction;
|
||||
import com.alttd.database.queries.QueriesAuctionActions.AuctionType;
|
||||
import com.alttd.database.queries.QueriesAuctions.Auction;
|
||||
import com.alttd.database.queries.QueriesAuctions.QueriesAuction;
|
||||
import com.alttd.schedulers.AuctionScheduler;
|
||||
import com.alttd.selectMenuManager.DiscordSelectMenu;
|
||||
import com.alttd.selectMenuManager.SelectMenuManager;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Mentions;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.events.interaction.component.SelectMenuInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectOption;
|
||||
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
|
||||
|
||||
import java.awt.*;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SelectMenuAuction extends DiscordSelectMenu {
|
||||
|
||||
private final SelectMenuManager selectMenuManager;
|
||||
|
||||
public SelectMenuAuction(SelectMenuManager selectMenuManager) {
|
||||
this.selectMenuManager = selectMenuManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSelectMenuId() {
|
||||
return "auction";
|
||||
|
|
@ -73,32 +80,33 @@ public class SelectMenuAuction extends DiscordSelectMenu {
|
|||
MessageEmbed messageEmbed = getMessageEmbed(event.getMessage().getEmbeds(), event);
|
||||
if (messageEmbed == null)
|
||||
return;
|
||||
if (messageEmbed.getAuthor() != null && messageEmbed.getAuthor().getName() != null && messageEmbed.getAuthor().getName().equalsIgnoreCase(member.getEffectiveName())) {
|
||||
if (member.getIdLong() == auction.getUserId()) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "You own this auction so you can not bid on it."))
|
||||
.setEphemeral(true).queue();
|
||||
//TODO store auction owner so this can be done better
|
||||
return;
|
||||
}
|
||||
BidFieldInfo bidFieldInfo = getPreviousBid(messageEmbed, event);
|
||||
if (bidFieldInfo == null)
|
||||
return;
|
||||
int prevBid;
|
||||
if (bidFieldInfo.bid() == 0)
|
||||
prevBid = auction.getStartingPrice();
|
||||
else
|
||||
prevBid = bidFieldInfo.bid();
|
||||
|
||||
int currentBid = prevBid + bid;
|
||||
Instant now = Instant.now();
|
||||
if (selectOption.getLabel().startsWith("Insta Buy")) {
|
||||
Integer instaBuy = auction.getInstaBuy();
|
||||
auction.addAction(new AuctionAction(AuctionType.INSTA_BUY, member.getIdLong(), auction.getMessageId(), instaBuy == null ? -1 : instaBuy, now.toEpochMilli()));
|
||||
auctionScheduler.finishAuction(auction, member);
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "You successfully insta bought the item for " + bid + "!"))
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "You successfully insta bought the item for $" + Util.formatNumber(bid) + "!"))
|
||||
.setEphemeral(true).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
AuctionAction lastAction = auction.getLastAction();
|
||||
int prevBid = (lastAction == null ? 0 : lastAction.price());
|
||||
int currentBid = prevBid + bid;
|
||||
|
||||
if (selectOption.getLabel().startsWith("Starting Bid"))
|
||||
auction.addAction(new AuctionAction(AuctionType.STARTING_BID, member.getIdLong(), auction.getMessageId(), currentBid, now.toEpochMilli()));
|
||||
else
|
||||
auction.addAction(new AuctionAction(AuctionType.BID, member.getIdLong(), auction.getMessageId(), currentBid, now.toEpochMilli()));
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder(messageEmbed)
|
||||
.clearFields()
|
||||
.setTimestamp(Instant.now());
|
||||
.setTimestamp(now);
|
||||
if (auction.updateExpiry()) {
|
||||
auctionScheduler.updateAuction(auction);
|
||||
String description = messageEmbed.getDescription();
|
||||
|
|
@ -106,102 +114,28 @@ public class SelectMenuAuction extends DiscordSelectMenu {
|
|||
embedBuilder.setDescription(description.substring(0, description.lastIndexOf("Closes <t:")))
|
||||
.appendDescription("Closes <t:" + TimeUnit.MILLISECONDS.toSeconds(auction.getExpireTime()) + ":R>");
|
||||
}
|
||||
if (bidFieldInfo.member() != null)
|
||||
embedBuilder.addField("Previous Bid", "$" + bidFieldInfo.bid() + " by <@" + bidFieldInfo.member() + ">", false);
|
||||
embedBuilder.addField("Current Bid", "$" + currentBid + " by " + event.getMember().getAsMention(), false);
|
||||
if (lastAction != null)
|
||||
embedBuilder.addField("Previous Bid", "$" + Util.formatNumber(prevBid) + " by <@" + lastAction.userId() + ">", false);
|
||||
embedBuilder.addField("Current Bid", "$" + Util.formatNumber(currentBid) + " by " + event.getMember().getAsMention(), false);
|
||||
ReplyCallbackAction replyCallbackAction = event.deferReply(true);
|
||||
|
||||
int finalPrevBid = prevBid;
|
||||
event.getMessage().editMessageEmbeds(embedBuilder.build()).queue(
|
||||
success -> {
|
||||
if (auction.updateExpiry())
|
||||
auctionScheduler.updateAuction(auction);
|
||||
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "You successfully increased the bid from " + finalPrevBid + " to " + currentBid + "!"))
|
||||
if (!selectOption.getLabel().startsWith("Starting Bid")) {
|
||||
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "You successfully increased the bid from $" +
|
||||
Util.formatNumber(prevBid) + " to $" + Util.formatNumber(currentBid) + "!"))
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "You successfully made the first bid on this item ($" + Util.formatNumber(currentBid) + ")!"))
|
||||
.queue();
|
||||
success.editMessageComponents().setActionRow(auction.getSelectMenu(selectMenuManager, true)).queue();
|
||||
},
|
||||
error -> replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to finish your bid")).queue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Expecting to find:
|
||||
* a: No fields
|
||||
* b: One field containing the current bid
|
||||
* c: Two fields, one containing the current bid and one for the previous bid
|
||||
* <p>
|
||||
* option a: return BidFieldInfo with the bid set to 0 and member to null
|
||||
* option b: check if field matches roughly this:
|
||||
* Name: Current Bid
|
||||
* Value: 160 by <@212303885988134914>
|
||||
* if it does set the BidFieldInfo value to 160, and attempt ot get the user from the <@ string,
|
||||
* set member to the member belonging to that user id or null if we can't find it
|
||||
* option c: Find the field with the name Current Bid and proceed with that field as if it was option b
|
||||
* @param messageEmbed Embed to find the fields for
|
||||
* @param event Event that we need to respond to for errors
|
||||
* @return BidFieldInfo or null if there was an error
|
||||
*/
|
||||
private BidFieldInfo getPreviousBid(MessageEmbed messageEmbed, SelectMenuInteractionEvent event) {
|
||||
List<MessageEmbed.Field> fields = messageEmbed.getFields();
|
||||
if (fields.size() > 2) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This auction embed has the wrong number of fields"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (fields.isEmpty())
|
||||
return new BidFieldInfo(0, null);
|
||||
|
||||
MessageEmbed.Field field = fields.get(0);
|
||||
if (field.getName() == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Found field with no name"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!field.getName().equals("Current Bid")) {
|
||||
if (fields.size() != 2) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Found one field and it's not the right one"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
field = fields.get(1);
|
||||
if (field.getName() == null || !field.getName().equals("Current Bid")) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to find current bid but it should be there"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
String value1 = field.getValue();
|
||||
if (value1 == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Received default input"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
String[] s = value1.split(" ");
|
||||
if (s.length < 3) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Field has incorrect input"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
int bid;
|
||||
try {
|
||||
bid = Integer.parseInt(s[0].substring(1));
|
||||
} catch (NumberFormatException e) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Field had the wrong value"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
String substring = s[2].substring(2, s[2].length() - 1);
|
||||
try {
|
||||
long l = Long.parseLong(substring);
|
||||
|
||||
return new BidFieldInfo(bid, l);
|
||||
} catch (NumberFormatException e) {
|
||||
return new BidFieldInfo(bid, null);
|
||||
}
|
||||
}
|
||||
|
||||
private MessageEmbed getMessageEmbed(List<MessageEmbed> embeds, SelectMenuInteractionEvent event) {
|
||||
if (embeds.isEmpty()) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Input came from message with no embeds"))
|
||||
|
|
@ -212,12 +146,10 @@ public class SelectMenuAuction extends DiscordSelectMenu {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SelectMenu getSelectMenu(SelectOption... selectOptions) {
|
||||
public SelectMenu getSelectMenu(List<SelectOption> selectOptions) {
|
||||
SelectMenu.Builder builder = SelectMenu.create(getSelectMenuId());
|
||||
if (selectOptions != null)
|
||||
builder.addOptions(selectOptions);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
record BidFieldInfo(int bid, Long member) {}
|
||||
|
|
|
|||
|
|
@ -216,4 +216,16 @@ public class Util {
|
|||
return str.toUpperCase();
|
||||
return str.toUpperCase().charAt(0) + str.toLowerCase().substring(1);
|
||||
}
|
||||
|
||||
public static String formatNumber(int price) {
|
||||
String priceString = new StringBuilder(String.valueOf(price)).reverse().toString();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i = 0;
|
||||
while (i + 3 < priceString.length()) {
|
||||
sb.append(priceString, i, i + 3).append(",");
|
||||
i += 3;
|
||||
}
|
||||
sb.append(priceString.substring(i)).reverse();
|
||||
return "" + sb;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user