diff --git a/build.gradle b/build.gradle index 6c22434..4d6af1b 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'org.javacord:javacord:3.0.0' + implementation 'org.javacord:javacord:3.0.5' compileOnly('org.projectlombok:lombok:1.18.4') annotationProcessor 'org.projectlombok:lombok:1.18.4' @@ -55,6 +55,8 @@ dependencies { 'javax.activation:activation:1.1', 'org.toile-libre.libe:curl:0.0.23', + + 'com.github.origma:Google-PerspectiveAPI-Java-Client:0.0.5', 'com.google.api-client:google-api-client:1.24.1', diff --git a/src/main/java/com/mazawrath/beanbot/Main.java b/src/main/java/com/mazawrath/beanbot/Main.java index 0938b50..857d26e 100644 --- a/src/main/java/com/mazawrath/beanbot/Main.java +++ b/src/main/java/com/mazawrath/beanbot/Main.java @@ -7,6 +7,7 @@ import com.mazawrath.beanbot.commands.copypasta.GiveModCommand; import com.mazawrath.beanbot.commands.beancoin.*; import com.mazawrath.beanbot.commands.copypasta.*; +import com.mazawrath.beanbot.commands.googleperspectiveapi.ToxicCommand; import com.mazawrath.beanbot.commands.googlevision.AnalyzeCommand; import com.mazawrath.beanbot.commands.image.*; import com.mazawrath.beanbot.commands.poll.PollCommand; @@ -14,6 +15,7 @@ import com.mazawrath.beanbot.utilities.*; import com.mazawrath.beanbot.commands.admin.*; import com.mazawrath.beanbot.utilities.jersey.RestServer; +import com.mazawrath.beanbot.utilities.pesrspectiveapi_requests.MessageRequest; import com.rethinkdb.net.Connection; import de.btobastian.sdcf4j.CommandHandler; import de.btobastian.sdcf4j.handler.JavacordHandler; @@ -45,6 +47,7 @@ public static void main(String[] args) { Thread restServer = new Thread(new RestServer()); restServer.start(); Twitch twitch = new Twitch(args[1], args[2], conn); + MessageRequest.apiKey = args[3]; new DiscordApiBuilder().setToken(args[0]).login().thenAccept(api -> { System.out.println("You can invite the bot by using the following url: " + api.createBotInvite()); @@ -74,9 +77,10 @@ public static void main(String[] args) { // beanCoin cmdHandler.registerCommand(new BeanBalanceCommand(points)); cmdHandler.registerCommand(new BeanFreeCommand(points)); - cmdHandler.registerCommand(new BeanBetCommand(points)); +// cmdHandler.registerCommand(new BeanBetCommand(points)); cmdHandler.registerCommand(new BeanTransferCommand(points)); cmdHandler.registerCommand(new BeanBoardCommand(points)); + cmdHandler.registerCommand(new BeanTriviaCommand(points, new Trivia())); // Bean Market cmdHandler.registerCommand(new BeanMarketCommand()); cmdHandler.registerCommand(new BeanInvestCommand(points, stockMarket)); @@ -94,6 +98,8 @@ public static void main(String[] args) { cmdHandler.registerCommand(new HistogramCommand(points)); // Google Vision Commands cmdHandler.registerCommand(new AnalyzeCommand(points)); + // Perspective AI Commands + cmdHandler.registerCommand(new ToxicCommand(points)); // Poll Commands cmdHandler.registerCommand(new PollCommand(points)); cmdHandler.registerCommand(new StrawPollCommand(points)); diff --git a/src/main/java/com/mazawrath/beanbot/commands/admin/AdminPostChangeLogCommand.java b/src/main/java/com/mazawrath/beanbot/commands/admin/AdminPostChangeLogCommand.java index 0f02b5f..c676e2b 100644 --- a/src/main/java/com/mazawrath/beanbot/commands/admin/AdminPostChangeLogCommand.java +++ b/src/main/java/com/mazawrath/beanbot/commands/admin/AdminPostChangeLogCommand.java @@ -40,26 +40,24 @@ public void onCommand(String[] args, DiscordApi api, ServerTextChannel serverTex private String getRecentChangeLog() { return "**New beanBOT update released.**\n" + - "Release can be found on https://github.com/Mazawrath/beanBOT/releases/tag/v3.5.0\n" + - "Detailed changelog can be found on https://github.com/Mazawrath/beanBOT/compare/v3.4.0...v3.5.0\n" + + "Release can be found on https://github.com/Mazawrath/beanBOT/releases/tag/v3.6.0\n" + + "Detailed changelog can be found on https://github.com/Mazawrath/beanBOT/compare/v3.5.0...v3.6.0\n" + "\n" + - "**v3.5.0**\n" + + "**v3.6.0**\n" + "**New**\n" + - "\t- Added photo manipulation.\n" + - "\t\t- Added `.deepfry`.\n" + - "\t\t- Added `.emboss`.\n" + - "\t\t- Added `.invert`.\n" + - "\t\t- Added `.diffuse`.\n" + - "\t\t- Added `.mosaic`.\n" + - "\t\t- Added `.sepia`.\n" + - "\t- Added polling.\n" + - "\t\t- Added `.poll`.\n" + - "\t\t- Added `.strawpoll`.\n" + + "\t- Added `.beantrivia`.\n" + + "\t\t- Earn beanCoin by answering trivia questions! After using the command you will have 8 seconds to react to the correct answer, anyone can participate and win beanCoin. Don't try to cheat, you will regret it!\n" + + "\t- Added `.toxic`.\n" + + "\t\t- Analyze messages to measure their toxicity. Leave the command blank to analyze the most recent message. Enter text in to analyze that text. Or mention a user with `@` to analyze their most recent message.\n" + "**Changes**\n" + - "\t- Changed limit to how many lottery tickets can be bought at the start of a new drawing from 200 to 100.\n" + - "\t\t- After every drawing without a winner users will be able to buy up to 50 more tickets.\n" + + "\t- Disabled `.beanbet`.\n" + + "\t- User now start with ß1000.00 when they use a command that uses beanCoin.\n" + + "\t- Changed amount users received from `.beanfree` from ß25.69 to ß50.00.\n" + + "\t- Changed the cooldown of `.beanfree` from 24 hours to 7 days.\n" + + "\t- Changed price of standard commands from ß2.00 to ß10.00.\n" + + "\t- Changed price of special commands from ß10 to ß15.\n" + + "\t- Changed price of bean lottery tickets from ß40 to ß45.\n" + "**Bug Fixes**\n" + - "\t- Fixed a file reading issue with `.analyze`.\n" + - "\t- Fixed a issue with records getting added to the lottery database when they did not buy a ticket."; + "\t- Fixed an issue with bean lottery crashing if someone tried buying too many tickets when they didn't have any in the first place."; } } \ No newline at end of file diff --git a/src/main/java/com/mazawrath/beanbot/commands/beancoin/BeanFreeCommand.java b/src/main/java/com/mazawrath/beanbot/commands/beancoin/BeanFreeCommand.java index 1fb65ef..5b21be8 100644 --- a/src/main/java/com/mazawrath/beanbot/commands/beancoin/BeanFreeCommand.java +++ b/src/main/java/com/mazawrath/beanbot/commands/beancoin/BeanFreeCommand.java @@ -11,6 +11,7 @@ import java.text.SimpleDateFormat; import java.util.Date; +import java.util.concurrent.TimeUnit; public class BeanFreeCommand implements CommandExecutor { private Points points; @@ -41,7 +42,7 @@ public void onCommand(ServerTextChannel serverTextChannel, User author, Server s String dateStart = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss") .format(new java.util.Date(System.currentTimeMillis())); String dateStop = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss") - .format(new java.util.Date(timeLeft + 24 * 60 * 60 * 1000)); + .format(new java.util.Date(timeLeft + Points.FREE_COIN_TIME_LIMIT)); //HH converts hour in 24 hours format (0-23), day calculation SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); @@ -56,17 +57,16 @@ public void onCommand(ServerTextChannel serverTextChannel, User author, Server s //in milliseconds long diff = d2.getTime() - d1.getTime(); - long diffMinutes = diff / (60 * 1000) % 60; - long diffHours = diff / (60 * 60 * 1000) % 24; - - if (diffHours == 1) - message.append(diffHours).append(" hour "); - else - message.append(diffHours).append(" hours "); - if (diffMinutes == 1) - message.append(diffMinutes).append(" minute."); - else - message.append(diffMinutes).append(" minutes."); + long days = TimeUnit.MILLISECONDS.toDays(diff); + diff -= TimeUnit.DAYS.toMillis(days); + long hours = TimeUnit.MILLISECONDS.toHours(diff); + diff -= TimeUnit.HOURS.toMillis(hours); + long minutes = TimeUnit.MILLISECONDS.toMinutes(diff); + diff -= TimeUnit.MINUTES.toMillis(minutes); + long seconds = TimeUnit.MILLISECONDS.toSeconds(diff); + + message.append(String.format("%d days, %d hours, %d mins, and %d seconds.", + days, hours, minutes, seconds)); serverTextChannel.sendMessage(message.toString()); diff --git a/src/main/java/com/mazawrath/beanbot/commands/beancoin/BeanTriviaCommand.java b/src/main/java/com/mazawrath/beanbot/commands/beancoin/BeanTriviaCommand.java new file mode 100644 index 0000000..a5739c8 --- /dev/null +++ b/src/main/java/com/mazawrath/beanbot/commands/beancoin/BeanTriviaCommand.java @@ -0,0 +1,236 @@ +package com.mazawrath.beanbot.commands.beancoin; + +import com.mazawrath.beanbot.utilities.Points; +import com.mazawrath.beanbot.utilities.PointsUser; +import com.mazawrath.beanbot.utilities.SentryLog; +import com.mazawrath.beanbot.utilities.Trivia; +import com.vdurmont.emoji.EmojiParser; +import de.btobastian.sdcf4j.Command; +import de.btobastian.sdcf4j.CommandExecutor; +import io.sentry.Sentry; +import org.javacord.api.DiscordApi; +import org.javacord.api.entity.channel.ServerTextChannel; +import org.javacord.api.entity.message.Message; +import org.javacord.api.entity.message.Reaction; +import org.javacord.api.entity.message.embed.EmbedBuilder; +import org.javacord.api.entity.server.Server; +import org.javacord.api.entity.user.User; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class BeanTriviaCommand implements CommandExecutor { + private Points points; + private Trivia trivia; + + public BeanTriviaCommand(Points points, Trivia trivia) { + this.points = points; + this.trivia = trivia; + } + + @Command( + aliases = {"beantrivia", "cointrivia"}, + usage = "beantrivia", + description = "Post a trivia question that anyone can answer to earn beanCoin", + privateMessages = false + ) + + public void onCommand(ServerTextChannel serverTextChannel, DiscordApi api, User author, Server server) { + SentryLog.addContext(null, author, server); + + long timeLeft = points.useTriviaQuestion(new PointsUser(author, server), false); + + if (timeLeft == 0) { + String emojiCorrectAnswer; + + JSONObject jsonObject = trivia.getTrivia(); + JSONArray results = (JSONArray) jsonObject.get("results"); + JSONObject questionObject = (JSONObject) results.get(0); + + String question = new String(Base64.getDecoder().decode(questionObject.get("question").toString())); + String difficulty = new String(Base64.getDecoder().decode(questionObject.get("difficulty").toString())); + String category = new String(Base64.getDecoder().decode(questionObject.get("category").toString())); + String correctAnswer = new String(Base64.getDecoder().decode(questionObject.get("correct_answer").toString())); + + // I'm honestly ashamed of this code, please forgive me if you're thinking about hiring me and run across this snippet. + JSONArray incorrectAnswersObject = (JSONArray) questionObject.get("incorrect_answers"); + String[] incorrectAnswers = new String[incorrectAnswersObject.size()]; + for (int i = 0; i < incorrectAnswers.length; i++) + incorrectAnswers[i] = new String(Base64.getDecoder().decode(incorrectAnswersObject.get(i).toString())); + + ArrayList answers = new ArrayList<>(); + answers.add(correctAnswer); + Collections.addAll(answers, incorrectAnswers); + Collections.shuffle(answers); + int correctAnswerIndex = answers.indexOf(correctAnswer); + switch (correctAnswerIndex) { + case 0: + emojiCorrectAnswer = ":one:"; + break; + case 1: + emojiCorrectAnswer = ":two:"; + break; + case 2: + emojiCorrectAnswer = ":three:"; + break; + case 3: + emojiCorrectAnswer = ":four:"; + break; + default: + serverTextChannel.sendMessage("Attempted to send trivia message but failed."); + return; + } + EmbedBuilder embed = new EmbedBuilder() + .setTitle(question) + .setDescription("Category: " + category) + .setFooter("Difficulty: " + difficulty); + for (int i = 0; i < answers.size(); i++) + embed.addField("Answer " + (i + 1), answers.get(i)); + try { + Message triviaMessage = serverTextChannel.sendMessage(embed).get(); + triviaMessage.addReaction(EmojiParser.parseToUnicode(":one:")); + triviaMessage.addReaction(EmojiParser.parseToUnicode(":two:")); + triviaMessage.addReaction(EmojiParser.parseToUnicode(":three:")); + triviaMessage.addReaction(EmojiParser.parseToUnicode(":four:")); + + Thread.sleep(8000); + List reactions = triviaMessage.getReactions(); + + ArrayList contestants = new ArrayList<>(); + ArrayList winners = new ArrayList<>(); + ArrayList cheaters = new ArrayList<>(); + + // Get the winners + for (int i = 0; i < reactions.size(); i++) { + if (reactions.get(i).getEmoji().equalsEmoji(EmojiParser.parseToUnicode(emojiCorrectAnswer))) { + Reaction correctEmoji = reactions.get(i); + for (int j = 0; j < correctEmoji.getUsers().get().size(); j++) { + if (correctEmoji.getUsers().get().get(j) != api.getYourself()) + winners.add(correctEmoji.getUsers().get().get(j)); + } + } else if (reactions.get(i).getUsers().get().contains(api.getYourself())) { + Reaction incorrectEmoji = reactions.get(i); + for (int j = 0; j < incorrectEmoji.getUsers().get().size(); j++) { + if (incorrectEmoji.getUsers().get().get(j) != api.getYourself()) + contestants.add(incorrectEmoji.getUsers().get().get(j)); + } + } + } + + // Check for cheaters + for (int i = 0; i < reactions.size(); i++) { + if (!reactions.get(i).getEmoji().equalsEmoji(EmojiParser.parseToUnicode(emojiCorrectAnswer)) && reactions.get(i).getUsers().get().contains(api.getYourself())) { + Reaction correctEmoji = reactions.get(i); + for (int j = 0; j < correctEmoji.getUsers().get().size(); j++) { + for (int k = 0; k < winners.size(); k++) { + // Found a cheater! + if (correctEmoji.getUsers().get().get(j) == winners.get(k)) { + winners.remove(winners.get(k)); + cheaters.add(correctEmoji.getUsers().get().get(j)); + } + } + } + } + } + // Anyone who reacted more then once but got it wrong also cheated + ArrayList duplicates = (ArrayList) getDuplicate(contestants); + for (User duplicate : duplicates) { + if (!cheaters.contains(duplicate)) + cheaters.add(duplicate); + } + + StringBuilder winnersMessage = new StringBuilder(); + + if (winners.size() == 0) { + winnersMessage.append("No one got the answer correct!\n"); + } else { + winnersMessage.append("The following users have won:\n"); + for (int i = 0; i < winners.size(); i++) { + winnersMessage.append(winners.get(i).getDisplayName(server)).append(" got the correct answer!\n"); + points.depositCoins(new PointsUser(author, server), Points.TRIVIA_CORRECT_ANSWER); + } + } + winnersMessage.append("\n"); + for (int i = 0; i < cheaters.size(); i++) { + winnersMessage.append(cheaters.get(i).getDisplayName(server)).append(" has cheated and has been fined ").append(Points.pointsToString(Points.TRIVIA_CHEAT_FINE)).append("!\n"); + if (points.checkBalance(new PointsUser(cheaters.get(i), server)).compareTo(Points.TRIVIA_CHEAT_FINE) <= 0) + points.makePurchase(new PointsUser(cheaters.get(i), server), new PointsUser(api.getYourself(), server), points.checkBalance(new PointsUser(cheaters.get(i), server))); + else + points.makePurchase(new PointsUser(cheaters.get(i), server), new PointsUser(api.getYourself(), server), Points.TRIVIA_CHEAT_FINE); + // Reset their trivia too. + points.useTriviaQuestion(new PointsUser(author, server), true); + } + if (cheaters.size() != 0) + winnersMessage.append("\n"); + winnersMessage.append("The correct answer was: ").append(correctAnswer).append(".\nAnyone who answered correctly received ").append(Points.pointsToString(Points.TRIVIA_CORRECT_ANSWER)).append("."); + + serverTextChannel.sendMessage(winnersMessage.toString()); + } catch (Exception e) { + serverTextChannel.sendMessage("Attempted to send trivia message but failed."); + return; + } + } else { + StringBuilder message = new StringBuilder(); + + message.append("You have already did trivia today. You can use your trivia again in "); + + String dateStart = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss") + .format(new java.util.Date(System.currentTimeMillis())); + String dateStop = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss") + .format(new java.util.Date(timeLeft + Points.FREE_COIN_TIME_LIMIT)); + + //HH converts hour in 24 hours format (0-23), day calculation + SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); + + Date d1; + Date d2; + + try { + d1 = format.parse(dateStart); + d2 = format.parse(dateStop); + + //in milliseconds + long diff = d2.getTime() - d1.getTime(); + + long days = TimeUnit.MILLISECONDS.toDays(diff); + diff -= TimeUnit.DAYS.toMillis(days); + long hours = TimeUnit.MILLISECONDS.toHours(diff); + diff -= TimeUnit.HOURS.toMillis(hours); + long minutes = TimeUnit.MILLISECONDS.toMinutes(diff); + diff -= TimeUnit.MINUTES.toMillis(minutes); + long seconds = TimeUnit.MILLISECONDS.toSeconds(diff); + + message.append(String.format("%d hours, %d mins, and %d seconds.", + hours, minutes, seconds)); + + serverTextChannel.sendMessage(message.toString()); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + Sentry.clearContext(); + } + + public static List getDuplicate(Collection list) { + + final List duplicatedObjects = new ArrayList(); + Set set = new HashSet() { + @Override + public boolean add(T e) { + if (contains(e)) { + duplicatedObjects.add(e); + } + return super.add(e); + } + }; + for (T t : list) { + set.add(t); + } + return duplicatedObjects; + } +} \ No newline at end of file diff --git a/src/main/java/com/mazawrath/beanbot/commands/googleperspectiveapi/ToxicCommand.java b/src/main/java/com/mazawrath/beanbot/commands/googleperspectiveapi/ToxicCommand.java new file mode 100644 index 0000000..fc026ac --- /dev/null +++ b/src/main/java/com/mazawrath/beanbot/commands/googleperspectiveapi/ToxicCommand.java @@ -0,0 +1,99 @@ +package com.mazawrath.beanbot.commands.googleperspectiveapi; + +import com.mazawrath.beanbot.utilities.Points; +import com.mazawrath.beanbot.utilities.PointsUser; +import com.mazawrath.beanbot.utilities.SentryLog; +import com.mazawrath.beanbot.utilities.pesrspectiveapi_requests.MessageRequest; +import de.btobastian.sdcf4j.Command; +import de.btobastian.sdcf4j.CommandExecutor; +import io.sentry.Sentry; +import org.javacord.api.DiscordApi; +import org.javacord.api.entity.channel.ServerTextChannel; +import org.javacord.api.entity.message.Message; +import org.javacord.api.entity.message.MessageSet; +import org.javacord.api.entity.message.embed.EmbedBuilder; +import org.javacord.api.entity.server.Server; +import org.javacord.api.entity.user.User; + +public class ToxicCommand implements CommandExecutor { + private Points points; + + public ToxicCommand(Points points) { + this.points = points; + } + + @Command( + aliases = {"toxic"}, + usage = "toxic [user]/[message]", + description = "Detects how toxic a message is", + privateMessages = false + ) + + public void onCommand(String[] args, DiscordApi api, Message discordMessage, ServerTextChannel serverTextChannel, User author, Server server) { + SentryLog.addContext(args, author, server); + + PointsUser user = new PointsUser(author, server); + String userName = ""; + StringBuilder message = new StringBuilder(); + + if (!points.canMakePurchase(user, Points.COMMAND_COST)) { + serverTextChannel.sendMessage("You do not have enough beanCoin to use this command."); + return; + } + + if (args.length != 0) { + // Get users most recent message + if (args[0].contains("@")) { + userName = discordMessage.getMentionedUsers().get(0).getDisplayName(server); + + MessageSet previousMessages = discordMessage.getMessagesBefore(20).join(); + for (Message previousMessage : previousMessages.descendingSet()) { + if (previousMessage.getUserAuthor().get().getIdAsString().equals(discordMessage.getMentionedUsers().get(0).getIdAsString()) && !previousMessage.getContent().isEmpty()) { + message.append(previousMessage.getContent()); + break; + } + } + if (message.toString().isEmpty()) { + serverTextChannel.sendMessage("Could not find any recent messages from this person."); + return; + } + } else { + userName = author.getDisplayName(server); + for (int i = 0; i < args.length; i++) { + message.append(args[i]); + if (i + 1 != args.length) + message.append(" "); + } + } + } else { + MessageSet previousMessages = discordMessage.getMessagesBefore(20).join(); + for (Message previousMessage : previousMessages.descendingSet()) { + if (!previousMessage.getContent().isEmpty()) { + userName = previousMessage.getUserAuthor().get().getDisplayName(server); + message.append(previousMessage.getContent()); + break; + } + } + if (message.toString().isEmpty()) { + serverTextChannel.sendMessage("Could not find any recent messages."); + return; + } + } + + MessageRequest messageAnalysis = new MessageRequest(message.toString()); + + EmbedBuilder embed = new EmbedBuilder() + .setTitle("Message Analysis") + .addField("Message", message.toString()) + .addInlineField("Message From", userName) + .addInlineField("Toxic Probability", String.format("%.0f%%", messageAnalysis.getToxicityProb() * 100)) + .addInlineField("Identity Attack Probability", String.format("%.0f%%", messageAnalysis.getIdentityAttackProb() * 100)) + .addInlineField("Insult Probability", String.format("%.0f%%", messageAnalysis.getInsultProb() * 100)) + .addInlineField("Incoherent Probability", String.format("%.0f%%", messageAnalysis.getIncoherentProb() * 100)) + .addInlineField("Sexually Explicit Probability", String.format("%.0f%%", messageAnalysis.getSexuallyExplicitProb() * 100)); + serverTextChannel.sendMessage(embed); + + points.makePurchase(user, new PointsUser(api.getYourself(), server), Points.COMMAND_COST); + Sentry.clearContext(); + } +} diff --git a/src/main/java/com/mazawrath/beanbot/commands/googlevision/AnalyzeCommand.java b/src/main/java/com/mazawrath/beanbot/commands/googlevision/AnalyzeCommand.java index b23e04d..eb6dd87 100644 --- a/src/main/java/com/mazawrath/beanbot/commands/googlevision/AnalyzeCommand.java +++ b/src/main/java/com/mazawrath/beanbot/commands/googlevision/AnalyzeCommand.java @@ -2,6 +2,7 @@ import com.mazawrath.beanbot.utilities.ImageRequest; import com.mazawrath.beanbot.utilities.Points; +import com.mazawrath.beanbot.utilities.PointsUser; import com.mazawrath.beanbot.utilities.SentryLog; import de.btobastian.sdcf4j.Command; import de.btobastian.sdcf4j.CommandExecutor; @@ -36,6 +37,8 @@ public AnalyzeCommand(Points points) { public void onCommand(String[] args, Message message, DiscordApi api, ServerTextChannel serverTextChannel, User author, Server server) { SentryLog.addContext(args, author, server); + PointsUser user = new PointsUser(author, server); + URL url; if (message.getAttachments().size() != 0) url = message.getAttachments().get(0).getUrl(); @@ -51,11 +54,13 @@ else if (args.length > 0) { return; } - if (!points.removePoints(author.getIdAsString(), api.getYourself().getIdAsString(), server.getIdAsString(), Points.GOOGLE_VISION_COST)) { + if (!points.canMakePurchase(user, Points.GOOGLE_VISION_COST)) { serverTextChannel.sendMessage("You do not have enough beanCoin for this command"); return; } + points.makePurchase(user, new PointsUser(api.getYourself(), server), Points.GOOGLE_VISION_COST); + ImageRequest imageRequest; try (NonThrowingAutoCloseable typingIndicator = serverTextChannel.typeContinuouslyAfter(5, TimeUnit.MICROSECONDS)) { diff --git a/src/main/java/com/mazawrath/beanbot/utilities/Lottery.java b/src/main/java/com/mazawrath/beanbot/utilities/Lottery.java index af3bfae..7edead3 100644 --- a/src/main/java/com/mazawrath/beanbot/utilities/Lottery.java +++ b/src/main/java/com/mazawrath/beanbot/utilities/Lottery.java @@ -58,7 +58,8 @@ private void checkUser(String userId, String serverId) { } else r.db(DB_NAME).table(serverId).insert(r.array( r.hashMap("id", userId) - .with("TicketCount", 0))).run(conn); + .with("TicketCount", 0) + .with("Lottery ticket", null))).run(conn); } public long getMaxTickets(String serverId) { diff --git a/src/main/java/com/mazawrath/beanbot/utilities/Points.java b/src/main/java/com/mazawrath/beanbot/utilities/Points.java index 89a99d0..1c3b0ef 100644 --- a/src/main/java/com/mazawrath/beanbot/utilities/Points.java +++ b/src/main/java/com/mazawrath/beanbot/utilities/Points.java @@ -4,8 +4,6 @@ import com.rethinkdb.net.Connection; import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.MathContext; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; @@ -19,13 +17,18 @@ public class Points { private static final String DB_VALUE_PREFIX = "P_"; public static final int SCALE = 2; public static final int ROUNDING_MODE = BigDecimal.ROUND_HALF_UP; + public static final int FREE_COIN_TIME_LIMIT = 168 * 60 * 60 * 1000; + public static final int TRIVIA_QUESTION_TIME_LIMIT = 24 * 60 * 60 * 1000; public static final BigDecimal ZERO_POINTS = (BigDecimal.ZERO).setScale(SCALE, ROUNDING_MODE); - public static final BigDecimal FREE_POINTS = new BigDecimal("25.69").setScale(SCALE, ROUNDING_MODE); - public static final BigDecimal COMMAND_COST = new BigDecimal("2.00").setScale(SCALE, ROUNDING_MODE); - public static final BigDecimal COMMAND_COST_SPECIAL = new BigDecimal("10.00").setScale(SCALE, ROUNDING_MODE); - public static final BigDecimal LOTTERY_TICKET_COST = new BigDecimal("40.00").setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal STARTING_POINTS = (new BigDecimal("1000")).setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal TRIVIA_CORRECT_ANSWER = (new BigDecimal("10")).setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal TRIVIA_CHEAT_FINE = (new BigDecimal("200")).setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal FREE_POINTS = new BigDecimal("50").setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal COMMAND_COST = new BigDecimal("10.00").setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal COMMAND_COST_SPECIAL = new BigDecimal("15.00").setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal LOTTERY_TICKET_COST = new BigDecimal("45.00").setScale(SCALE, ROUNDING_MODE); public static final BigDecimal LOTTERY_DRAWING_COST = new BigDecimal("20000.00").setScale(SCALE, ROUNDING_MODE); - public static final BigDecimal GOOGLE_VISION_COST = new BigDecimal("50.00").setScale(SCALE, ROUNDING_MODE); + public static final BigDecimal GOOGLE_VISION_COST = new BigDecimal("20.00").setScale(SCALE, ROUNDING_MODE); private Connection conn; private static final BigDecimal NUMBER_TO_PERCENT = new BigDecimal(.01); @@ -56,8 +59,9 @@ private void checkUser(String userID, String serverID) { } else r.db(DB_NAME).table(serverID).insert(r.array( r.hashMap("id", userID) - .with("Points", buildValueForDB(ZERO_POINTS)) + .with("Points", buildValueForDB(Points.STARTING_POINTS)) .with("Last Received Free Points", 0) + .with("Last Used Trivia Question", 0) )).run(conn); } @@ -83,18 +87,52 @@ public ArrayList getLeaderboard(String serverID) { ).run(conn); } + @Deprecated public BigDecimal getBalance(String userID, String serverID) { checkUser(userID, serverID); return new BigDecimal(parseValueFromDB(r.db(DB_NAME).table(serverID).get(userID).getField("Points").run(conn))).setScale(SCALE, ROUNDING_MODE); } + public boolean canMakePurchase(PointsUser user, BigDecimal points) { + checkUser(user.getUserId(), user.getServerId()); + return getBalance(user.getUserId(), user.getServerId()).compareTo(points) >= 0; + } + + public void makePurchase(PointsUser user, PointsUser bot, BigDecimal points) { + checkUser(user.getUserId(), user.getServerId()); + + if (bot != null && !bot.getUserId().isEmpty()) { + Random r = new Random(); + BigDecimal blackHolePercent = new BigDecimal(r.nextInt(25 - 8 + 1) + 8).multiply(NUMBER_TO_PERCENT); + BigDecimal mysteriousTax = points.multiply(blackHolePercent); + + depositCoins(bot, points.subtract(mysteriousTax)); + } + + r.db(DB_NAME).table(user.getServerId()).filter(r.hashMap("id", user.getUserId())).update(r.hashMap("Points", buildValueForDB(getBalance(user.getUserId(), user.getServerId()).subtract(points)))).run(conn); + } + + public BigDecimal checkBalance(PointsUser user) { + checkUser(user.getUserId(), user.getServerId()); + + return new BigDecimal(parseValueFromDB(r.db(DB_NAME).table(user.getServerId()).get(user.getUserId()).getField("Points").run(conn))).setScale(SCALE, ROUNDING_MODE); + } + + public void depositCoins(PointsUser user, BigDecimal points) { + checkUser(user.getUserId(), user.getServerId()); + + r.db(DB_NAME).table(user.getServerId()).filter(r.hashMap("id", user.getUserId())).update(r.hashMap("Points", buildValueForDB(getBalance(user.getUserId(), user.getServerId()).add(points)))).run(conn); + } + + @Deprecated public void addPoints(String userID, String serverID, BigDecimal points) { checkUser(userID, serverID); r.db(DB_NAME).table(serverID).filter(r.hashMap("id", userID)).update(r.hashMap("Points", buildValueForDB(getBalance(userID, serverID).add(points)))).run(conn); } + @Deprecated public boolean removePoints(String userID, String botUserID, String serverID, BigDecimal points) { checkUser(userID, serverID); if (botUserID != null && !botUserID.isEmpty()) { @@ -119,7 +157,7 @@ public long giveFreePoints(String userID, String serverID) { checkUser(userID, serverID); long timeLeft = r.db(DB_NAME).table(serverID).get(userID).getField("Last Received Free Points").run(conn); - if (System.currentTimeMillis() - timeLeft > 24 * 60 * 60 * 1000) { + if (System.currentTimeMillis() - timeLeft > FREE_COIN_TIME_LIMIT) { r.db(DB_NAME).table(serverID).filter(r.hashMap("id", userID)).update(r.hashMap("Points", buildValueForDB(getBalance(userID, serverID).add(FREE_POINTS)))).run(conn); r.db(DB_NAME).table(serverID).filter(r.hashMap("id", userID)).update(r.hashMap("Last Received Free Points", System.currentTimeMillis())).run(conn); return 0; @@ -127,6 +165,17 @@ public long giveFreePoints(String userID, String serverID) { return timeLeft; } + public long useTriviaQuestion(PointsUser user, boolean cheaterPunishment) { + checkUser(user.getUserId(), user.getServerId()); + long timeLeft = r.db(DB_NAME).table(user.getServerId()).get(user.getUserId()).getField("Last Used Trivia Question").run(conn); + + if (System.currentTimeMillis() - timeLeft > TRIVIA_QUESTION_TIME_LIMIT || cheaterPunishment) { + r.db(DB_NAME).table(user.getServerId()).filter(r.hashMap("id", user.getUserId())).update(r.hashMap("Last Used Trivia Question", System.currentTimeMillis())).run(conn); + return 0; + } + return timeLeft; + } + public static String parseValueFromDB(String value) { return value.substring(DB_VALUE_PREFIX.length()); } diff --git a/src/main/java/com/mazawrath/beanbot/utilities/PointsUser.java b/src/main/java/com/mazawrath/beanbot/utilities/PointsUser.java new file mode 100644 index 0000000..c6533bd --- /dev/null +++ b/src/main/java/com/mazawrath/beanbot/utilities/PointsUser.java @@ -0,0 +1,27 @@ +package com.mazawrath.beanbot.utilities; + +import org.javacord.api.entity.server.Server; +import org.javacord.api.entity.user.User; + +public class PointsUser { + private User user; + private Server server; + private String userId; + private String serverId; + + public PointsUser(User user, Server server) { + this.user = user; + this.server = server; + + userId = user.getIdAsString(); + serverId = server.getIdAsString(); + } + + public String getUserId() { + return userId; + } + + public String getServerId() { + return serverId; + } +} diff --git a/src/main/java/com/mazawrath/beanbot/utilities/Trivia.java b/src/main/java/com/mazawrath/beanbot/utilities/Trivia.java new file mode 100644 index 0000000..fe7e6a4 --- /dev/null +++ b/src/main/java/com/mazawrath/beanbot/utilities/Trivia.java @@ -0,0 +1,40 @@ +package com.mazawrath.beanbot.utilities; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Trivia { + public JSONObject getTrivia() { + try { + URL url = new URL("https://opentdb.com/api.php?amount=1&type=multiple&encode=base64"); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + + if (con.getResponseCode() == 200) { + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer content = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + } + in.close(); + JSONParser parser = new JSONParser(); + return (JSONObject) parser.parse(content.toString()); + } else { + return null; + } + + } catch (IOException | ParseException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/src/main/java/com/mazawrath/beanbot/utilities/pesrspectiveapi_requests/MessageRequest.java b/src/main/java/com/mazawrath/beanbot/utilities/pesrspectiveapi_requests/MessageRequest.java new file mode 100644 index 0000000..7fd575b --- /dev/null +++ b/src/main/java/com/mazawrath/beanbot/utilities/pesrspectiveapi_requests/MessageRequest.java @@ -0,0 +1,53 @@ +package com.mazawrath.beanbot.utilities.pesrspectiveapi_requests; + +import au.com.origma.perspectiveapi.v1alpha1.PerspectiveAPI; +import au.com.origma.perspectiveapi.v1alpha1.models.*; + +public class MessageRequest { + String message; + public static String apiKey; + PerspectiveAPI pAPI; + AnalyzeCommentRequest.Builder request; + AnalyzeCommentResponse response; + + public MessageRequest(String message) { + this.pAPI = PerspectiveAPI.create(apiKey); + this.request = new AnalyzeCommentRequest.Builder() + .comment(new Entry.Builder() + .type(ContentType.PLAIN_TEXT) + .text(message) + .build()); + request.addRequestedAttribute(AttributeType.TOXICITY, null); + request.addRequestedAttribute(AttributeType.IDENTITY_ATTACK, null); + request.addRequestedAttribute(AttributeType.INSULT, null); + request.addRequestedAttribute(AttributeType.THREAT, null); + request.addRequestedAttribute(AttributeType.INCOHERENT, null); + request.addRequestedAttribute(AttributeType.SEXUALLY_EXPLICIT, null); + + requestAnalysis(); + } + + private void requestAnalysis() { + response = pAPI.analyze(request.build()); + } + + public float getToxicityProb() { + return response.getAttributeScore(AttributeType.TOXICITY).getSummaryScore().getValue(); + } + + public float getIdentityAttackProb() { + return response.getAttributeScore(AttributeType.IDENTITY_ATTACK).getSummaryScore().getValue(); + } + + public float getInsultProb() { + return response.getAttributeScore(AttributeType.INSULT).getSummaryScore().getValue(); + } + + public float getIncoherentProb() { + return response.getAttributeScore(AttributeType.INCOHERENT).getSummaryScore().getValue(); + } + + public float getSexuallyExplicitProb() { + return response.getAttributeScore(AttributeType.SEXUALLY_EXPLICIT).getSummaryScore().getValue(); + } +}