Compare commits

..

29 Commits

Author SHA1 Message Date
BodgeMaster 4d04523cfe formatting, apparently 2022-02-22 21:17:46 +01:00
BodgeMaster 8c0abb092a trying to work around an arbitrary API limitation with a hack 2022-02-22 21:17:16 +01:00
BodgeMaster 95b38a39dd troubleshooting 2022-02-22 20:41:46 +01:00
BodgeMaster 41c7dc2831 trying to figure out while checking for "isYourself" doesn’t work 2022-02-22 20:26:12 +01:00
BodgeMaster 9590e717bb ignore own messages 2022-02-22 20:10:44 +01:00
BodgeMaster 4222046c20 added a debug message to see if the reaction listener works even if the reaction doesn’t get added 2022-02-22 20:03:32 +01:00
BodgeMaster d59774b0c2 trying to get the thing to add and recognize reactions 2022-02-22 20:02:16 +01:00
BodgeMaster a4a004cf94 doing the js thing in java 2022-02-22 20:00:15 +01:00
BodgeMaster 38803d519d testing reaction 2022-02-22 19:45:04 +01:00
BodgeMaster 3f36573c19 handle per-user question contingent 2022-02-22 18:50:34 +01:00
BodgeMaster e885b18cc5 dummy function 2022-02-22 18:50:19 +01:00
BodgeMaster 0de1cf9a67 updated the initial message the QuizHandler sends and removed useless passing of the Discord API object 2022-02-22 18:27:10 +01:00
BodgeMaster 113323da00 reworked how users are handled 2022-02-22 18:09:37 +01:00
BodgeMaster d5201044ec start over 2022-02-22 17:54:56 +01:00
BodgeMaster 5a37675753 fixed typo 2022-02-21 12:54:01 +01:00
BodgeMaster 339a4dd55c jdbc string wrong? 2022-02-21 12:50:51 +01:00
BodgeMaster a97424041c hack: force load QuizBackend 2022-02-21 12:48:26 +01:00
BodgeMaster 9f4421f448 move comments containing db structure to a more appropriate place 2022-02-21 12:46:16 +01:00
BodgeMaster aa0bcd3e99 print message to System.err because we want to see them on `systemctl status hacky` 2022-02-21 12:41:04 +01:00
BodgeMaster b7b6c2bda9 started MySQL implementation 2022-02-21 12:35:35 +01:00
BodgeMaster 75b9530029 added DB information 2022-02-20 22:03:36 +01:00
BodgeMaster 56eaf9a9b3 added TODOs for many things that need to be done in the backend 2022-02-20 21:15:50 +01:00
BodgeMaster 06160852fc fuck it, here’s a "fixed typo" commit 2022-02-20 19:50:39 +01:00
BodgeMaster 9738530b4e forgot another thing in the API :( 2022-02-20 19:50:04 +01:00
BodgeMaster 8f2636a283 added a todo 2022-02-20 19:48:11 +01:00
BodgeMaster 5628b3847c get rid of some stuff from the example bot 2022-02-20 19:47:48 +01:00
BodgeMaster 02649a0365 Merge branch 'milan' into bodgemaster 2022-02-20 19:44:59 +01:00
Shwoomple 01d023a2bf completing merge 2022-02-21 00:00:42 +05:30
Shwoomple bd9eae58cd commit for merge 2022-02-20 23:59:54 +05:30
5 changed files with 170 additions and 89 deletions

11
pom.xml
View File

@ -12,6 +12,17 @@
<version>3.4.0</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>5.1.1</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>

View File

@ -4,37 +4,55 @@ import org.javacord.api.DiscordApi;
import org.javacord.api.DiscordApiBuilder;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Scanner;
public class Main {
public static final String startupTime = String.format("%1$tY-%1$tm-%1$td %1$tI:%1$tM:%1$tS%1$tp UTC%1$tz", new Date());
private static String[] commandLineArguments;
private static long userID;
public static void main(String[] args) {
String startupTime = String.format("%1$tY-%1$tm-%1$td %1$tI:%1$tM:%1$tS%1$tp UTC%1$tz", new Date());
// [0] token, [1] db username, [2] db password
commandLineArguments = args;
// Insert your bot's token here
String token = args[0];
// checks every 7500 ms if a deployment happened, if so shuts down the bot
CheckDeploy check = new CheckDeploy(7500, "/var/www/deployment/Hacky-Quizbot/id.txt");
check.start();
DiscordApi api = new DiscordApiBuilder().setToken(token).login().join();
//Trivia management
Member member = new Member(api);
//TODO: remove, this is just a way of force loading of the QuizBackend class while it isnt being loaded automatically
QuizBackend backend = new QuizBackend();
// Add a listener which answers with "Pong!" if someone writes "!ping"
DiscordApi api = new DiscordApiBuilder().setToken(commandLineArguments[0]).login().join();
userID = api.getYourself().getId();
System.err.println("Logging in as "+api.getYourself().getDiscriminatedName());
//user management
ArrayList<QuizHandler> QuizHandlers = new ArrayList<QuizHandler>();
// commands
api.addMessageCreateListener(event -> {
if (event.getMessageContent().equalsIgnoreCase("!ping")) {
event.getChannel().sendMessage("Pong!\nHacky the quiz bot has been running since "+startupTime);
}
if (event.getMessageContent().equalsIgnoreCase("!trivia")) {
QuizHandlers.add(new QuizHandler(event.getMessageAuthor().asUser().get()));
}
});
// Print the invite url of your bot
System.out.println("You can invite the bot by using the following url: " + api.createBotInvite());
}
public static String getCommandLineArgument(int index) {
return commandLineArguments[index];
}
public static long getUserID() {
return userID;
}
//Deploy check thread
public static class CheckDeploy extends Thread {
private int interval;
private String id;

View File

@ -1,23 +0,0 @@
package linux.general.hackyquizbot;
import org.javacord.api.DiscordApi;
import org.javacord.api.entity.user.User;
public class Member {
private DiscordApi api;
private User user;
public Member(DiscordApi api) {
this.api = api;
this.api.addMessageCreateListener(event ->{
if(event.getMessageContent().equalsIgnoreCase("!trivia")) {
if(event.getMessageAuthor().asUser().isPresent()) {
this.user = event.getMessageAuthor().asUser().get();
this.user.sendMessage("Welcome to hell");
}
}
});
}
}

View File

@ -1,69 +1,87 @@
package linux.general.hackyquizbot;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class QuizBackend {
private static final String dbUsername = Main.getCommandLineArgument(1);
private static final String dbPassword = Main.getCommandLineArgument(2);
private static final String dbName = "jdbc:mariadb://localhost/quizbot"; //we can make this configurable later
private static Connection dbConnection;
private static Statement statement;
// temporary hack to get something working
private static boolean once = true;
// CREATE TABLE questions(id INT(32) AUTO_INCREMENT PRIMARY KEY, question TEXT, max_score INT(8));
// CREATE TABLE answer_choices(id INT(32), answer VARCHAR(2048), correctness BOOLEAN);
// CREATE TABLE user_answers(id INT(32), given_answer VARCHAR(2048), discord_user VARCHAR(1024));
// CREATE TABLE categories(id INT(32), category VARCHAR(1024));
private static Question[] allQuestions;
private static ArrayList<String> categories;
static {
categories = new ArrayList<String>();
try {
dbConnection = DriverManager.getConnection(dbName, dbUsername, dbPassword);
System.err.println("Database connected.");
statement = dbConnection.createStatement();
System.err.println("Statement object created.");
// populate categories
ResultSet resultSet = statement.executeQuery("SELECT category FROM categories;");
while (resultSet.next()) {
String category = resultSet.getString("category");
if (!categories.contains(category)) {
categories.add(category);
}
}
System.err.print("Loaded categories:");
for (int i = 0; i<categories.size(); i++) {
System.err.print(" " + categories.get(i));
}
System.err.println();
//TODO: populate allQuestions
}
catch (SQLException e) {
System.err.println("Error while interacting with DB.");
e.printStackTrace();
System.exit(1);
}
}
public static String[] getCategories() {
return null;
return (String[]) categories.toArray();
}
public static Question getRandomQuestionForCategory(String category) {
return null;
}
public static int getScoreForUser(String discordUserID) {
return 0;
//TODO: user aware random question picker
//TODO: function to determine whether a user should get more questions
public static boolean shouldGetMoreQuestions(String discordUserID) {
if (once) {
once=false;
return true;
}
return false;
}
//TODO: function to get a users score
public static class Question {
/**
*
* @param question The string for the question text
* @param answers The multiple choice answers
* @param mask A mask to be layed over answers to decide which answers are correct and which arent
*/
public Question(String question, String[] answers, boolean[] mask) {
//TODO: get full question text with multiple choice answers
}
/**
* @return the full question text including multiple choice options with letters that correspond to getValidResponses()
*/
public String getQuestionTextWithOptions() {
return null;
}
/**
* @return a character array containing all the valid answers
*/
public char[] getValidResponses() {
return null;
}
//TODO: get possible answers (scrambled per user)
public char[] getCorrectResponses() {
return null;
}
/**
* This is used to send the users reply back to the backend. Can be called
* multiple times to add answers for questions with multiple possible answers.
*
* @param discordUserID
* @param answer
*/
public void addAnswer(String discordUserID, char answer) {
}
/**
* Used to balance easy and difficult questions. Difficult questions will have a
* higher value so if someone gets a bunch of them they will get less questions
* overall.
*
* @return
*/
public int getQuestionScoreValue() {
return 0;
}
//TODO: get correct answers (scrambled per user)
//TODO: submit answer
}
}

View File

@ -0,0 +1,57 @@
package linux.general.hackyquizbot;
import java.util.concurrent.ExecutionException;
import org.javacord.api.entity.message.Message;
import org.javacord.api.entity.user.User;
import com.vdurmont.emoji.EmojiParser;
import linux.general.hackyquizbot.QuizBackend.Question;
public class QuizHandler {
private User user;
private Question lastQuestion;
public QuizHandler(User user) {
this.user = user;
if (QuizBackend.shouldGetMoreQuestions(user.getIdAsString())) {
try {
Message message = user.sendMessage("Hi! I'm Hacky.\n"
+ "I will be sending you a bunch of multiple-choice questions. "
+ "You can answer by selecting one or more of the reactions on the message and confirm your selection by selecting the :white_check_mark: reaction."
+ " Please contact @BodgeMaster#0344 if there are any issues.\n\n"
+ "Select the :white_check_mark: reaction to continue.").get();
message.addReaction(EmojiParser.parseToUnicode(":white_check_mark:"));
message.addReactionAddListener(event -> {
// HACK: Testing for an exception to find out whether the event was caused by a
// user or by the bot itself because reactions added by the bot allow to check
// for user where reactions added by actual users dont.
try {
if (!event.getUser().get().isYourself() && event.getReaction().get().getEmoji()
.equalsEmoji(EmojiParser.parseToUnicode(":white_check_mark:"))) {
event.getMessage().get().getChannel().sendMessage(
"This should not work. If you ever see this message, please inform @BodgeMaster#0344 that there is more to this arbitrary limitation in the Discord API than expected.");
}
} catch (Exception e) {
System.err.println("Assuming the reaction event was caused by the user...");
System.err.println("User ID: "+this.user.getIdAsString()); //test if we can get the user ID that way
}
// TODO: trigger question dispatch
// TODO: remove ReactionAddListener
});
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
System.err.println("Something went wrong while trying to get the sent message object.");
e.printStackTrace();
}
// TODO: add white question mark reaction
// TODO: add reaction handler (preferably to channel?)
} else {
user.sendMessage(
"You have already had the maximum amount of questions that you can get with the current question set.");
}
}
}