Added the Poll module V1
This commit is contained in:
parent
0817607697
commit
d6c272cdaf
3
SheepstarModules/PollV1/.gitignore
vendored
Normal file
3
SheepstarModules/PollV1/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Project exclude paths
|
||||||
|
/target/
|
||||||
|
.idea
|
2
SheepstarModules/PollV1/README.md
Normal file
2
SheepstarModules/PollV1/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# SheepstarModule-Poll
|
||||||
|
The official sheepstar poll module
|
24
SheepstarModules/PollV1/pom.xml
Normal file
24
SheepstarModules/PollV1/pom.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>xyz.sheepstar</groupId>
|
||||||
|
<artifactId>SheepstarModule-Poll</artifactId>
|
||||||
|
<version>pre1.0.0</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>xyz.sheepstar</groupId>
|
||||||
|
<artifactId>SheepstarCore</artifactId>
|
||||||
|
<version>beta1.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,27 @@
|
|||||||
|
package xyz.sheepstar.poll.action;
|
||||||
|
|
||||||
|
import xyz.sheepstar.poll.api.controller.PollController;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollManager;
|
||||||
|
import xyz.sheepstar.poll.core.PollCore;
|
||||||
|
import xyz.sheepstar.util.action.RepeatedAction;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class AutomaticCloseAction extends RepeatedAction {
|
||||||
|
|
||||||
|
private final PollManager pollManager = (PollManager) api.getDatabase().getTableFactory().getTable(PollManager.class);
|
||||||
|
private final PollController pollController = PollCore.getPollController();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long time() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
pollManager.getExpirablePolls().forEach((pollID, dateTime) -> {
|
||||||
|
if (dateTime.compareTo(LocalDateTime.now()) <= 0)
|
||||||
|
pollController.endPoll(pollID, pollManager.getPollById(pollID).getGuild());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
package xyz.sheepstar.poll.api.controller;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Emoji;
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.TextChannel;
|
||||||
|
import net.dv8tion.jda.api.interactions.components.ButtonStyle;
|
||||||
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import xyz.sheepstar.poll.api.entities.Poll;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollAnswerManager;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollManager;
|
||||||
|
import xyz.sheepstar.poll.commands.ClosePollCommand;
|
||||||
|
import xyz.sheepstar.util.bot.builder.message.DefaultEmbedBuilder;
|
||||||
|
import xyz.sheepstar.util.bot.builder.message.DefaultResponseBuilder;
|
||||||
|
import xyz.sheepstar.util.bot.builder.message.MessageType;
|
||||||
|
import xyz.sheepstar.util.bot.listener.ListenerBasics;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class PollController extends ListenerBasics {
|
||||||
|
|
||||||
|
private PollManager pollManager = (PollManager) table(PollManager.class);
|
||||||
|
private PollAnswerManager pollAnswerManager = (PollAnswerManager) table(PollAnswerManager.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number emoji by number
|
||||||
|
*
|
||||||
|
* @param number The number the emoji should display
|
||||||
|
* @return the number as emoji
|
||||||
|
*/
|
||||||
|
private Emoji getEmojiByNumber(int number) {
|
||||||
|
return Emoji.fromUnicode(number + "️⃣");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the 'started'-message of the poll
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll (used for the end button)
|
||||||
|
* @param date The date when the poll should expire
|
||||||
|
* @param title The title of the poll
|
||||||
|
* @param description The description of the poll
|
||||||
|
* @param answers All answers available in this poll
|
||||||
|
* @param guild The guild which created the poll
|
||||||
|
* @param closeButton Should the close button be displayed?
|
||||||
|
* @param multipleChoices Are multiple choices allowed?
|
||||||
|
* @return the final message
|
||||||
|
*/
|
||||||
|
public Message getStartedPollMessage(String pollID, Date date, String title, String description, ArrayList<String> answers, Guild guild,
|
||||||
|
boolean closeButton, boolean multipleChoices) {
|
||||||
|
DefaultResponseBuilder response = DefaultResponseBuilder.createSimple(guild, ClosePollCommand.class).withColor(MessageType.PRIMARY)
|
||||||
|
.withTitle(translate("poll.poll_started", guild));
|
||||||
|
|
||||||
|
response.addField(":label: " + translate("poll.object.title", guild), title);
|
||||||
|
|
||||||
|
if (description != null)
|
||||||
|
response.addField(":clipboard: " + translate("poll.object.description", guild), description);
|
||||||
|
|
||||||
|
ArrayList<String> subFields = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < answers.size(); i++)
|
||||||
|
subFields.add(getEmojiByNumber(i + 1).getAsMention() + " - " + answers.get(i));
|
||||||
|
|
||||||
|
response.addField(":ballot_box: " + translate("poll.object." + (multipleChoices ? "multiple_" : "") + "choices", guild) + "", subFields);
|
||||||
|
|
||||||
|
if (date != null)
|
||||||
|
response.addField(String.format("\n:alarm_clock: %s <t:%s:R>", translate("poll.ends", guild), date.getTime() / 1000));
|
||||||
|
|
||||||
|
if (closeButton)
|
||||||
|
response.addButton(ButtonStyle.DANGER, "end#" + pollID, date == null ? translate("poll.end_poll", guild) : translate("poll.end_now", guild));
|
||||||
|
|
||||||
|
return response.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the 'ended'-message of the poll
|
||||||
|
*
|
||||||
|
* @param poll The poll you want to get the message from
|
||||||
|
* @return The final 'ended'-message
|
||||||
|
*/
|
||||||
|
public Message getEndedPollMessage(Poll poll) {
|
||||||
|
DefaultEmbedBuilder embedBuilder = new DefaultEmbedBuilder(MessageType.PRIMARY).setTitle(translate("poll.poll_ended", poll.getGuild()));
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
boolean isTimeMessage = false;
|
||||||
|
for (String line : poll.getMessage().getEmbeds().get(0).getDescription().split("\n")) {
|
||||||
|
if (line.startsWith(":alarm_clock:")) isTimeMessage = true;
|
||||||
|
if (!line.startsWith(":alarm_clock:")) builder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
embedBuilder.setDescription((!isTimeMessage ? builder + "\n" : builder.substring(0, builder.length() - 3)));
|
||||||
|
|
||||||
|
HashMap<String, Integer> reaction_counts = new HashMap<>();
|
||||||
|
|
||||||
|
poll.getMessage().getReactions().forEach(reaction -> {
|
||||||
|
if (reaction.getReactionEmote().isEmoji())
|
||||||
|
reaction_counts.put(reaction.getReactionEmote().getEmoji(), reaction.getCount() - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
ArrayList<String> subFields = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < poll.getAnswers().size(); i++)
|
||||||
|
subFields.add(getEmojiByNumber(i + 1).getAsMention() + " - " + reaction_counts.getOrDefault(getEmojiByNumber(i + 1).getAsMention(), 0));
|
||||||
|
|
||||||
|
embedBuilder.addBField(":abacus: " + translate("poll.object.results", poll.getGuild()), subFields.toArray(new String[0]));
|
||||||
|
|
||||||
|
return embedBuilder.toMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new poll
|
||||||
|
*
|
||||||
|
* @param channel The channel the poll should be created in
|
||||||
|
* @param date The date when the poll should expire
|
||||||
|
* @param title The title of the poll
|
||||||
|
* @param description The description of the poll
|
||||||
|
* @param answers All answers available in this poll
|
||||||
|
* @param closeButton Should the close button be displayed?
|
||||||
|
* @param multipleChoices Are multiple choices allowed?
|
||||||
|
* @return the id of the created poll
|
||||||
|
*/
|
||||||
|
public String createPoll(TextChannel channel, Date date, String title, String description, ArrayList<String> answers, boolean closeButton, boolean multipleChoices) {
|
||||||
|
String pollID = RandomStringUtils.randomAlphanumeric(10);
|
||||||
|
|
||||||
|
pollAnswerManager.addAnswers(pollID, answers);
|
||||||
|
|
||||||
|
channel.sendMessage(getStartedPollMessage(pollID, date, title, description, answers, channel.getGuild(), closeButton, multipleChoices)).queue(message -> {
|
||||||
|
pollManager.createPoll(pollID, message, date);
|
||||||
|
for (int i = 0; i < answers.size(); i++)
|
||||||
|
message.addReaction(getEmojiByNumber(i + 1).getAsMention()).queue();
|
||||||
|
});
|
||||||
|
return pollID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the provided poll
|
||||||
|
*
|
||||||
|
* @param pollID The poll you want to end
|
||||||
|
* @param guild The guild which created the poll
|
||||||
|
* @return <code>true</code> if the poll has been ended successfully, otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean endPoll(String pollID, Guild guild) {
|
||||||
|
if (!pollManager.isCreated(pollID, guild)) return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Poll poll = pollManager.getPollById(pollID);
|
||||||
|
|
||||||
|
poll.getMessage().editMessage(getEndedPollMessage(poll)).queue();
|
||||||
|
|
||||||
|
poll.getMessage().clearReactions().queue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pollManager.deletePoll(pollID, guild);
|
||||||
|
pollAnswerManager.deleteAnswers(pollID);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package xyz.sheepstar.poll.api.entities;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.TextChannel;
|
||||||
|
import xyz.sheepstar.core.SheepstarCore;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollAnswerManager;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Poll {
|
||||||
|
|
||||||
|
private PollAnswerManager pollAnswerManager = (PollAnswerManager) SheepstarCore
|
||||||
|
.getSheepstar().getDatabase().getTableFactory().getTable(PollAnswerManager.class);
|
||||||
|
|
||||||
|
private String pollID;
|
||||||
|
private Guild guild;
|
||||||
|
private TextChannel channel;
|
||||||
|
private Message message;
|
||||||
|
private LocalDateTime expiryDate;
|
||||||
|
private ArrayList<String> answers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic constructor of the {@link Poll} entity
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll
|
||||||
|
* @param message The poll message created by the bot
|
||||||
|
* @param expiryDate The date when the poll should expire
|
||||||
|
*/
|
||||||
|
public Poll(String pollID, Message message, LocalDateTime expiryDate) {
|
||||||
|
this.pollID = pollID;
|
||||||
|
this.message = message;
|
||||||
|
this.guild = message.getGuild();
|
||||||
|
this.channel = message.getTextChannel();
|
||||||
|
this.expiryDate = expiryDate;
|
||||||
|
this.answers = pollAnswerManager.getAnswers(pollID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the poll id
|
||||||
|
*
|
||||||
|
* @return the poll id
|
||||||
|
*/
|
||||||
|
public String getPollID() {
|
||||||
|
return pollID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the guild
|
||||||
|
*
|
||||||
|
* @return the guild
|
||||||
|
*/
|
||||||
|
public Guild getGuild() {
|
||||||
|
return guild;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the channel
|
||||||
|
*
|
||||||
|
* @return the channel
|
||||||
|
*/
|
||||||
|
public TextChannel getChannel() {
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the message
|
||||||
|
*
|
||||||
|
* @return the message
|
||||||
|
*/
|
||||||
|
public Message getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date when the poll should expire
|
||||||
|
*
|
||||||
|
* @return the expiry date
|
||||||
|
*/
|
||||||
|
public LocalDateTime getExpiryDate() {
|
||||||
|
return expiryDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all answers
|
||||||
|
*
|
||||||
|
* @return all answers
|
||||||
|
*/
|
||||||
|
public ArrayList<String> getAnswers() {
|
||||||
|
return answers;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package xyz.sheepstar.poll.api.models;
|
||||||
|
|
||||||
|
import xyz.sheepstar.util.sql.SheepManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class PollAnswerManager extends SheepManager {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String tableName() {
|
||||||
|
return "poll_poll_answers";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tableFields() {
|
||||||
|
custom("poll_id").add();
|
||||||
|
custom("answer").add();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a single answer to the poll answers
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll you want to add the answer to
|
||||||
|
* @param answer The answer you want to add
|
||||||
|
*/
|
||||||
|
public void addAnswer(String pollID, String answer) {
|
||||||
|
insert().value("poll_id", pollID).value("answer", answer).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds multiple answers to the poll answers
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll you want to add the answer to
|
||||||
|
* @param answers The answers you want to add
|
||||||
|
*/
|
||||||
|
public void addAnswers(String pollID, ArrayList<String> answers) {
|
||||||
|
answers.forEach(answer -> addAnswer(pollID, answer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all answers from a poll
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll
|
||||||
|
*/
|
||||||
|
public void deleteAnswers(String pollID) {
|
||||||
|
delete().where("poll_id", pollID).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all answers from the poll
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll you want to get the answers from
|
||||||
|
* @return all answers from the poll
|
||||||
|
*/
|
||||||
|
public ArrayList<String> getAnswers(String pollID) {
|
||||||
|
return select().where("poll_id", pollID).getResult().getList("answer");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
package xyz.sheepstar.poll.api.models;
|
||||||
|
|
||||||
|
import de.gnmyt.sqltoolkit.types.SQLType;
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import xyz.sheepstar.poll.api.entities.Poll;
|
||||||
|
import xyz.sheepstar.util.sql.SheepManager;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class PollManager extends SheepManager {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String tableName() {
|
||||||
|
return "poll_polls";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tableFields() {
|
||||||
|
custom("poll_id").add();
|
||||||
|
custom("guild_id").add();
|
||||||
|
custom("channel_id").add();
|
||||||
|
custom("message_id").add();
|
||||||
|
custom("expiry").type(SQLType.DATETIME).allowNull(true).add();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the provided poll has been already created
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll you want to check
|
||||||
|
* @param guild The guild in which the poll has been created
|
||||||
|
* @return <code>true</code> if the provided poll has been already created, otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean isCreated(String pollID, Guild guild) {
|
||||||
|
return select().where("guild_id", guild.getId()).where("poll_id", pollID).getResult().exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the provided message is a poll
|
||||||
|
*
|
||||||
|
* @param message The message you want to check
|
||||||
|
* @return <code>true</code> if the message is a poll, otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean isPollMessage(Message message) {
|
||||||
|
return select().where("message_id", message.getId()).getResult().exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id from the poll by a message
|
||||||
|
*
|
||||||
|
* @param message The message you want to get the poll id from
|
||||||
|
* @return the id of the poll
|
||||||
|
*/
|
||||||
|
public String getIDByMessage(Message message) {
|
||||||
|
return select().where("message_id", message.getId()).getResult().getString("poll_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new poll for you
|
||||||
|
*
|
||||||
|
* @param pollID The id the poll should have
|
||||||
|
* @param message The already sent message of the poll (to edit if finished)
|
||||||
|
* @param expiry The date when the poll should expire, <code>NULL</code> if it should not close automatically
|
||||||
|
*/
|
||||||
|
public void createPoll(String pollID, Message message, Date expiry) {
|
||||||
|
if (isCreated(pollID, message.getGuild())) return;
|
||||||
|
insert()
|
||||||
|
.value("poll_id", pollID)
|
||||||
|
.value("guild_id", message.getGuild().getId())
|
||||||
|
.value("channel_id", message.getChannel().getId())
|
||||||
|
.value("message_id", message.getId())
|
||||||
|
.value("expiry", expiry)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a poll from the table
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll you want to delete
|
||||||
|
* @param guild The id of the guild the poll was created on
|
||||||
|
*/
|
||||||
|
public void deletePoll(String pollID, Guild guild) {
|
||||||
|
if (!isCreated(pollID, guild)) return;
|
||||||
|
delete().where("poll_id", pollID).where("guild_id", guild.getId()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all polls that <b>can</b> expire
|
||||||
|
*
|
||||||
|
* @return all polls that can expire
|
||||||
|
*/
|
||||||
|
public HashMap<String, LocalDateTime> getExpirablePolls() {
|
||||||
|
HashMap<String, LocalDateTime> expirable_polls = new HashMap<>();
|
||||||
|
select().getResult().getList().forEach(entry -> {
|
||||||
|
if (entry.get("expiry") != null)
|
||||||
|
expirable_polls.put((String) entry.get("poll_id"), (LocalDateTime) entry.get("expiry"));
|
||||||
|
});
|
||||||
|
return expirable_polls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a specific poll by id
|
||||||
|
*
|
||||||
|
* @param pollID The id of the poll you want to get
|
||||||
|
* @return the poll
|
||||||
|
*/
|
||||||
|
public Poll getPollById(String pollID) {
|
||||||
|
return new Poll(pollID, api.getJDA().getTextChannelById(select().where("poll_id", pollID)
|
||||||
|
.getResult().getString("channel_id")).retrieveMessageById(select().where("poll_id", pollID).getResult().getString("message_id")).complete(),
|
||||||
|
(LocalDateTime) select().where("poll_id", pollID).getResult().getObject("expiry"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package xyz.sheepstar.poll.commands;
|
||||||
|
|
||||||
|
import xyz.sheepstar.poll.api.controller.PollController;
|
||||||
|
import xyz.sheepstar.poll.core.PollCore;
|
||||||
|
import xyz.sheepstar.util.bot.command.Arguments;
|
||||||
|
import xyz.sheepstar.util.bot.command.GuildCommand;
|
||||||
|
import xyz.sheepstar.util.bot.command.GuildEventController;
|
||||||
|
import xyz.sheepstar.util.bot.command.PublicCommandException;
|
||||||
|
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
|
||||||
|
import xyz.sheepstar.util.bot.permission.PermissionNode;
|
||||||
|
|
||||||
|
@CommandMeta(aliases = "poll", subAliases = "close", description = "Closes a specific poll", permission = PermissionNode.ADMINISTRATOR)
|
||||||
|
public class ClosePollCommand extends GuildCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void usage() {
|
||||||
|
usage("poll_id", "The id of the poll you want to close").required(true).add();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PollController pollController = PollCore.getPollController();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(GuildEventController event, Arguments args) throws Exception {
|
||||||
|
if (pollController.endPoll(args.getString("poll_id"), event.getGuild())) {
|
||||||
|
event.success("poll.ended_successfully");
|
||||||
|
} else throw new PublicCommandException("poll.not_found");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buttonClick(GuildEventController event, String id) throws Exception {
|
||||||
|
if (!id.startsWith("end#")) return;
|
||||||
|
|
||||||
|
pollController.endPoll(id.split("#")[1], event.getGuild());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package xyz.sheepstar.poll.commands;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.ChannelType;
|
||||||
|
import net.dv8tion.jda.api.entities.GuildChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.TextChannel;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||||
|
import xyz.sheepstar.poll.api.controller.PollController;
|
||||||
|
import xyz.sheepstar.poll.core.PollCore;
|
||||||
|
import xyz.sheepstar.util.bot.command.Arguments;
|
||||||
|
import xyz.sheepstar.util.bot.command.GuildCommand;
|
||||||
|
import xyz.sheepstar.util.bot.command.GuildEventController;
|
||||||
|
import xyz.sheepstar.util.bot.command.PublicCommandException;
|
||||||
|
import xyz.sheepstar.util.bot.command.annotations.CommandMeta;
|
||||||
|
import xyz.sheepstar.util.bot.permission.PermissionNode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@CommandMeta(aliases = "poll", subAliases = "create", permission = PermissionNode.ADMINISTRATOR, description = "Creates a poll")
|
||||||
|
public class CreatePollCommand extends GuildCommand {
|
||||||
|
|
||||||
|
private PollController pollController = PollCore.getPollController();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void usage() {
|
||||||
|
usage("title", "The title of the poll").required(true).add();
|
||||||
|
|
||||||
|
usage("choice_1", "The first choice").required(true).add();
|
||||||
|
usage("choice_2", "The second choice").required(true).add();
|
||||||
|
|
||||||
|
|
||||||
|
usage("description", "The description of the poll").add();
|
||||||
|
|
||||||
|
usage("time", "When should the poll automatically be dissolved").add();
|
||||||
|
|
||||||
|
usage(OptionType.BOOLEAN, "close_button", "Should the poll show a close button? Otherwise you get the id to close the poll").add();
|
||||||
|
|
||||||
|
usage(OptionType.BOOLEAN, "multiple_choices", "Allows the user to click on multiple options").add();
|
||||||
|
|
||||||
|
usage(OptionType.CHANNEL, "channel", "The channel in which the message should be sent (for example if you have an poll channel)").add();
|
||||||
|
|
||||||
|
// All optional choices
|
||||||
|
|
||||||
|
usage("choice_3", "The third choice").add();
|
||||||
|
usage("choice_4", "The fourth choice").add();
|
||||||
|
usage("choice_5", "The fifth choice").add();
|
||||||
|
usage("choice_6", "The 6th choice").add();
|
||||||
|
usage("choice_7", "The 7th choice").add();
|
||||||
|
usage("choice_8", "The 8th choice").add();
|
||||||
|
usage("choice_9", "The 9th choice").add();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(GuildEventController event, Arguments args) throws Exception {
|
||||||
|
GuildChannel channel = args.exists("channel") ? args.getChannel("channel") : event.getChannel();
|
||||||
|
|
||||||
|
Date date = args.exists("time") ? getTimeFromString(args.getString("time")) : null;
|
||||||
|
|
||||||
|
boolean closeButton = !args.exists("close_button") || args.getBoolean("close_button");
|
||||||
|
|
||||||
|
boolean multipleChoices = args.exists("multiple_choices") && args.getBoolean("multiple_choices");
|
||||||
|
|
||||||
|
if (channel.getType() != ChannelType.TEXT)
|
||||||
|
throw new PublicCommandException("poll.error.channel.must_be_text");
|
||||||
|
|
||||||
|
ArrayList<String> answers = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 1; i < 10; i++)
|
||||||
|
if (args.exists("choice_" + i)) answers.add(args.getString("choice_" + i));
|
||||||
|
|
||||||
|
|
||||||
|
String pollID = pollController.createPoll((TextChannel) channel, date, args.getString("title"), args.getString("description"), answers, closeButton, multipleChoices);
|
||||||
|
|
||||||
|
event.success("poll.poll_created", channel.getAsMention(), pollID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package xyz.sheepstar.poll.core;
|
||||||
|
|
||||||
|
import xyz.sheepstar.poll.action.AutomaticCloseAction;
|
||||||
|
import xyz.sheepstar.poll.api.controller.PollController;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollAnswerManager;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollManager;
|
||||||
|
import xyz.sheepstar.poll.commands.ClosePollCommand;
|
||||||
|
import xyz.sheepstar.poll.commands.CreatePollCommand;
|
||||||
|
import xyz.sheepstar.poll.listener.MultipleReactionListener;
|
||||||
|
import xyz.sheepstar.util.bot.manager.ImportManager;
|
||||||
|
import xyz.sheepstar.util.module.SheepstarModule;
|
||||||
|
|
||||||
|
public class PollCore extends SheepstarModule {
|
||||||
|
|
||||||
|
private static PollController pollController;
|
||||||
|
|
||||||
|
private ImportManager importManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
importManager = new ImportManager(getAPI(), "poll");
|
||||||
|
|
||||||
|
registerManagers();
|
||||||
|
|
||||||
|
pollController = new PollController();
|
||||||
|
|
||||||
|
registerCommands();
|
||||||
|
registerActions();
|
||||||
|
registerListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all managers of the module
|
||||||
|
*/
|
||||||
|
public void registerManagers() {
|
||||||
|
registerTable(new PollAnswerManager());
|
||||||
|
registerTable(new PollManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all commands of the module
|
||||||
|
*/
|
||||||
|
public void registerCommands() {
|
||||||
|
importManager.registerCommand(new CreatePollCommand());
|
||||||
|
importManager.registerCommand(new ClosePollCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all listeners of the module
|
||||||
|
*/
|
||||||
|
public void registerListeners() {
|
||||||
|
importManager.registerListener(new MultipleReactionListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all actions of the module
|
||||||
|
*/
|
||||||
|
public void registerActions() {
|
||||||
|
new AutomaticCloseAction().start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the poll controller
|
||||||
|
*
|
||||||
|
* @return the poll controller
|
||||||
|
*/
|
||||||
|
public static PollController getPollController() {
|
||||||
|
return pollController;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package xyz.sheepstar.poll.listener;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollAnswerManager;
|
||||||
|
import xyz.sheepstar.poll.api.models.PollManager;
|
||||||
|
import xyz.sheepstar.util.bot.listener.GuildListener;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class MultipleReactionListener extends GuildListener {
|
||||||
|
|
||||||
|
private PollManager pollManager = (PollManager) table(PollManager.class);
|
||||||
|
private PollAnswerManager pollAnswerManager = (PollAnswerManager) table(PollAnswerManager.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the provided emoji is valid
|
||||||
|
*
|
||||||
|
* @param emoji The emoji you want to check
|
||||||
|
* @param message The message to get the size of the answers
|
||||||
|
* @return <code>true</code> if the emoji is valid, otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean isValidEmote(String emoji, Message message) {
|
||||||
|
for (int i = 0; i < pollAnswerManager.getAnswers(pollManager.getIDByMessage(message)).size(); i++) {
|
||||||
|
if (emoji.contains(String.valueOf(i + 1))) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGuildMessageReactionAdd(GuildMessageReactionAddEvent event) {
|
||||||
|
event.retrieveMessage().queue(message -> {
|
||||||
|
if (event.getUser().getId().equals(jda.getSelfUser().getId())) return;
|
||||||
|
if (!message.getAuthor().getId().equals(jda.getSelfUser().getId())) return;
|
||||||
|
if (!pollManager.isPollMessage(message)) return;
|
||||||
|
|
||||||
|
// TODO: Migrate to id instead of message
|
||||||
|
|
||||||
|
if (!event.getReactionEmote().isEmoji()) {
|
||||||
|
event.getReaction().removeReaction(event.getUser()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidEmote(event.getReactionEmote().getEmoji(), message)) {
|
||||||
|
event.getReaction().removeReaction(event.getUser()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] embedLines = message.getEmbeds().get(0).getDescription().split("\n");
|
||||||
|
|
||||||
|
for (String line : embedLines)
|
||||||
|
if (line.startsWith("**:ballot_box:") && line.contains("(")) return;
|
||||||
|
|
||||||
|
AtomicInteger reactAmount = new AtomicInteger();
|
||||||
|
message.getReactions().forEach(reaction -> reaction.retrieveUsers().queue(users -> users.forEach(user -> {
|
||||||
|
if (user.getId().equals(event.getUser().getId())) reactAmount.getAndIncrement();
|
||||||
|
|
||||||
|
if (reactAmount.get() > 1) {
|
||||||
|
event.getReaction().removeReaction(event.getUser()).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
3
SheepstarModules/PollV1/src/main/resources/module.yml
Normal file
3
SheepstarModules/PollV1/src/main/resources/module.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
main: xyz.sheepstar.poll.core.PollCore
|
||||||
|
name: poll
|
||||||
|
author: Mathias Wagner
|
Reference in New Issue
Block a user