243 lines
11 KiB
Java
243 lines
11 KiB
Java
package com.alttd.commandManager.commands;
|
|
|
|
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.commandOutputChannels.CommandOutputChannels;
|
|
import com.alttd.database.queries.commandOutputChannels.OutputType;
|
|
import com.alttd.schedulers.AuctionScheduler;
|
|
import com.alttd.selectMenuManager.SelectMenuManager;
|
|
import com.alttd.util.Logger;
|
|
import com.alttd.util.Util;
|
|
import net.dv8tion.jda.api.EmbedBuilder;
|
|
import net.dv8tion.jda.api.JDA;
|
|
import net.dv8tion.jda.api.entities.Guild;
|
|
import net.dv8tion.jda.api.entities.Member;
|
|
import net.dv8tion.jda.api.entities.Message;
|
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
|
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
|
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
|
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
|
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
|
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.requests.RestAction;
|
|
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
|
|
import net.dv8tion.jda.api.utils.AttachedFile;
|
|
|
|
import java.awt.*;
|
|
import java.nio.file.Path;
|
|
import java.time.Instant;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
public class CommandAuction extends DiscordCommand {
|
|
|
|
private final CommandData commandData;
|
|
private final SelectMenuManager selectMenuManager;
|
|
public CommandAuction(JDA jda, CommandManager commandManager, SelectMenuManager selectMenuManager) {
|
|
commandData = Commands.slash(getName(), "Create an auction")
|
|
.addOption(OptionType.STRING, "item", "The name (and type) of the item you're selling", true)
|
|
.addOption(OptionType.INTEGER, "amount", "How many of the item you're selling", true)
|
|
.addOption(OptionType.INTEGER, "starting-price", "How much the bids should start at (the minimum price you're willing to accept for the item", true)
|
|
.addOption(OptionType.INTEGER, "minimum-increase", "The minimum amount of money bids should increase by", true)
|
|
.addOption(OptionType.INTEGER, "insta-buy", "(optional) A price you're willing to sell the item for immediately (ends the auction)", false)
|
|
.addOption(OptionType.STRING, "description", "(optional) A further explanation of the item", false)
|
|
.addOption(OptionType.ATTACHMENT, "screenshot", "(optional) A screenshot of the item you're selling if needed", false)
|
|
.setDefaultPermissions(DefaultMemberPermissions.ENABLED);
|
|
|
|
this.selectMenuManager = selectMenuManager;
|
|
Util.registerCommand(commandManager, jda, commandData, getName());
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "auction";
|
|
}
|
|
|
|
@Override
|
|
public void execute(SlashCommandInteractionEvent event) {
|
|
Guild guild = event.getGuild();
|
|
if (guild == null) {
|
|
handleError(event, "This command can only be executed within a guild");
|
|
return;
|
|
}
|
|
|
|
GuildChannel outputChannel = CommandOutputChannels.getOutputChannel(guild, OutputType.AUCTION);
|
|
if (outputChannel == null) {
|
|
handleError(event, "This guild does not have an Auction channel set");
|
|
return;
|
|
}
|
|
|
|
TextChannel textChannel = validTextChannel(event, outputChannel);
|
|
if (textChannel == null) {
|
|
handleError(event, "This guild has an invalid Auction channel");
|
|
return;
|
|
}
|
|
|
|
Integer minimumIncrease = event.getOption("minimum-increase", OptionMapping::getAsInt);
|
|
if (minimumIncrease == null) {
|
|
handleError(event, "Missing required minimum increase option");
|
|
return;
|
|
}
|
|
|
|
MessageEmbed messageEmbed = buildAuctionEmbed(event, minimumIncrease);
|
|
if (messageEmbed == null)
|
|
return;
|
|
ReplyCallbackAction replyCallbackAction = event.deferReply(true);
|
|
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());
|
|
}
|
|
|
|
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.altitudeLogs.error("Starting price magically became null");
|
|
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Error", "Failed to store auction"))
|
|
.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(auction);
|
|
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "Your auction was created"))
|
|
.queue();
|
|
}
|
|
|
|
private void addScreenshot(Message.Attachment screenshot, Message message) {
|
|
String dataFolder = AltitudeBot.getInstance().getDataFolder();
|
|
Path path = Path.of(dataFolder + 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) {
|
|
Member member = event.getMember();
|
|
if (member == null) {
|
|
return handleBuildEmbedError(event, "You are not a member of this guild");
|
|
}
|
|
EmbedBuilder embedBuilder = new EmbedBuilder();
|
|
String item = event.getOption("item", OptionMapping::getAsString);
|
|
if (item == null)
|
|
return handleBuildEmbedError(event, "Missing required item option");
|
|
if (item.length() > 128)
|
|
return handleBuildEmbedError(event, "Your item name is too long");
|
|
embedBuilder.appendDescription("**Item**: " + item);
|
|
|
|
Integer amount = event.getOption("amount", OptionMapping::getAsInt);
|
|
if (amount == null)
|
|
return handleBuildEmbedError(event, "Missing required amount option");
|
|
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**: $" + 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**: $" + Util.formatNumber(instaBuy));
|
|
}
|
|
|
|
|
|
String description = event.getOption("description", OptionMapping::getAsString);
|
|
if (description != null)
|
|
embedBuilder.appendDescription("\n**Description**: " + description);
|
|
|
|
embedBuilder
|
|
.setAuthor(member.getEffectiveName(), null, member.getAvatarUrl())
|
|
.setTitle("Auction")
|
|
.setColor(Color.ORANGE)
|
|
.appendDescription("\n\nCloses <t:" + (Instant.now().getEpochSecond() + TimeUnit.DAYS.toSeconds(1)) + ":R>");
|
|
return embedBuilder.build();
|
|
}
|
|
|
|
private MessageEmbed handleBuildEmbedError(SlashCommandInteractionEvent event, String s) {
|
|
event.replyEmbeds(Util.genericErrorEmbed("Error", s))
|
|
.setEphemeral(true)
|
|
.queue();
|
|
return null;
|
|
}
|
|
|
|
private void handleError(SlashCommandInteractionEvent event, String s) {
|
|
event.replyEmbeds(Util.genericErrorEmbed("Error", s))
|
|
.setEphemeral(true)
|
|
.queue();
|
|
}
|
|
|
|
private TextChannel validTextChannel(SlashCommandInteractionEvent event, GuildChannel guildChannel) {
|
|
if (guildChannel == null) {
|
|
event.replyEmbeds(Util.genericErrorEmbed("Error", "This server does not have a valid auction channel"))
|
|
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
|
return null;
|
|
}
|
|
|
|
if (!(guildChannel instanceof TextChannel channel)) {
|
|
event.replyEmbeds(Util.genericErrorEmbed("Error", "A auction channel can't be of type: " + guildChannel.getType().name()))
|
|
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
|
return null;
|
|
}
|
|
return channel;
|
|
}
|
|
|
|
@Override
|
|
public void suggest(CommandAutoCompleteInteractionEvent event) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public String getHelpMessage() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public CommandData getCommandData() {
|
|
return commandData;
|
|
}
|
|
}
|