142 lines
4.8 KiB
Java
142 lines
4.8 KiB
Java
package ru.emotilt.antiplatka.poll;
|
|
|
|
import java.time.Duration;
|
|
import java.util.Date;
|
|
import java.util.Objects;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import net.dv8tion.jda.api.entities.Member;
|
|
import net.dv8tion.jda.api.entities.Message;
|
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
|
import net.dv8tion.jda.api.entities.emoji.Emoji;
|
|
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
|
import net.dv8tion.jda.api.utils.messages.MessagePollBuilder;
|
|
import net.dv8tion.jda.api.utils.messages.MessagePollData;
|
|
import ru.emotilt.antiplatka.Bot;
|
|
|
|
public abstract class BotPoll {
|
|
public final @Nullable Message message;
|
|
// TODO: Create an abstraction for targets. This means that it can have any
|
|
// targets except the user.
|
|
public final Member targetUser;
|
|
public final @Nullable MessageChannel channel;
|
|
public final Date start;
|
|
public final Duration voteDuration;
|
|
|
|
public abstract void endVote();
|
|
|
|
public abstract String getEndAnnouncementText(boolean success);
|
|
|
|
@SuppressWarnings("method.invocation")
|
|
public BotPoll(@Nullable Message message, Member targetUser, @Nullable MessageChannel channel, Date start, Duration voteDuration) {
|
|
this.message = message;
|
|
this.targetUser = targetUser;
|
|
this.channel = channel;
|
|
this.start = start;
|
|
this.voteDuration = voteDuration;
|
|
|
|
schedule(message);
|
|
}
|
|
|
|
/**
|
|
* Queue to complete the poll.
|
|
* This is required if the poll lasts less than 1 hour.
|
|
*
|
|
* @param message A message containing a poll.
|
|
*/
|
|
public void schedule(@Nullable Message message) {
|
|
if (isShort()) {
|
|
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
|
executorService.submit(() -> {
|
|
try {
|
|
Thread.sleep(voteDuration.toMillis());
|
|
} catch (InterruptedException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
|
|
Objects.requireNonNull(message).endPoll().queue();
|
|
});
|
|
executorService.shutdown();
|
|
}
|
|
}
|
|
|
|
protected boolean isShort() {
|
|
// The Discord API does not allow polls that are less than 1 hour in length.
|
|
return voteDuration.toMillis() < TimeUnit.HOURS.toMillis(1);
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
public static abstract class Builder<T extends Builder<T>> {
|
|
protected @Nullable Message message = null;
|
|
protected Member targetUser;
|
|
protected @Nullable MessageChannel channel = null;
|
|
protected Date start = new Date();
|
|
protected Duration voteDuration;
|
|
|
|
protected abstract T self();
|
|
|
|
public Builder(Member targetUser, Duration voteDuration) {
|
|
this.targetUser = targetUser;
|
|
this.voteDuration = voteDuration;
|
|
}
|
|
|
|
public T message(Message message) {
|
|
this.message = message;
|
|
return self();
|
|
}
|
|
|
|
public T targetUser(Member targetUser) {
|
|
this.targetUser = targetUser;
|
|
return self();
|
|
}
|
|
|
|
public T channel(MessageChannel channel) {
|
|
this.channel = channel;
|
|
return self();
|
|
}
|
|
|
|
public T start(Date start) {
|
|
this.start = start;
|
|
return self();
|
|
}
|
|
|
|
public T voteDuration(Duration voteDuration) {
|
|
this.voteDuration = voteDuration;
|
|
return self();
|
|
}
|
|
|
|
public MessageCreateBuilder buildMessage(String announcementText) {
|
|
String title = announcementText + ". Порог голосования **%d%%**.";
|
|
title = String.format(title, Bot.config.threshold);
|
|
|
|
MessagePollData poll = new MessagePollBuilder("Голосование")
|
|
.addAnswer("Да", Emoji.fromUnicode("✅"))
|
|
.addAnswer("Нет", Emoji.fromUnicode("❌"))
|
|
.setDuration(
|
|
isShort() ? TimeUnit.HOURS.toMinutes(1)
|
|
: voteDuration.toMinutes(),
|
|
TimeUnit.MINUTES)
|
|
.build();
|
|
|
|
if (isShort()) {
|
|
title += String.format(" Голосование закончится <t:%d:R>",
|
|
start.getTime() / 1000 + voteDuration.toSeconds());
|
|
}
|
|
|
|
return new MessageCreateBuilder().addContent(title).setPoll(poll);
|
|
}
|
|
|
|
protected boolean isShort() {
|
|
// The Discord API does not allow polls that are less than 1 hour in length.
|
|
return voteDuration.toMillis() < TimeUnit.HOURS.toMillis(1);
|
|
}
|
|
|
|
// Abstract build method to be implemented by subclasses
|
|
public abstract BotPoll build();
|
|
}
|
|
}
|