├── src └── main │ ├── java │ ├── META-INF │ │ └── MANIFEST.MF │ └── ml │ │ └── codeboy │ │ └── thebot │ │ ├── Bot.java │ │ ├── util │ │ ├── ModalListener.java │ │ ├── ButtonListener.java │ │ ├── SelectMenuListener.java │ │ ├── Replyable.java │ │ └── ASCII.java │ │ ├── commands │ │ ├── sound │ │ │ ├── Shuffle.java │ │ │ ├── PlayNext.java │ │ │ ├── Skip.java │ │ │ ├── Stop.java │ │ │ ├── Queue.java │ │ │ ├── Resume.java │ │ │ ├── Pause.java │ │ │ ├── RemoveTrack.java │ │ │ ├── CurrentTrack.java │ │ │ ├── GuildMusicManager.java │ │ │ ├── AudioPlayerSendHandler.java │ │ │ ├── Volume.java │ │ │ ├── fPlay.java │ │ │ ├── Loop.java │ │ │ ├── Echo.java │ │ │ ├── AudioCommand.java │ │ │ ├── TrackScheduler.java │ │ │ └── PlayerManager.java │ │ ├── image │ │ │ ├── meme │ │ │ │ ├── DisasterGirlCommand.java │ │ │ │ ├── SupermanCommand.java │ │ │ │ ├── Draw25Command.java │ │ │ │ ├── HotlineBlingCommand.java │ │ │ │ ├── TwoButtonsCommand.java │ │ │ │ ├── ChangeMyMindCommand.java │ │ │ │ └── MemeGeneratorCommand.java │ │ │ ├── ShitCommand.java │ │ │ ├── ImageCommand.java │ │ │ └── MorbCommand.java │ │ ├── NewsCommand.java │ │ ├── TrumpQuoteCommand.java │ │ ├── InsultCommand.java │ │ ├── AdviceCommand.java │ │ ├── ChuckNorrisJokeCommand.java │ │ ├── secret │ │ │ ├── SecretCommand.java │ │ │ ├── React.java │ │ │ ├── RejectImage.java │ │ │ ├── Msg.java │ │ │ ├── AcceptImage.java │ │ │ ├── RickRoll.java │ │ │ └── LoadKarma.java │ │ ├── debug │ │ │ ├── DebugCommand.java │ │ │ ├── GetQuotes.java │ │ │ └── ListQuotes.java │ │ ├── LanguagesCommand.java │ │ ├── MemeCommand.java │ │ ├── Help.java │ │ ├── PingCommand.java │ │ ├── Dönertop.java │ │ ├── ShittyTranslateCommand.java │ │ ├── JermaCommand.java │ │ ├── Karma.java │ │ ├── RhymeCommand.java │ │ ├── mensa │ │ │ ├── DefaultMensaCommand.java │ │ │ ├── MensaAnnounceChannelCommand.java │ │ │ └── DetailCommand.java │ │ ├── ASCIICommand.java │ │ ├── KarmaTop.java │ │ ├── KarmaBottom.java │ │ ├── WeatherCommand.java │ │ ├── JokeCommand.java │ │ ├── quotes │ │ │ ├── AddQuote.java │ │ │ ├── QuoteCommand.java │ │ │ └── AddQuoteList.java │ │ ├── ShortsCommand.java │ │ ├── DönerrateCommand.java │ │ ├── ExecuteCommand.java │ │ └── Command.java │ │ ├── data │ │ ├── Restaurant.java │ │ ├── Comment.java │ │ ├── MealEmoji.java │ │ ├── Rating.java │ │ ├── CommentManager.java │ │ ├── GuildManager.java │ │ ├── GuildData.java │ │ ├── EmojiManager.java │ │ ├── RestaurantManager.java │ │ ├── MealImage.java │ │ ├── UserData.java │ │ ├── UserDataManager.java │ │ └── FoodRatingManager.java │ │ ├── apis │ │ ├── TrumpQuote.java │ │ ├── MemeApi.java │ │ ├── InsultApi.java │ │ ├── NewsArticle.java │ │ ├── AdviceApi.java │ │ ├── TrumpQuotesApi.java │ │ ├── NewsApi.java │ │ ├── ChuckNorrisJokesApi.java │ │ ├── API.java │ │ ├── RhymeApi.java │ │ ├── CachedAPI.java │ │ ├── Meme.java │ │ ├── mongoDB │ │ │ ├── DatabaseQuoteAPI.java │ │ │ └── DatabaseManager.java │ │ ├── MensaVeganika.java │ │ └── RWTHMensa.java │ │ ├── quotes │ │ ├── Person.java │ │ ├── Quote.java │ │ └── QuoteManager.java │ │ ├── MensaBot.java │ │ ├── Config.java │ │ ├── events │ │ ├── MessageCommandEvent.java │ │ ├── SlashCommandCommandEvent.java │ │ └── CommandEvent.java │ │ ├── LogAppender.java │ │ ├── tracker │ │ └── BedTimeTracker.java │ │ └── WeatherUtil.java │ └── resources │ ├── emojis.csv │ └── logback.xml ├── README.md ├── pom.xml └── .gitignore /src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: ml.codeboy.thebot.MensaBot 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/Bot.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot; 2 | 3 | import net.dv8tion.jda.api.JDA; 4 | 5 | public interface Bot { 6 | public JDA getJda(); 7 | 8 | CommandHandler getCmdHandler(); 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MensaBot 2 | This repository is meant for contribution to the MensaBot. Feel free to make a PR or even just open issues for feature request. Every help is appreciated. 3 | 4 | # Self Hosting 5 | 6 | The bot is not meant for self hosting. 7 | But if you do want to do that you will just have to run the main method and it will generate a config file. 8 | In there you can set the bots token. 9 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/util/ModalListener.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.util; 2 | 3 | import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; 4 | 5 | public interface ModalListener { 6 | /** 7 | * @param event the event 8 | * @return true when the listener should be unregistered after this event 9 | */ 10 | boolean onModalInteraction(ModalInteractionEvent event); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Shuffle.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | 5 | public class Shuffle extends AudioCommand { 6 | public Shuffle() { 7 | super("shuffle"); 8 | } 9 | 10 | @Override 11 | public void run(CommandEvent event) { 12 | shuffle(event); 13 | event.reply("success"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/meme/DisasterGirlCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image.meme; 2 | 3 | import java.awt.*; 4 | 5 | public class DisasterGirlCommand extends MemeGeneratorCommand{ 6 | public DisasterGirlCommand() { 7 | super("https://i.imgflip.com/4/23ls.jpg", "DisasterGirl", "", "dg"); 8 | setBounds(new Rectangle(5,5,245,55),new Rectangle(5,130,245,50)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/util/ButtonListener.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.util; 2 | 3 | import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; 4 | 5 | public interface ButtonListener { 6 | /** 7 | * @param event the event 8 | * @return true when the listener should be unregistered after this event 9 | */ 10 | boolean onButtonInteraction(ButtonInteractionEvent event); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/meme/SupermanCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image.meme; 2 | 3 | import java.awt.*; 4 | import java.io.File; 5 | 6 | public class SupermanCommand extends MemeGeneratorCommand{ 7 | public SupermanCommand() { 8 | super("file://"+new File("images/superman.png").getAbsolutePath(), "superman", ""); 9 | setBounds(new Rectangle(450,140,220,60)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/meme/Draw25Command.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image.meme; 2 | 3 | import java.awt.*; 4 | 5 | public class Draw25Command extends MemeGeneratorCommand{ 6 | public Draw25Command() { 7 | super("https://i.imgflip.com/4/3lmzyx.jpg", "Draw25", "", "25","draw"); 8 | setImageScale(2); 9 | setBounds(new Rectangle(25,80,90,40),new Rectangle(135,5,110,30)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/Restaurant.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | public class Restaurant { 4 | public String name; 5 | private Rating rating = new Rating(); 6 | 7 | public String getName() { 8 | return name; 9 | } 10 | 11 | public Rating getRating() { 12 | return rating; 13 | } 14 | 15 | public void setRating(Rating rating) { 16 | this.rating = rating; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/util/SelectMenuListener.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.util; 2 | 3 | import net.dv8tion.jda.api.events.interaction.component.SelectMenuInteractionEvent; 4 | 5 | public interface SelectMenuListener { 6 | /** 7 | * @param event the event 8 | * @return true when the listener should be unregistered after this event 9 | */ 10 | boolean onSelectMenuInteraction(SelectMenuInteractionEvent event); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/Comment.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | public class Comment { 4 | private final String content, meal; 5 | 6 | public Comment(String content, String meal) { 7 | this.content = content; 8 | this.meal = meal; 9 | } 10 | 11 | public String getContent() { 12 | return content; 13 | } 14 | 15 | public String getMeal() { 16 | return meal; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/TrumpQuote.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import net.dv8tion.jda.api.EmbedBuilder; 4 | 5 | public class TrumpQuote { 6 | private String value; 7 | 8 | public EmbedBuilder createEmbed(EmbedBuilder builder) { 9 | builder.setDescription(value); 10 | builder.setAuthor("Donald Trump", null, "https://www.tronalddump.io/img/tronalddump_850x850.png"); 11 | return builder; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/meme/HotlineBlingCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image.meme; 2 | 3 | import java.awt.*; 4 | 5 | public class HotlineBlingCommand extends MemeGeneratorCommand{ 6 | public HotlineBlingCommand() { 7 | super("https://i.imgflip.com/4/30b1gx.jpg", "HotlineBling", "","hotline","hb"); 8 | setImageScale(2); 9 | setBounds(new Rectangle(130,5,100,100),new Rectangle(130,130,100,100)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/meme/TwoButtonsCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image.meme; 2 | 3 | import java.awt.*; 4 | 5 | public class TwoButtonsCommand extends MemeGeneratorCommand{ 6 | public TwoButtonsCommand() { 7 | super("https://i.imgflip.com/4/1g8my4.jpg", "TwoButtons", "", "tb"); 8 | setImageScale(2); 9 | setBounds(new Rectangle(5,15,100,30),new Rectangle(60,10,100,30),new Rectangle(5,180,150,40)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/NewsCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.apis.NewsApi; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | 6 | public class NewsCommand extends Command { 7 | 8 | public NewsCommand() { 9 | super("news", "Sends news articles"); 10 | setGuildOnlyCommand(false); 11 | } 12 | 13 | @Override 14 | public void run(CommandEvent event) { 15 | event.reply(NewsApi.getInstance().getObject().createEmbed(newBuilder())); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/meme/ChangeMyMindCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image.meme; 2 | 3 | import java.awt.*; 4 | 5 | public class ChangeMyMindCommand extends MemeGeneratorCommand { 6 | public ChangeMyMindCommand() { 7 | super("https://i.kym-cdn.com/photos/images/original/001/663/358/bda.png", "ChangeMyMind", "", "cmm"); 8 | setImageScale(0.25f); 9 | setBounds(textBounds); 10 | } 11 | 12 | private static final Rectangle textBounds = new Rectangle(750, 950, 900, 350); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/PlayNext.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | 5 | public class PlayNext extends AudioCommand { 6 | public PlayNext() { 7 | super("playNext", "", "pn"); 8 | } 9 | 10 | @Override 11 | public void run(CommandEvent event) { 12 | if (!ensureConnected(event)) 13 | return; 14 | String link = String.join(" ", event.getArgs()); 15 | queue(event, link, true); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/TrumpQuoteCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.apis.TrumpQuotesApi; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | 6 | public class TrumpQuoteCommand extends Command { 7 | 8 | public TrumpQuoteCommand() { 9 | super("trump", "sends trump quotes"); 10 | setGuildOnlyCommand(false); 11 | } 12 | 13 | @Override 14 | public void run(CommandEvent event) { 15 | event.reply(TrumpQuotesApi.getApi().getObject().createEmbed(newBuilder())); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Skip.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.util.Util; 5 | 6 | public class Skip extends AudioCommand { 7 | public Skip() { 8 | super("skip"); 9 | } 10 | 11 | @Override 12 | public void run(CommandEvent event) { 13 | 14 | event.reply(Util.sign(event.getBuilder().setTitle("Song skipped"), event)); 15 | PlayerManager.getInstance().getMusicManager(event.getGuild()).scheduler.nextTrack(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Stop.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.util.Util; 6 | 7 | public class Stop extends AudioCommand { 8 | public Stop() { 9 | super("stop"); 10 | } 11 | 12 | @Override 13 | public void run(CommandEvent event) { 14 | PlayerManager.getInstance().getMusicManager(event.getGuild()).audioPlayer.stopTrack(); 15 | 16 | event.reply(Util.sign(event.getBuilder().setTitle("Song stopped"), event)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/InsultCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.apis.InsultApi; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | 6 | public class InsultCommand extends Command { 7 | 8 | public InsultCommand() { 9 | super("insult", "Insults you"); 10 | setGuildOnlyCommand(false); 11 | } 12 | 13 | @Override 14 | public void run(CommandEvent event) { 15 | event.reply(newBuilder().setTitle("Insult") 16 | .setDescription(InsultApi.getInstance().getObject())); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/AdviceCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.apis.AdviceApi; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | 6 | public class AdviceCommand extends Command { 7 | public AdviceCommand() { 8 | super("advice", "Gives you advice"); 9 | setGuildOnlyCommand(false); 10 | } 11 | 12 | @Override 13 | public void run(CommandEvent event) { 14 | event.reply(newBuilder().setTitle("Advice") 15 | .setDescription(AdviceApi.getInstance().getObject())); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/ChuckNorrisJokeCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.apis.ChuckNorrisJokesApi; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | 6 | public class ChuckNorrisJokeCommand extends Command { 7 | public ChuckNorrisJokeCommand() { 8 | super("chuckNorrisJoke", "Sends a Chuck Norris joke"); 9 | setGuildOnlyCommand(false); 10 | } 11 | 12 | @Override 13 | public void run(CommandEvent event) { 14 | event.reply(newBuilder().setTitle("Chuck Norris Joke") 15 | .setDescription(ChuckNorrisJokesApi.getInstance().getObject())); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/MemeApi.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | public class MemeApi extends CachedAPI { 4 | private static final MemeApi instance = new MemeApi(); 5 | 6 | public static MemeApi getInstance() { 7 | return instance; 8 | } 9 | 10 | @Override 11 | protected Meme requestObject() { 12 | try { 13 | String json = readUrl("https://meme-api.herokuapp.com/gimme"); 14 | Meme meme = gson.fromJson(json, Meme.class); 15 | return meme; 16 | } catch (Exception e) { 17 | e.printStackTrace(); 18 | } 19 | return new Meme(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/InsultApi.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | public class InsultApi extends CachedAPI { 4 | private static final InsultApi instance = new InsultApi(); 5 | 6 | public InsultApi() { 7 | super(1); 8 | } 9 | 10 | public static InsultApi getInstance() { 11 | return instance; 12 | } 13 | 14 | @Override 15 | protected String requestObject() { 16 | try { 17 | return readUrl("https://evilinsult.com/generate_insult.php?lang=en"); 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | return e.getMessage(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/NewsArticle.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import net.dv8tion.jda.api.EmbedBuilder; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class NewsArticle { 8 | private String author, content, imageUrl, readMoreUrl, title; 9 | 10 | public EmbedBuilder createEmbed(EmbedBuilder builder) { 11 | builder.setAuthor(author); 12 | builder.setTitle(title, readMoreUrl); 13 | builder.setThumbnail(imageUrl); 14 | builder.setDescription(content); 15 | return builder; 16 | } 17 | 18 | public static class NewsArticleResponse { 19 | public ArrayList data; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Queue.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | 5 | public class Queue extends AudioCommand { 6 | public Queue() { 7 | super("queue", "","play"); 8 | } 9 | 10 | @Override 11 | public void run(CommandEvent event) { 12 | if (event.getArgs().length == 0) { 13 | event.getManager().scheduler.sendQueueInfo(event); 14 | return; 15 | } 16 | 17 | if (!ensureConnected(event)) 18 | return; 19 | String link = String.join(" ", event.getArgs()); 20 | queue(event, link); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Resume.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.util.Util; 6 | 7 | public class Resume extends AudioCommand { 8 | public Resume() { 9 | super("resume"); 10 | } 11 | 12 | @Override 13 | public void run(CommandEvent event) { 14 | AudioPlayer player = PlayerManager.getInstance().getMusicManager(event.getGuild()).audioPlayer; 15 | player.setPaused(false); 16 | 17 | event.reply(Util.sign(event.getBuilder().setTitle("Song resumed"), event)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/secret/SecretCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.secret; 2 | 3 | import ml.codeboy.thebot.Config; 4 | import ml.codeboy.thebot.commands.Command; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | 7 | public abstract class SecretCommand extends Command { 8 | public SecretCommand(String name, String description, String... aliases) { 9 | super(name, description, aliases); 10 | setHidden(true); 11 | } 12 | 13 | @Override 14 | public void execute(CommandEvent event) { 15 | if (!Config.getInstance().admins.contains(event.getUser().getId())) 16 | return; 17 | super.execute(event); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Pause.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.util.Util; 6 | 7 | public class Pause extends AudioCommand { 8 | public Pause() { 9 | super("pause"); 10 | } 11 | 12 | @Override 13 | public void run(CommandEvent event) { 14 | AudioPlayer player = PlayerManager.getInstance().getMusicManager(event.getGuild()).audioPlayer; 15 | player.setPaused(!player.isPaused()); 16 | 17 | event.reply(Util.sign(event.getBuilder().setTitle("Song paused"), event)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/debug/DebugCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.debug; 2 | 3 | import ml.codeboy.thebot.Config; 4 | import ml.codeboy.thebot.commands.Command; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | 7 | public abstract class DebugCommand extends Command { 8 | public DebugCommand(String name, String description, String... aliases) { 9 | super(name, description, aliases); 10 | setHidden(true); 11 | } 12 | 13 | @Override 14 | public void execute(CommandEvent event) { 15 | if (!Config.getInstance().isDebugAccount(event.getUser())) { 16 | return; 17 | } 18 | super.execute(event); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/quotes/Person.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.quotes; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Person { 6 | private String name; 7 | private ArrayList quotes = new ArrayList<>(); 8 | 9 | public Person(){} 10 | public Person(String name) 11 | { 12 | this.name = name; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public ArrayList getQuotes() { 24 | return quotes; 25 | } 26 | 27 | public void setQuotes(ArrayList quotes) { 28 | this.quotes = quotes; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/AdviceApi.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import com.google.gson.JsonParser; 4 | 5 | public class AdviceApi extends CachedAPI { 6 | private static final AdviceApi instance = new AdviceApi(); 7 | 8 | public static AdviceApi getInstance() { 9 | return instance; 10 | } 11 | 12 | @Override 13 | protected String requestObject() { 14 | try { 15 | return JsonParser.parseString(readUrl("https://api.adviceslip.com/advice")).getAsJsonObject() 16 | .get("slip").getAsJsonObject().get("advice").getAsString(); 17 | } catch (Exception e) { 18 | e.printStackTrace(); 19 | return e.getMessage(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/emojis.csv: -------------------------------------------------------------------------------- 1 | schnitzel,<:schnitzel:943559144135336047> 2 | beeren,🐻 3 | burger,🍔 4 | pizza,🍕 5 | pfannkuchen,🥞 6 | kuchen,🍰 7 | küchlein,🍰 8 | spaghetti,🍝 9 | suppe,🍲 10 | chili,🌶 11 | scharf,🌶 12 | keule,🍗 13 | steak,🥩 14 | hähnchen,🐔 15 | huhn,🐔 16 | chicken,🐔 17 | schwein,🐷 18 | pork,🐷 19 | kuh,🐮 20 | rind,🐮 21 | ente,🦆 22 | gans,🦆 23 | fisch,🐟 24 | lachs,🐟 25 | krebs,🦀 26 | reis,🍚 27 | pommes,🍟 28 | apfel,🍎 29 | zitrone,🍋 30 | lemon,🍋 31 | limette,🍋 32 | brokkoli,🥦 33 | paprika,🫑 34 | mais,🌽 35 | karotte,🥕 36 | kartoffel,🥔 37 | salat,🥗 38 | eintopf,🍲 39 | käse,🧀 40 | zwiebel,🧅 41 | vegan,<:vegan:1003629202739822702> 42 | weizen,🌾 43 | milch,🥛 44 | farbstoff,🖌 45 | soja,🌱 46 | samen,🌱 47 | eier,🥚 48 | schalenfrüchte,🌰 49 | mandeln,🌰 50 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/TrumpQuotesApi.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | public class TrumpQuotesApi extends CachedAPI { 4 | private static final TrumpQuotesApi api = new TrumpQuotesApi(); 5 | 6 | public TrumpQuotesApi() { 7 | super(10); 8 | } 9 | 10 | public static TrumpQuotesApi getApi() { 11 | return api; 12 | } 13 | 14 | @Override 15 | protected TrumpQuote requestObject() { 16 | try { 17 | String json = readUrl("https://api.tronalddump.io/random/quote"); 18 | TrumpQuote quote = gson.fromJson(json, TrumpQuote.class); 19 | return quote; 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | } 23 | return new TrumpQuote(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/MealEmoji.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import java.util.Collection; 4 | 5 | public class MealEmoji { 6 | private final String emoji; 7 | private final Collection names; 8 | private final int priority; 9 | 10 | public MealEmoji(String emoji, Collection names, int priority) { 11 | this.emoji = emoji; 12 | this.names = names; 13 | this.priority = priority; 14 | } 15 | 16 | public String getEmoji() { 17 | return emoji; 18 | } 19 | 20 | public Collection getNames() { 21 | return names; 22 | } 23 | 24 | public int getPriority() { 25 | return priority; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return getEmoji(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/LanguagesCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import com.github.codeboy.piston4j.api.Piston; 4 | import com.github.codeboy.piston4j.api.Runtime; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | import net.dv8tion.jda.api.EmbedBuilder; 7 | 8 | public class LanguagesCommand extends Command { 9 | public LanguagesCommand() { 10 | super("languages", "sends available languages"); 11 | setGuildOnlyCommand(false); 12 | } 13 | 14 | @Override 15 | public void run(CommandEvent event) { 16 | EmbedBuilder builder = new EmbedBuilder(); 17 | for (Runtime r : Piston.getDefaultApi().getRuntimes()) { 18 | builder.addField(r.getLanguage(), r.getVersion(), true); 19 | } 20 | event.reply(builder); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/RemoveTrack.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.util.Util; 6 | 7 | public class RemoveTrack extends AudioCommand { 8 | public RemoveTrack() { 9 | super("removeTrack", "", "rmt"); 10 | } 11 | 12 | @Override 13 | public void run(CommandEvent event) { 14 | String arg = event.getArgs()[0]; 15 | if (Util.isInt(arg)) { 16 | boolean success = event.getManager().scheduler.removeTrack(Util.toInt(arg, -1)); 17 | if (success) 18 | event.reply("success"); 19 | else 20 | event.replyError("Could not remove song with id " + arg + " from queue"); 21 | } else event.replyError("wrong usage"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/NewsApi.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class NewsApi extends CachedAPI { 6 | private static final NewsApi instance = new NewsApi(); 7 | 8 | public static NewsApi getInstance() { 9 | return instance; 10 | } 11 | 12 | @Override 13 | protected NewsArticle requestObject() { 14 | try { 15 | String json = readUrl("https://inshortsapi.vercel.app/news?category=all"); 16 | ArrayList articles = gson.fromJson(json, NewsArticle.NewsArticleResponse.class).data; 17 | NewsArticle article = articles.remove(0); 18 | cache.addAll(articles); 19 | return article; 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | return new NewsArticle(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/MemeCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.apis.Meme; 4 | import ml.codeboy.thebot.apis.MemeApi; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | import net.dv8tion.jda.api.EmbedBuilder; 7 | 8 | public class MemeCommand extends Command { 9 | 10 | public MemeCommand() { 11 | super("meme", "sends a meme"); 12 | setGuildOnlyCommand(false); 13 | } 14 | 15 | @Override 16 | public void run(CommandEvent event) { 17 | Meme meme = MemeApi.getInstance().getObject(); 18 | EmbedBuilder builder = event.getBuilder(); 19 | builder.setTitle(meme.getTitle(), meme.getPostLink()) 20 | .setAuthor(meme.getAuthor()) 21 | .setImage(meme.getUrl()) 22 | .setFooter(meme.getUps() + " upvotes"); 23 | event.reply(builder); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/CurrentTrack.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import com.sedmelluq.discord.lavaplayer.track.AudioTrack; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | 6 | import static ml.codeboy.thebot.util.Util.sendTrackInfo; 7 | 8 | public class CurrentTrack extends AudioCommand { 9 | 10 | public CurrentTrack() { 11 | super("current"); 12 | } 13 | 14 | @Override 15 | public void run(CommandEvent event) { 16 | 17 | if (!ensureConnected(event)) 18 | return; 19 | 20 | AudioTrack current = event.getManager().audioPlayer.getPlayingTrack(); 21 | 22 | if (current != null) { 23 | sendTrackInfo(event, current); 24 | event.getManager().scheduler.setLatestEvent(event); 25 | } else { 26 | event.replyError("There is no song currently playing!"); 27 | } 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/ChuckNorrisJokesApi.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonParser; 5 | 6 | public class ChuckNorrisJokesApi extends CachedAPI { 7 | private static final ChuckNorrisJokesApi instance = new ChuckNorrisJokesApi(); 8 | 9 | public ChuckNorrisJokesApi() { 10 | super(10); 11 | } 12 | 13 | public static ChuckNorrisJokesApi getInstance() { 14 | return instance; 15 | } 16 | 17 | @Override 18 | protected String requestObject() { 19 | try { 20 | String json = readUrl("https://api.chucknorris.io/jokes/random"); 21 | JsonObject obj = JsonParser.parseString(json).getAsJsonObject(); 22 | return obj.get("value").getAsString(); 23 | } catch (Exception e) { 24 | e.printStackTrace(); 25 | } 26 | return "Can´t find joke"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/API.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.InputStreamReader; 7 | import java.net.URL; 8 | 9 | public abstract class API { 10 | protected final Gson gson = new Gson(); 11 | 12 | protected String readUrl(String urlString) throws Exception { 13 | BufferedReader reader = null; 14 | try { 15 | URL url = new URL(urlString); 16 | reader = new BufferedReader(new InputStreamReader(url.openStream())); 17 | StringBuilder buffer = new StringBuilder(); 18 | int read; 19 | char[] chars = new char[1024]; 20 | while ((read = reader.read(chars)) != -1) 21 | buffer.append(chars, 0, read); 22 | 23 | return buffer.toString(); 24 | } finally { 25 | if (reader != null) 26 | reader.close(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/Help.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.Bot; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.EmbedBuilder; 6 | 7 | import java.util.Collection; 8 | 9 | public class Help extends Command { 10 | private final Bot bot; 11 | 12 | public Help(Bot bot) { 13 | super("help", "gives help"); 14 | this.bot = bot; 15 | setGuildOnlyCommand(false); 16 | } 17 | 18 | @Override 19 | public void run(CommandEvent event) { 20 | Collection commands = bot.getCmdHandler().getCommands(); 21 | EmbedBuilder embedBuilder = newBuilder(); 22 | embedBuilder.setTitle("Help for commands", "https://cntr.click/g3PZ5hm"); 23 | for (Command command : commands) { 24 | if (!command.isHidden()) 25 | embedBuilder.addField(command.getName(), command.getDescription(), true); 26 | } 27 | event.reply(embedBuilder); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/PingCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.events.SlashCommandCommandEvent; 5 | import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; 6 | 7 | public class PingCommand extends Command { 8 | 9 | public PingCommand() { 10 | super("ping", "Measures the bots ping", "pong"); 11 | } 12 | 13 | @Override 14 | public void run(CommandEvent event) { 15 | long startTime = System.nanoTime(); 16 | if (event instanceof SlashCommandCommandEvent) { 17 | SlashCommandInteractionEvent event2 = event.getSlashCommandEvent(); 18 | event2.getHook().sendMessage("loading").complete(); 19 | } else { 20 | event.reply("loading"); 21 | } 22 | long ping = System.nanoTime() - startTime; 23 | ping = ping / 1000000; 24 | event.edit("Der Ping beträgt " + ping + " Millisekunden"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/secret/React.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.secret; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import net.dv8tion.jda.api.JDA; 5 | import net.dv8tion.jda.api.entities.Message; 6 | import net.dv8tion.jda.api.entities.TextChannel; 7 | 8 | public class React extends SecretCommand { 9 | public React() { 10 | super("react", ""); 11 | } 12 | 13 | @Override 14 | public void run(CommandEvent event) { 15 | String[] args = event.getArgs(); 16 | if (args.length > 0) { 17 | String channelId = args[0]; 18 | String messageId = args[1]; 19 | String reaction = args[2]; 20 | JDA jda = event.getJdaEvent().getJDA(); 21 | TextChannel channel = (TextChannel) jda.getGuildChannelById(channelId); 22 | Message message = channel.getHistoryAround(messageId, 1).complete().getMessageById(messageId); 23 | message.addReaction(jda.getEmojiById(reaction)).complete(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/Rating.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public class Rating implements Comparable { 6 | public static final int MAX_RATING = 5; 7 | private int ratings = 0; 8 | private int total = 0; 9 | 10 | public double getAverage() { 11 | if (ratings == 0) 12 | return -1;//no ratings 13 | return total / (double) ratings; 14 | } 15 | 16 | public void addRating(int rating) { 17 | ratings++; 18 | total += rating; 19 | } 20 | 21 | public void removeRating(int rating) { 22 | ratings--; 23 | total -= rating; 24 | } 25 | 26 | public int getRatings() { 27 | return ratings; 28 | } 29 | 30 | @Override 31 | public int compareTo(@NotNull Rating o) { 32 | int result = Double.compare(getAverage(), o.getAverage()); 33 | if (result == 0) 34 | result = Double.compare(getRatings(), o.getRatings()); 35 | return result; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss} %boldGreen(%-15.-15logger{0}) %highlight(%-6level) %msg%n 6 | 7 | 8 | 9 | 10 | 11 | ${application.home:-.}/logs/%d{yyyy-MM-dd}.log 12 | 13 | true 14 | 15 | %d{HH:mm:ss} %-15.-15logger{0} %-6level %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/RhymeApi.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonParser; 5 | 6 | import java.net.URLEncoder; 7 | import java.util.ArrayList; 8 | 9 | public class RhymeApi extends API { 10 | private static final RhymeApi instance = new RhymeApi(); 11 | 12 | public static RhymeApi getInstance() { 13 | return instance; 14 | } 15 | 16 | public ArrayList getRhymingWords(String word) { 17 | try { 18 | String json = readUrl("https://api.datamuse.com/words?rel_rhy=" + URLEncoder.encode(word)); 19 | JsonArray jsonArray = JsonParser.parseString(json).getAsJsonArray(); 20 | ArrayList words = new ArrayList<>(); 21 | for (int i = 0; i < jsonArray.size(); i++) 22 | words.add(jsonArray.get(i).getAsJsonObject().get("word").getAsString()); 23 | return words; 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | return new ArrayList<>(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/secret/RejectImage.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.secret; 2 | 3 | import ml.codeboy.thebot.data.FoodRatingManager; 4 | import ml.codeboy.thebot.data.MealImage; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | 7 | import java.util.UUID; 8 | 9 | public class RejectImage extends SecretCommand { 10 | public RejectImage() { 11 | super("reject", ""); 12 | } 13 | 14 | @Override 15 | public void run(CommandEvent event) { 16 | String[] args = event.getArgs(); 17 | String id = args[0]; 18 | MealImage image = FoodRatingManager.getInstance().getImage(UUID.fromString(id)); 19 | if (image == null) 20 | event.replyError("can not find image"); 21 | else { 22 | String message = ""; 23 | if (args.length > 1) { 24 | message = String.join(" ", args); 25 | message = message.substring(id.length() + 1); 26 | } 27 | image.reject(message); 28 | event.reply("rejected " + image.getUrl()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/GuildMusicManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; 4 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; 5 | import net.dv8tion.jda.api.entities.Guild; 6 | 7 | public class GuildMusicManager { 8 | public final AudioPlayer audioPlayer; 9 | 10 | public final TrackScheduler scheduler; 11 | public final Guild guild; 12 | private final AudioPlayerSendHandler sendHandler; 13 | 14 | public GuildMusicManager(AudioPlayerManager manager, Guild guild) { 15 | this.audioPlayer = manager.createPlayer(); 16 | this.guild = guild; 17 | this.scheduler = new TrackScheduler(this); 18 | this.audioPlayer.addListener(this.scheduler); 19 | this.sendHandler = new AudioPlayerSendHandler(this.audioPlayer); 20 | } 21 | 22 | public AudioPlayerSendHandler getSendHandler() { 23 | return sendHandler; 24 | } 25 | 26 | public void destroy() { 27 | audioPlayer.destroy(); 28 | scheduler.destroy(); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/AudioPlayerSendHandler.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; 4 | import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame; 5 | import net.dv8tion.jda.api.audio.AudioSendHandler; 6 | 7 | import java.nio.ByteBuffer; 8 | 9 | public class AudioPlayerSendHandler implements AudioSendHandler { 10 | private final AudioPlayer audioPlayer; 11 | private final ByteBuffer buffer; 12 | private final MutableAudioFrame frame; 13 | 14 | public AudioPlayerSendHandler(AudioPlayer audioPlayer) { 15 | this.audioPlayer = audioPlayer; 16 | this.buffer = ByteBuffer.allocate(1024); 17 | this.frame = new MutableAudioFrame(); 18 | this.frame.setBuffer(buffer); 19 | } 20 | 21 | @Override 22 | public boolean canProvide() { 23 | return this.audioPlayer.provide(this.frame); 24 | } 25 | 26 | @Override 27 | public ByteBuffer provide20MsAudio() { 28 | return (ByteBuffer) this.buffer.flip(); 29 | } 30 | 31 | @Override 32 | public boolean isOpus() { 33 | return true; 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/Dönertop.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.MensaUtil; 4 | import ml.codeboy.thebot.data.Restaurant; 5 | import ml.codeboy.thebot.data.RestaurantManager; 6 | import ml.codeboy.thebot.events.CommandEvent; 7 | import net.dv8tion.jda.api.EmbedBuilder; 8 | 9 | import java.util.Comparator; 10 | import java.util.List; 11 | 12 | public class Dönertop extends Command { 13 | public Dönertop() { 14 | super("dönertop", "best döner", "dt"); 15 | } 16 | 17 | @Override 18 | public void run(CommandEvent event) { 19 | EmbedBuilder builder = event.getBuilder(); 20 | builder.setTitle("Dönertop"); 21 | List restaurants = RestaurantManager.getInstance().getRestaurants(); 22 | restaurants.sort(Comparator.comparing(Restaurant::getRating).reversed()); 23 | for (Restaurant restaurant : restaurants) { 24 | builder.addField(restaurant.getName(), 25 | MensaUtil.getRatingString(restaurant.getRating().getAverage()) + " (" + restaurant.getRating().getRatings() + ")", false); 26 | } 27 | event.reply(builder); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Volume.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.util.Util; 6 | 7 | public class Volume extends AudioCommand { 8 | public Volume() { 9 | super("volume"); 10 | } 11 | 12 | @Override 13 | public void run(CommandEvent event) { 14 | if (event.getArgs().length == 0) { 15 | event.reply(event.getBuilder().setTitle("Volume").setDescription(event.getManager().audioPlayer.getVolume() / 10 + "%")); 16 | return; 17 | } 18 | String arg1 = event.getArgs()[0]; 19 | if (Util.isInt(arg1)) { 20 | int volume = Util.toInt(arg1); 21 | if (volume > -1 && volume <= 100) { 22 | event.getManager().audioPlayer.setVolume(10 * volume); 23 | } 24 | } else if (arg1.equalsIgnoreCase("up")) { 25 | event.getManager().audioPlayer.setVolume(10 + event.getManager().audioPlayer.getVolume()); 26 | } else if (arg1.equalsIgnoreCase("down")) { 27 | event.getManager().audioPlayer.setVolume(-10 + event.getManager().audioPlayer.getVolume()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/CachedAPI.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import java.util.ArrayList; 4 | 5 | public abstract class CachedAPI extends API { 6 | 7 | protected final ArrayList cache = new ArrayList<>(); 8 | private final int cacheSize; 9 | 10 | protected CachedAPI() { 11 | this(10); 12 | } 13 | 14 | protected CachedAPI(int cacheSize) { 15 | cacheSize = 0; 16 | this.cacheSize = cacheSize; 17 | int finalCacheSize = cacheSize; 18 | new Thread(() -> { 19 | while (cache.size() < finalCacheSize) 20 | cache.add(requestObject()); 21 | }).start(); 22 | } 23 | 24 | public T getObject() { 25 | if (cache.size() <= cacheSize) { 26 | Thread thread = new Thread(() -> cache.add(requestObject())); 27 | thread.start(); 28 | if (cache.size() == 0) { 29 | try { 30 | thread.join(); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | } 36 | return cache.remove(0); 37 | } 38 | 39 | protected abstract T requestObject(); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/secret/Msg.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.secret; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import net.dv8tion.jda.api.entities.MessageChannel; 5 | import net.dv8tion.jda.api.entities.TextChannel; 6 | import net.dv8tion.jda.api.entities.User; 7 | import net.dv8tion.jda.api.entities.emoji.Emoji; 8 | 9 | public class Msg extends SecretCommand { 10 | public Msg() { 11 | super("msg", ""); 12 | } 13 | 14 | @Override 15 | public void run(CommandEvent event) { 16 | String id = event.getArgs()[0]; 17 | MessageChannel channel = (TextChannel) event.getJdaEvent().getJDA().getGuildChannelById(id); 18 | if (channel == null) { 19 | User user = event.getJdaEvent().getJDA().retrieveUserById(id).complete(); 20 | if(user==null) { 21 | event.reply(":("); 22 | return; 23 | } 24 | channel=user.openPrivateChannel().complete(); 25 | } 26 | String message = String.join(" ", event.getArgs()); 27 | message = message.substring(event.getArgs()[0].length() + 1); 28 | channel.sendMessage(message).complete(); 29 | event.getMessageReceivedEvent().getMessage().addReaction(Emoji.fromFormatted("✅")).queue(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/Meme.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Meme { 6 | private String postLink; 7 | private String subreddit; 8 | private String title; 9 | private String url; 10 | private String author; 11 | private int ups; 12 | private String[] preview; 13 | 14 | public String getPostLink() { 15 | return postLink; 16 | } 17 | 18 | public String getSubreddit() { 19 | return subreddit; 20 | } 21 | 22 | public String getTitle() { 23 | return title; 24 | } 25 | 26 | public String getUrl() { 27 | return url; 28 | } 29 | 30 | public String getAuthor() { 31 | return author; 32 | } 33 | 34 | public int getUps() { 35 | return ups; 36 | } 37 | 38 | public String[] getPreview() { 39 | return preview; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "Meme{" + 45 | "postLink='" + postLink + '\'' + 46 | ", subreddit='" + subreddit + '\'' + 47 | ", title='" + title + '\'' + 48 | ", url='" + url + '\'' + 49 | ", author='" + author + '\'' + 50 | ", ups=" + ups + 51 | ", preview=" + Arrays.toString(preview) + 52 | '}'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/util/Replyable.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.util; 2 | 3 | import net.dv8tion.jda.api.entities.MessageChannel; 4 | import net.dv8tion.jda.api.entities.MessageEmbed; 5 | import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; 6 | 7 | import java.util.Arrays; 8 | 9 | public interface Replyable { 10 | static Replyable from(MessageChannel channel) { 11 | return new Replyable() { 12 | @Override 13 | public void reply(String message) { 14 | channel.sendMessage(message).queue(); 15 | } 16 | 17 | @Override 18 | public void reply(MessageEmbed... embeds) { 19 | channel.sendMessageEmbeds(Arrays.asList(embeds)).queue(); 20 | } 21 | }; 22 | } 23 | 24 | static Replyable from(IReplyCallback replyCallback) { 25 | return new Replyable() { 26 | @Override 27 | public void reply(String message) { 28 | replyCallback.getHook().sendMessage(message).queue(); 29 | } 30 | 31 | @Override 32 | public void reply(MessageEmbed... embeds) { 33 | replyCallback.getHook().sendMessageEmbeds(Arrays.asList(embeds)).queue(); 34 | } 35 | }; 36 | } 37 | 38 | void reply(String message); 39 | 40 | void reply(MessageEmbed... embeds); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/fPlay.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | 5 | public class fPlay extends AudioCommand { 6 | public fPlay() { 7 | super("fplay", "Play the given song and then resume with the playlist"); 8 | } 9 | 10 | @Override 11 | public void run(CommandEvent event) { 12 | 13 | if (!ensureConnected(event)) 14 | return; 15 | 16 | if (event.getArgs().length == 0) { 17 | if (event.getManager().audioPlayer.getPlayingTrack() == null) { 18 | if (event.getManager().scheduler.songsInQueue() == 0) { 19 | play(event, "https://www.youtube.com/watch?v=w2Ov5jzm3j8&list=PLurPBtLcqJqcg3r-HOhR3LZ0aDxpI15Fa", true); 20 | shuffle(event); 21 | } 22 | } 23 | event.getManager().audioPlayer.setPaused(false); 24 | return; 25 | } 26 | 27 | if (event.getManager().audioPlayer.getPlayingTrack() != null) { 28 | String n = event.getManager().audioPlayer.getPlayingTrack().getInfo().uri+"&t="+(int)(event.getManager().audioPlayer.getPlayingTrack().getPosition()/1000); 29 | queue(event, n, true); 30 | } 31 | 32 | String link = String.join(" ", event.getArgs()); 33 | play(event, link); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/CommentManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import net.dv8tion.jda.api.entities.User; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | 8 | public class CommentManager { 9 | private static final CommentManager instance = new CommentManager(); 10 | 11 | private final HashMap> comments = new HashMap<>(); 12 | 13 | public CommentManager() { 14 | for (UserData data : UserDataManager.getInstance().getAllUserData()) { 15 | if (data != null && data.getComments() != null) 16 | for (Comment c : data.getComments()) { 17 | getComments(c.getMeal()).add(c.getContent()); 18 | } 19 | } 20 | } 21 | 22 | public static CommentManager getInstance() { 23 | return instance; 24 | } 25 | 26 | public ArrayList getComments(String meal) { 27 | return comments.computeIfAbsent(meal, e -> new ArrayList<>()); 28 | } 29 | 30 | public void addComment(String meal, String comment, User user) { 31 | getComments(meal).add(comment); 32 | UserData data = UserDataManager.getInstance().getData(user); 33 | if (data != null) { 34 | data.getComments().add(new Comment(comment, meal)); 35 | UserDataManager.getInstance().save(data); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/quotes/Quote.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.quotes; 2 | 3 | import net.dv8tion.jda.api.EmbedBuilder; 4 | 5 | public class Quote { 6 | private String content; 7 | private long time; 8 | private transient String person; 9 | private String authorId; 10 | 11 | public Quote(String content, long time, String person, String authorId) { 12 | this.content = content; 13 | this.time = time; 14 | this.person = person; 15 | this.authorId = authorId; 16 | } 17 | 18 | public String getAuthorId() { 19 | return authorId; 20 | } 21 | 22 | public void setAuthorId(String authorId) { 23 | this.authorId = authorId; 24 | } 25 | 26 | public String getContent() { 27 | return content; 28 | } 29 | 30 | public void setContent(String content) { 31 | this.content = content; 32 | } 33 | 34 | public long getTime() { 35 | return time; 36 | } 37 | 38 | public void setTime(long time) { 39 | this.time = time; 40 | } 41 | 42 | public String getPerson() { 43 | return person; 44 | } 45 | 46 | public void setPerson(String person) { 47 | this.person = person; 48 | } 49 | 50 | public EmbedBuilder builder() { 51 | return new EmbedBuilder().setTitle(getContent()).setDescription("||" + getPerson() + "||"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/debug/GetQuotes.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.debug; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.quotes.Quote; 5 | import ml.codeboy.thebot.quotes.QuoteManager; 6 | import net.dv8tion.jda.api.EmbedBuilder; 7 | import net.dv8tion.jda.api.entities.MessageEmbed; 8 | 9 | /** 10 | * Echos all the quotes of the given person 11 | */ 12 | public class GetQuotes extends DebugCommand { 13 | public GetQuotes() { 14 | super("getQuotes", "", "gq"); 15 | } 16 | 17 | @Override 18 | public void run(CommandEvent event) { 19 | EmbedBuilder m = null; 20 | MessageEmbed[] msg; 21 | int i = 0; 22 | if(QuoteManager.getInstance().getQuotes(event.getArgs()[0]).size()>10) 23 | msg = new MessageEmbed[10]; 24 | else 25 | msg = new MessageEmbed[QuoteManager.getInstance().getQuotes(event.getArgs()[0]).size()]; 26 | for(Quote q : QuoteManager.getInstance().getQuotes(event.getArgs()[0])) { 27 | m = new EmbedBuilder(); 28 | m.setTitle(event.getArgs()[0]); 29 | m.addField("Quote", q.getContent(),false); 30 | msg[i] = m.build(); 31 | i++; 32 | if(i==10) { 33 | event.reply(msg); 34 | i=0; 35 | } 36 | } 37 | event.reply(msg); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/debug/ListQuotes.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.debug; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.quotes.Person; 5 | import ml.codeboy.thebot.quotes.Quote; 6 | import ml.codeboy.thebot.quotes.QuoteManager; 7 | import net.dv8tion.jda.api.EmbedBuilder; 8 | import net.dv8tion.jda.api.entities.MessageEmbed; 9 | 10 | import java.util.ArrayList; 11 | 12 | public class ListQuotes extends DebugCommand { 13 | public ListQuotes() { 14 | super("listQuotes", "", "lq"); 15 | } 16 | 17 | @Override 18 | public void run(CommandEvent event) { 19 | Person[] persons = QuoteManager.getInstance().getPersons().toArray(new Person[0]); 20 | ArrayList rep = new ArrayList<>(); 21 | EmbedBuilder m = null; 22 | int s = 0; 23 | for(Person p : persons) 24 | { 25 | m = new EmbedBuilder(); 26 | m.setTitle(p.getName()); 27 | for(Quote q : p.getQuotes()) 28 | { 29 | if(s+q.getContent().length()>1024) 30 | { 31 | s=0; 32 | rep.add(m.build()); 33 | m = new EmbedBuilder(); 34 | m.setTitle(p.getName()); 35 | } 36 | m.addField("",q.getContent(), false); 37 | s+=q.getContent().length(); 38 | } 39 | rep.add(m.build()); 40 | } 41 | event.reply(rep.toArray(new MessageEmbed[0])); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/mongoDB/DatabaseQuoteAPI.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis.mongoDB; 2 | 3 | import com.mongodb.client.FindIterable; 4 | import com.mongodb.client.MongoIterable; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | import ml.codeboy.thebot.quotes.Quote; 7 | import ml.codeboy.thebot.quotes.QuoteManager; 8 | import org.bson.Document; 9 | 10 | public class DatabaseQuoteAPI { 11 | /** 12 | * Saves the given quote in the database and adds it to the quote manager 13 | * @param q 14 | */ 15 | public static void saveQuote(Quote q) { 16 | QuoteManager.getInstance().addQuote(q); 17 | Document quote = new Document("content", q.getContent()); 18 | quote.append("time", q.getTime()); 19 | quote.append("authorId", q.getAuthorId()); 20 | quote.append("name",q.getPerson()); 21 | DatabaseManager.getInstance().getQuotesDatabase().getCollection(q.getPerson().toLowerCase()).insertOne(quote); 22 | } 23 | 24 | /** 25 | * Returns all saved persons 26 | * @return 27 | */ 28 | public static MongoIterable getPersons(){ 29 | return DatabaseManager.getInstance().getQuotesDatabase().listCollectionNames(); 30 | } 31 | 32 | /** 33 | * Returns all the quotes of the given person 34 | * @param name 35 | * @return 36 | */ 37 | public static FindIterable getQuotes(String name) 38 | { 39 | return DatabaseManager.getInstance().getQuotesDatabase().getCollection(name.toLowerCase()).find(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/ShittyTranslateCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.translator.GoogleTranslate; 5 | import net.dv8tion.jda.api.interactions.commands.OptionType; 6 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 7 | 8 | import java.io.IOException; 9 | 10 | public class ShittyTranslateCommand extends Command { 11 | public ShittyTranslateCommand() { 12 | super("shittyTranslate", "", "st"); 13 | setGuildOnlyCommand(false); 14 | } 15 | 16 | @Override 17 | public SlashCommandData getCommandData() { 18 | return super.getCommandData().addOption(OptionType.STRING, "text", "the text to translate", true); 19 | } 20 | 21 | @Override 22 | public void run(CommandEvent event) { 23 | String text; 24 | if (event.isSlashCommandEvent()) { 25 | text = event.getSlashCommandEvent().getOption("text").getAsString(); 26 | } else { 27 | text = String.join(" ", event.getArgs()); 28 | } 29 | event.reply(event.getBuilder().setTitle("Please wait").setDescription("this might take a while").setImage("https://i.giphy.com/media/3o7bu3XilJ5BOiSGic/giphy.webp")); 30 | try { 31 | text = GoogleTranslate.shittyTranslate(text); 32 | } catch (IOException e) { 33 | throw new RuntimeException(e); 34 | } 35 | event.edit(event.getBuilder().setTitle("Shitty translate").addField("", text, true)); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/ShitCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.util.Util; 5 | import net.dv8tion.jda.api.entities.Member; 6 | import net.dv8tion.jda.api.entities.User; 7 | 8 | import javax.imageio.ImageIO; 9 | import java.awt.*; 10 | import java.awt.image.BufferedImage; 11 | import java.io.IOException; 12 | import java.net.URL; 13 | import java.util.List; 14 | 15 | public class ShitCommand extends ImageCommand{ 16 | public ShitCommand() { 17 | super("shit", ""); 18 | } 19 | 20 | @Override 21 | protected void generateImage(CommandEvent event) { 22 | 23 | BufferedImage img= null; 24 | User user=event.getUser(); 25 | if (event.isMessageEvent()){ 26 | List members = event.getMessageReceivedEvent().getMessage().getMentions().getMembers(); 27 | if(!members.isEmpty()){ 28 | user=members.get(0).getUser(); 29 | } 30 | } 31 | try { 32 | img = Util.getAvatarImage(user); 33 | } catch (IOException e) { 34 | throw new RuntimeException(e); 35 | } 36 | 37 | BufferedImage shit = null; 38 | try { 39 | shit = ImageIO.read(new URL("https://i.pinimg.com/originals/00/0b/26/000b26a172951b7be6a6107cb8c775dc.jpg")); 40 | } catch (IOException e) { 41 | throw new RuntimeException(e); 42 | } 43 | Graphics g=shit.createGraphics(); 44 | g.drawImage(img,300,800,128,128,null); 45 | g.dispose(); 46 | 47 | event.reply(shit,"jpg","shit"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/MensaVeganika.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import com.github.codeboy.api.Meal; 4 | import com.github.codeboy.api.Mensa; 5 | 6 | import java.util.Date; 7 | import java.util.List; 8 | 9 | public class MensaVeganika implements Mensa { 10 | private final Mensa mensa; 11 | 12 | public MensaVeganika(Mensa mensa) { 13 | this.mensa = mensa; 14 | } 15 | 16 | 17 | @Override 18 | public List getMeals() { 19 | return mensa.getMeals(); 20 | } 21 | 22 | @Override 23 | public List getMeals(Date date) { 24 | return mensa.getMeals(date); 25 | } 26 | 27 | @Override 28 | public List getMeals(String date) { 29 | return mensa.getMeals(date); 30 | } 31 | 32 | @Override 33 | public boolean isOpen() { 34 | return mensa.isOpen(); 35 | } 36 | 37 | @Override 38 | public boolean isOpen(Date date) { 39 | return mensa.isOpen(date); 40 | } 41 | 42 | @Override 43 | public boolean isOpen(String date) { 44 | return mensa.isOpen(date); 45 | } 46 | 47 | @Override 48 | public int getId() { 49 | return mensa.getId(); 50 | } 51 | 52 | @Override 53 | public String getName() { 54 | return mensa.getName().replace("Academica", "Veganika"); 55 | } 56 | 57 | @Override 58 | public String getCity() { 59 | return mensa.getCity(); 60 | } 61 | 62 | @Override 63 | public String getAddress() { 64 | return mensa.getAddress(); 65 | } 66 | 67 | @Override 68 | public List getCoordinates() { 69 | return mensa.getCoordinates(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Loop.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.util.Util; 5 | 6 | public class Loop extends AudioCommand { 7 | public Loop() { 8 | super("loop", "allows you to loop a song"); 9 | } 10 | 11 | @Override 12 | public void run(CommandEvent event) { 13 | if (!ensureConnected(event)) 14 | return; 15 | String firstArg = event.getArgs().length > 0 ? event.getArgs()[0] : ""; 16 | 17 | switch (firstArg) { 18 | case "": { 19 | event.getManager().scheduler.loop(Integer.MAX_VALUE); 20 | event.reply("Songs will be repeated until you skip them"); 21 | break; 22 | } 23 | case "none": { 24 | event.getManager().scheduler.loop(0); 25 | event.getManager().scheduler.dontLoopQueue(); 26 | event.reply("Songs and the queue won't be repeated"); 27 | break; 28 | } 29 | case "queue": { 30 | event.getManager().scheduler.loopQueue(); 31 | event.reply("The current queue will be repeated once the queue ends"); 32 | break; 33 | } 34 | default: { 35 | if (Util.isInt(firstArg)) { 36 | int loop = Util.toInt(firstArg, 0); 37 | event.getManager().scheduler.loop(loop); 38 | event.reply("Songs will be repeated " + loop + " times"); 39 | } else { 40 | event.reply("wrong usage"); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/secret/AcceptImage.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.secret; 2 | 3 | import ml.codeboy.thebot.data.FoodRatingManager; 4 | import ml.codeboy.thebot.data.MealImage; 5 | import ml.codeboy.thebot.data.UserData; 6 | import ml.codeboy.thebot.data.UserDataManager; 7 | import ml.codeboy.thebot.events.CommandEvent; 8 | import net.dv8tion.jda.api.entities.MessageChannel; 9 | import net.dv8tion.jda.api.entities.User; 10 | 11 | import java.util.UUID; 12 | 13 | public class AcceptImage extends SecretCommand { 14 | public AcceptImage() { 15 | super("accept", ""); 16 | } 17 | 18 | public static void accept(MealImage image, MessageChannel channel) { 19 | image.setAccepted(true); 20 | FoodRatingManager.getInstance().saveImages(); 21 | channel.sendMessage("accepted " + image.getUrl()).queue(); 22 | UserData data = UserDataManager.getInstance().getData(image.getAuthor()); 23 | data.setKarma(data.getKarma() + 5); 24 | UserDataManager.getInstance().save(data); 25 | User user = channel.getJDA().getUserById(image.getAuthor()); 26 | if (user != null) { 27 | user.openPrivateChannel().complete() 28 | .sendMessage("Your image has been accepted. Thank you for your contribution. You received 5 karma for this").queue(); 29 | } 30 | } 31 | 32 | @Override 33 | public void run(CommandEvent event) { 34 | String id = event.getArgs()[0]; 35 | MealImage image = FoodRatingManager.getInstance().getImage(UUID.fromString(id)); 36 | if (image == null) 37 | event.replyError("can not find image"); 38 | else { 39 | accept(image, event.getChannel()); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/JermaCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import com.mongodb.client.MongoCollection; 4 | import ml.codeboy.thebot.apis.mongoDB.DatabaseManager; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | import org.bson.Document; 7 | 8 | import static ml.codeboy.thebot.util.Util.shuffle; 9 | 10 | public class JermaCommand extends Command { 11 | 12 | private int p = 0; 13 | 14 | private final MongoCollection collection; 15 | 16 | private Document[] docs; 17 | 18 | private long databaseSize = -1; 19 | 20 | public JermaCommand() { 21 | super("jerma", "Sends a Jerma"); 22 | collection = DatabaseManager.getInstance().getTextDatabase().getCollection("jerma"); 23 | databaseSize = collection.countDocuments(); 24 | docs = new Document[(int)databaseSize]; 25 | { 26 | int i = 0; 27 | for(Object d : collection.find()) 28 | docs[i++] = (Document) d; 29 | } 30 | shuffle(docs); 31 | setGuildOnlyCommand(false); 32 | } 33 | 34 | @Override 35 | public void run(CommandEvent event) { 36 | if(databaseSize!=collection.countDocuments()) 37 | { 38 | databaseSize = collection.countDocuments(); 39 | int i = 0; 40 | docs = new Document[(int)databaseSize]; 41 | for(Object d : collection.find()) 42 | docs[i++] = (Document) d; 43 | shuffle(docs); 44 | p = 0; 45 | getLogger().info("Reloaded Jerma urls"); 46 | } 47 | if(p==databaseSize) 48 | { 49 | shuffle(docs); 50 | p=0; 51 | } 52 | event.reply(docs[p++].getString("url")); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/MensaBot.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot; 2 | 3 | import net.dv8tion.jda.api.JDA; 4 | import net.dv8tion.jda.api.JDABuilder; 5 | import net.dv8tion.jda.api.requests.GatewayIntent; 6 | import net.dv8tion.jda.api.utils.cache.CacheFlag; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import javax.security.auth.login.LoginException; 11 | 12 | public class MensaBot implements Bot { 13 | 14 | private static MensaBot instance;//I don't really want to make this a singleton so I didn't make this final 15 | private final CommandHandler commandHandler; 16 | private final JDA jda; 17 | private final Logger logger 18 | = LoggerFactory.getLogger(getClass()); 19 | 20 | public MensaBot() throws LoginException, InterruptedException { 21 | jda = JDABuilder.createDefault(Config.getInstance().token) 22 | .enableIntents(GatewayIntent.DIRECT_MESSAGES, 23 | GatewayIntent.GUILD_MEMBERS, 24 | GatewayIntent.MESSAGE_CONTENT, 25 | GatewayIntent.GUILD_PRESENCES) 26 | .enableCache(CacheFlag.ONLINE_STATUS, CacheFlag.ACTIVITY).build(); 27 | jda.awaitReady(); 28 | commandHandler = new CommandHandler(this); 29 | instance = this; 30 | logger.info("Bot started"); 31 | } 32 | 33 | public static void main(String[] args) throws LoginException, InterruptedException { 34 | new MensaBot(); 35 | } 36 | 37 | public static MensaBot getInstance() { 38 | return instance; 39 | } 40 | 41 | @Override 42 | public JDA getJda() { 43 | return jda; 44 | } 45 | 46 | @Override 47 | public CommandHandler getCmdHandler() { 48 | return commandHandler; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/GuildManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import com.google.gson.Gson; 4 | import net.dv8tion.jda.api.entities.Guild; 5 | 6 | import java.io.*; 7 | import java.util.HashMap; 8 | 9 | public class GuildManager { 10 | private static final String guildFolder = "guilds"; 11 | 12 | private static final GuildManager instance = new GuildManager(); 13 | private final HashMap guildData = new HashMap<>(); 14 | 15 | private GuildManager() { 16 | } 17 | 18 | public static GuildManager getInstance() { 19 | return instance; 20 | } 21 | 22 | public GuildData getData(Guild guild) { 23 | GuildData data = guildData.get(guild.getId()); 24 | if (data != null) { 25 | return data; 26 | } 27 | try { 28 | return loadData(guild); 29 | } catch (FileNotFoundException ignored) { 30 | } 31 | data = new GuildData(guild); 32 | guildData.put(guild.getId(), data); 33 | return data; 34 | } 35 | 36 | 37 | public GuildData loadData(Guild guild) throws FileNotFoundException { 38 | return loadData(guild.getId()); 39 | } 40 | 41 | 42 | private GuildData loadData(String id) throws FileNotFoundException { 43 | GuildData data = new Gson().fromJson(new FileReader(guildFolder + File.separator + id), GuildData.class); 44 | return data; 45 | } 46 | 47 | public void save(GuildData data) { 48 | try { 49 | new File(guildFolder).mkdirs(); 50 | FileWriter writer = new FileWriter(guildFolder + File.separator + data.getId()); 51 | new Gson().toJson(data, writer); 52 | writer.close(); 53 | } catch (IOException ex) { 54 | ex.printStackTrace(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/Karma.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.data.UserDataManager; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.EmbedBuilder; 6 | import net.dv8tion.jda.api.entities.Member; 7 | import net.dv8tion.jda.api.entities.User; 8 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 9 | import net.dv8tion.jda.api.interactions.commands.OptionType; 10 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 11 | 12 | import java.util.List; 13 | 14 | public class Karma extends Command { 15 | public Karma() { 16 | super("Karma", "gives the karma of a user"); 17 | setGuildOnlyCommand(false); 18 | } 19 | 20 | @Override 21 | public SlashCommandData getCommandData() { 22 | return super.getCommandData().addOption(OptionType.USER, "user", "the user to get the karma of", false); 23 | } 24 | 25 | @Override 26 | public void run(CommandEvent event) { 27 | User user = event.getUser(); 28 | if (event.isSlashCommandEvent()) { 29 | OptionMapping om = event.getSlashCommandEvent().getOption("user"); 30 | if (om != null) 31 | user = om.getAsMember().getUser(); 32 | } else if (event.isMessageEvent()) { 33 | List members = event.getMessageReceivedEvent().getMessage().getMentions().getMembers(); 34 | if (!members.isEmpty() && members.get(0) != null) 35 | user = members.get(0).getUser(); 36 | } 37 | int karma = UserDataManager.getInstance().getData(user).getKarma(); 38 | EmbedBuilder builder = event.getBuilder(); 39 | builder.setTitle("Karma of " + user.getAsTag()) 40 | .setDescription(karma + ""); 41 | event.reply(builder); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/ImageCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image; 2 | 3 | import ml.codeboy.thebot.commands.Command; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | 6 | import java.awt.*; 7 | import java.awt.geom.Rectangle2D; 8 | 9 | public abstract class ImageCommand extends Command { 10 | public ImageCommand(String name, String description, String... aliases) { 11 | super(name, description, aliases); 12 | setHidden(true); 13 | } 14 | 15 | @Override 16 | public void run(CommandEvent event) { 17 | generateImage(event); 18 | } 19 | 20 | 21 | public static boolean drawString(Graphics g, String s, Rectangle position) { 22 | return drawString(g, s, position, Color.BLACK); 23 | } 24 | 25 | public static boolean drawString(Graphics g, String s, Rectangle position, Color color) { 26 | g.setFont(g.getFont().deriveFont(1f)); 27 | 28 | while (fits(g, s, position)) { 29 | changeSize(g, 1); 30 | } 31 | changeSize(g, -1); 32 | 33 | if (g.getFont().getSize() < 8) 34 | return false;//this is too small to read 35 | 36 | g.setColor(color); 37 | g.drawString(s, position.x, position.y + position.height); 38 | return true; 39 | } 40 | 41 | public static boolean fits(Graphics g, String msg, Rectangle pos) { 42 | return biggerThan(pos, g.getFontMetrics().getStringBounds(msg, g)); 43 | } 44 | 45 | public static boolean biggerThan(Rectangle2D r, Rectangle2D r2) { 46 | return r.getWidth() > r2.getWidth() && r.getHeight() > r2.getHeight(); 47 | } 48 | 49 | public static void changeSize(Graphics g, int amount) { 50 | g.setFont(g.getFont().deriveFont((float) g.getFont().getSize() + amount)); 51 | } 52 | 53 | protected abstract void generateImage(CommandEvent event); 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/RhymeCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.apis.RhymeApi; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.EmbedBuilder; 6 | import net.dv8tion.jda.api.entities.MessageEmbed; 7 | import net.dv8tion.jda.api.interactions.commands.OptionType; 8 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 9 | 10 | import java.awt.*; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class RhymeCommand extends Command { 15 | public RhymeCommand() { 16 | super("rhyme", "Gives you a word that rhymes with the one provided"); 17 | setGuildOnlyCommand(false); 18 | } 19 | 20 | @Override 21 | public SlashCommandData getCommandData() { 22 | return super.getCommandData() 23 | .addOption(OptionType.STRING, "word" 24 | , "The word to find rhymes for", true); 25 | } 26 | 27 | @Override 28 | public void run(CommandEvent event) { 29 | String[] args = event.getArgs(); 30 | if (args.length == 0) { 31 | event.reply(newBuilder().setColor(Color.RED).setTitle("Error") 32 | .setDescription("Please provide a word")); 33 | } else { 34 | String word = args[0]; 35 | ArrayList words = RhymeApi.getInstance().getRhymingWords(word); 36 | EmbedBuilder builder = newBuilder(); 37 | builder.setTitle("Words that rhyme with " + word); 38 | for (String w : words) { 39 | if (!builder.isValidLength()) { 40 | List fields = builder.getFields(); 41 | fields.remove(fields.size() - 1); 42 | break; 43 | } 44 | builder.addField(w, "", true); 45 | } 46 | event.reply(builder); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/mensa/DefaultMensaCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.mensa; 2 | 3 | import com.github.codeboy.OpenMensa; 4 | import com.github.codeboy.api.Mensa; 5 | import ml.codeboy.thebot.commands.Command; 6 | import ml.codeboy.thebot.events.CommandEvent; 7 | import net.dv8tion.jda.api.EmbedBuilder; 8 | import net.dv8tion.jda.api.Permission; 9 | import net.dv8tion.jda.api.interactions.commands.OptionType; 10 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 11 | 12 | import java.awt.*; 13 | 14 | public class DefaultMensaCommand extends Command { 15 | public DefaultMensaCommand() { 16 | super("default_mensa", "Sets the default mensa for this server"); 17 | setRequiredPermissions(Permission.MANAGE_SERVER); 18 | } 19 | 20 | @Override 21 | public SlashCommandData getCommandData() { 22 | return super.getCommandData().addOption(OptionType.INTEGER, "id", "Id of the new default Mensa", true); 23 | } 24 | 25 | @Override 26 | public void run(CommandEvent event) { 27 | String[] args = event.getArgs(); 28 | if (args.length == 0) { 29 | event.replyError("Missing argument"); 30 | } else { 31 | try { 32 | int i = Integer.parseInt(args[0]); 33 | Mensa mensa = OpenMensa.getInstance().getMensa(i); 34 | if (mensa == null) { 35 | event.replyError("Unable to find mensa with id " + i); 36 | } else { 37 | event.reply(new EmbedBuilder().setTitle("Success").setDescription("New default mensa for server is " + mensa.getName()) 38 | .setColor(Color.GREEN)); 39 | event.getGuildData().setDefaultMensaId(i); 40 | } 41 | } catch (NumberFormatException e) { 42 | event.replyError("Invalid argument. Expected Integer"); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/GuildData.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import com.github.codeboy.OpenMensa; 4 | import com.github.codeboy.api.Mensa; 5 | import ml.codeboy.thebot.apis.MensaVeganika; 6 | import net.dv8tion.jda.api.entities.Guild; 7 | 8 | public class GuildData { 9 | private final transient Guild guild; 10 | private final String guildId; 11 | private String latestAnnouncementId = ""; 12 | private int defaultMensaId = 187; 13 | private String updateChannelId = ""; 14 | 15 | public GuildData(Guild guild) { 16 | this.guild = guild; 17 | guildId = guild.getId(); 18 | } 19 | 20 | 21 | public Guild getGuild() { 22 | return guild; 23 | } 24 | 25 | 26 | public Mensa getDefaultMensa() { 27 | Mensa mensa = OpenMensa.getInstance().getMensa(getDefaultMensaId()); 28 | if (getId().equals("896116435875668019")) 29 | mensa = new MensaVeganika(mensa);//such a useless feature 30 | return mensa; 31 | } 32 | 33 | public int getDefaultMensaId() { 34 | return defaultMensaId; 35 | } 36 | 37 | public void setDefaultMensaId(int defaultMensaId) { 38 | this.defaultMensaId = defaultMensaId; 39 | save(); 40 | } 41 | 42 | public String getUpdateChannelId() { 43 | return updateChannelId; 44 | } 45 | 46 | public void setUpdateChannelId(String updateChannelId) { 47 | this.updateChannelId = updateChannelId; 48 | save(); 49 | } 50 | 51 | public void save() { 52 | GuildManager.getInstance().save(this); 53 | } 54 | 55 | public String getId() { 56 | return guildId; 57 | } 58 | 59 | //region getter setter 60 | public String getLatestAnnouncementId() { 61 | return latestAnnouncementId; 62 | } 63 | 64 | public void setLatestAnnouncementId(String latestAnnouncementId) { 65 | this.latestAnnouncementId = latestAnnouncementId; 66 | } 67 | //endregion 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/ASCIICommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.events.CommandEvent; 4 | import ml.codeboy.thebot.util.ASCII; 5 | import ml.codeboy.thebot.util.Util; 6 | import net.dv8tion.jda.api.entities.Message; 7 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 8 | 9 | import java.awt.image.BufferedImage; 10 | import java.io.IOException; 11 | 12 | public class ASCIICommand extends Command { 13 | public ASCIICommand() { 14 | super("ascii", "converts and image to ascii"); 15 | setHidden(true); 16 | } 17 | 18 | @Override 19 | public SlashCommandData getCommandData() { 20 | return null;//make sure not slash command gets registered 21 | } 22 | 23 | @Override 24 | public void run(CommandEvent event) { 25 | if (event.isSlashCommandEvent()) { 26 | getLogger().warn("command was run as slash command which should not be possible"); 27 | return;//this should never happen 28 | } 29 | Message message = event.getMessageReceivedEvent().getMessage(); 30 | String url; 31 | if (message.getAttachments().isEmpty()) { 32 | String[] args = event.getArgs(); 33 | if (args.length == 0) { 34 | event.replyError("please attach an image or supply an url"); 35 | return; 36 | } 37 | url = args[0]; 38 | } else { 39 | Message.Attachment attachment = message.getAttachments().get(0); 40 | url = attachment.getUrl(); 41 | } 42 | try { 43 | BufferedImage image = Util.getImageFromUrl(url); 44 | String ascii = ASCII.convert(ASCII.scale(image)); 45 | if (ascii.length() < 2000) 46 | event.reply("\n```" + ascii + "```"); 47 | else event.replyError("too much text " + ascii.length()); 48 | } catch (IOException e) { 49 | event.replyError("unable to load image from url"); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/secret/RickRoll.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.secret; 2 | 3 | import ml.codeboy.thebot.commands.sound.PlayerManager; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.JDA; 6 | import net.dv8tion.jda.api.entities.AudioChannel; 7 | 8 | import java.io.File; 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | 14 | public class RickRoll extends SecretCommand { 15 | public RickRoll() { 16 | super("rickroll", "", "rick"); 17 | } 18 | 19 | @Override 20 | public void run(CommandEvent event) { 21 | String[] args = event.getArgs(); 22 | if (args.length > 0) { 23 | JDA jda = event.getJdaEvent().getJDA(); 24 | AudioChannel channel = jda.getVoiceChannelById(args[0]); 25 | channel.getGuild().getAudioManager().openAudioConnection(channel); 26 | ArrayList a = new ArrayList<>(Arrays.asList(args)); 27 | if (a.size() > 0) 28 | a.remove(0); 29 | String song = String.join(" ", a); 30 | if (song.isEmpty()) 31 | song = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"; 32 | if (!isUrl(song)) 33 | song = toYtUrl(song); 34 | 35 | PlayerManager.getInstance().load(event, channel.getGuild(), song, true, false, false, false); 36 | } 37 | } 38 | 39 | private String toYtUrl(String link) { 40 | if (!isUrl(link)) { 41 | File file = new File("music" + File.separator + link + ".mp3"); 42 | if (file.exists())//music available offline 43 | { 44 | return "file://" + file.getPath(); 45 | } 46 | link = "ytsearch:" + link; 47 | } 48 | return link; 49 | } 50 | 51 | private boolean isUrl(String url) { 52 | try { 53 | new URL(url); 54 | return true; 55 | } catch (MalformedURLException e) { 56 | return false; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/MorbCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image; 2 | 3 | import de.cerus.jgif.GifImage; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.util.Util; 6 | import net.dv8tion.jda.api.entities.Member; 7 | import net.dv8tion.jda.api.entities.User; 8 | 9 | import java.awt.*; 10 | import java.awt.image.BufferedImage; 11 | import java.io.File; 12 | import java.io.FileNotFoundException; 13 | import java.io.IOException; 14 | import java.util.List; 15 | import java.util.Random; 16 | 17 | public class MorbCommand extends ImageCommand { 18 | public MorbCommand() { 19 | super("morb", "I'm gonna morb"); 20 | } 21 | 22 | private final Random random=new Random(); 23 | 24 | @Override 25 | protected void generateImage(CommandEvent event) { 26 | 27 | BufferedImage img= null; 28 | User user=event.getUser(); 29 | if (event.isMessageEvent()){ 30 | List members = event.getMessageReceivedEvent().getMessage().getMentions().getMembers(); 31 | if(!members.isEmpty()){ 32 | user=members.get(0).getUser(); 33 | } 34 | } 35 | try { 36 | img = Util.getAvatarImage(user); 37 | } catch (IOException e) { 38 | throw new RuntimeException(e); 39 | } 40 | 41 | GifImage image = new GifImage(); 42 | image.setOutputFile(new File("images/morb_"+random.nextInt()+".gif")); 43 | try { 44 | image.loadFrom(new File("images/morb.gif")); 45 | } catch (FileNotFoundException e) { 46 | e.printStackTrace(); 47 | return; 48 | } 49 | 50 | for (int i = 0; i < image.getFrames().size(); i++) { 51 | BufferedImage frame = image.getFrame(i); 52 | Graphics graphics = frame.getGraphics(); 53 | graphics.drawImage(img,80,50,64,64,null); 54 | graphics.dispose(); 55 | image.setFrame(i, frame); 56 | } 57 | image.save(); 58 | event.getChannel().sendFile(image.getOutputFile()).complete(); 59 | image.getOutputFile().delete(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/Config.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot; 2 | 3 | import com.google.gson.Gson; 4 | import net.dv8tion.jda.api.entities.User; 5 | 6 | import java.io.FileNotFoundException; 7 | import java.io.FileReader; 8 | import java.io.FileWriter; 9 | import java.io.IOException; 10 | import java.util.*; 11 | 12 | public class Config { 13 | private static Config instance; 14 | 15 | static { 16 | try { 17 | instance = new Gson().fromJson(new FileReader("config.json"), Config.class); 18 | } catch (FileNotFoundException ignored) { 19 | } 20 | try { 21 | FileWriter writer = new FileWriter("config.json"); 22 | new Gson().toJson(instance == null ? (instance = new Config()) : instance, writer); 23 | writer.close(); 24 | } catch (IOException ex) { 25 | ex.printStackTrace(); 26 | } 27 | } 28 | 29 | public String token = "token"; 30 | public String serverId = "0"; 31 | public String prefix = "!"; 32 | public boolean quoteStatus = true; 33 | public Set debugAccounts = new HashSet<>(Arrays.asList("412330776886247424", 34 | "902979780394221648", "358247499531681803"));//eg contributers - for debugging 35 | public List upvoteEmotes = Collections.singletonList("hochwaehli:903336533992550420"), 36 | downVoteEmotes = Collections.singletonList("runterwaehli:903336514644222033"); 37 | public String mongoDB_URL = ""; 38 | public List debugChannels = Arrays.asList("993961018919235644", "966789128375140412");//will receive logs 39 | 40 | public Set admins = new HashSet<>(Collections.singletonList("412330776886247424"));//can use secret commands 41 | 42 | public String dmDebugChannel = "966789128375140412"; 43 | public String openWeatherApiKey = ""; 44 | 45 | public static Config getInstance() { 46 | return instance; 47 | } 48 | 49 | 50 | public boolean isUpvote(String s) { 51 | return upvoteEmotes.contains(s); 52 | } 53 | 54 | public boolean isDownvote(String s) { 55 | return downVoteEmotes.contains(s); 56 | } 57 | 58 | public boolean isDebugAccount(User user) { 59 | return debugAccounts.contains(user.getId()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/events/MessageCommandEvent.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.events; 2 | 3 | import net.dv8tion.jda.api.entities.*; 4 | import net.dv8tion.jda.api.events.message.MessageReceivedEvent; 5 | 6 | import java.io.File; 7 | import java.util.Arrays; 8 | 9 | public class MessageCommandEvent extends CommandEvent { 10 | 11 | private Message reply = null; 12 | 13 | public MessageCommandEvent(MessageReceivedEvent jdaEvent) { 14 | super(jdaEvent); 15 | } 16 | 17 | @Override 18 | public void reply(String message) { 19 | MessageReceivedEvent event = getMessageReceivedEvent(); 20 | reply = event.getChannel().sendMessage(message).complete(); 21 | } 22 | 23 | @Override 24 | public void reply(MessageEmbed... embed) { 25 | reply = getMessageReceivedEvent().getChannel().sendMessageEmbeds(Arrays.asList(embed)).complete(); 26 | } 27 | 28 | @Override 29 | public void reply(File file, String name) { 30 | reply = getMessageReceivedEvent().getChannel().sendFile(file, name).complete(); 31 | } 32 | 33 | @Override 34 | public void reply(String message, File file, String name) { 35 | reply = getMessageReceivedEvent().getChannel().sendMessage(message).addFile(file, name).complete(); 36 | } 37 | 38 | @Override 39 | public User getUser() { 40 | return getMessageReceivedEvent().getAuthor(); 41 | } 42 | 43 | @Override 44 | public Member getMember() { 45 | return getMessageReceivedEvent().getMember(); 46 | } 47 | 48 | @Override 49 | public void edit(String message) { 50 | if (reply == null) 51 | throw new IllegalStateException("Can not edit message without replying first"); 52 | reply = reply.editMessage(message).complete(); 53 | } 54 | 55 | @Override 56 | public void edit(MessageEmbed... embed) { 57 | if (reply == null) 58 | throw new IllegalStateException("Can not edit message without replying first"); 59 | reply = reply.editMessageEmbeds(embed).complete(); 60 | } 61 | 62 | @Override 63 | public Guild getGuild() { 64 | return getMessageReceivedEvent().getGuild(); 65 | } 66 | 67 | @Override 68 | public MessageChannel getChannel() { 69 | return getMessageReceivedEvent().getChannel(); 70 | } 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/KarmaTop.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.CommandHandler; 4 | import ml.codeboy.thebot.data.UserData; 5 | import ml.codeboy.thebot.data.UserDataManager; 6 | import ml.codeboy.thebot.events.CommandEvent; 7 | import net.dv8tion.jda.api.EmbedBuilder; 8 | import net.dv8tion.jda.api.JDA; 9 | import net.dv8tion.jda.api.entities.MessageEmbed; 10 | 11 | import java.awt.*; 12 | import java.util.List; 13 | 14 | public class KarmaTop extends Command { 15 | public static final long updateInterval = 6000; 16 | 17 | public KarmaTop() { 18 | super("KarmaTop", "Karma Bestenliste", "kt"); 19 | setGuildOnlyCommand(false); 20 | } 21 | 22 | private CommandEvent latestEvent; 23 | private MessageEmbed karmaTop = new EmbedBuilder().setTitle("Loading KarmaTop") 24 | .setDescription("please wait a few seconds\nI will update the message when I'm done").setColor(Color.RED).build(); 25 | 26 | @Override 27 | public void register(CommandHandler handler) { 28 | // updateKarmaTop(handler.getServer().getJDA());//initialisation is done when the command is first run 29 | } 30 | 31 | private long lastUpdated = 0; 32 | 33 | @Override 34 | public void run(CommandEvent event) { 35 | latestEvent = event; 36 | event.reply(getKarmaTop(event.getJdaEvent().getJDA())); 37 | } 38 | 39 | private MessageEmbed getKarmaTop(JDA jda) { 40 | if (lastUpdated + updateInterval < System.currentTimeMillis()) { 41 | updateKarmaTop(jda); 42 | } 43 | return karmaTop; 44 | } 45 | 46 | private void updateKarmaTop(JDA jda) { 47 | new Thread(() -> { 48 | EmbedBuilder builder = new EmbedBuilder(); 49 | builder.setTitle("KarmaTop"); 50 | List karmaTop = UserDataManager.getInstance().getKarmaSorted(); 51 | for (int i = 0; i < 10; i++) { 52 | UserData data = karmaTop.get(i); 53 | builder.addField(i + 1 + ".", data.getTag(jda) + " " + data.getKarma(), false); 54 | } 55 | this.karmaTop = builder.build(); 56 | lastUpdated = System.currentTimeMillis(); 57 | if (latestEvent != null) 58 | latestEvent.edit(this.karmaTop); 59 | }).start(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/mongoDB/DatabaseManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis.mongoDB; 2 | 3 | import com.mongodb.*; 4 | import com.mongodb.client.MongoClient; 5 | import com.mongodb.client.MongoClients; 6 | import com.mongodb.client.MongoCollection; 7 | import com.mongodb.client.MongoDatabase; 8 | import ml.codeboy.thebot.Config; 9 | import org.bson.BsonDocument; 10 | import org.bson.BsonInt64; 11 | import org.bson.Document; 12 | import org.bson.conversions.Bson; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | public class DatabaseManager { 17 | 18 | private static final DatabaseManager database_instance; 19 | 20 | static { 21 | database_instance = new DatabaseManager(); 22 | } 23 | 24 | private final MongoDatabase quotesDatabase; 25 | private final MongoDatabase textDatabase; 26 | private final MongoCollection karma; 27 | private final MongoClient mongoClient; 28 | private final Logger logger 29 | = LoggerFactory.getLogger(getClass()); 30 | 31 | public DatabaseManager() { 32 | ConnectionString connectionString = new ConnectionString(Config.getInstance().mongoDB_URL); 33 | MongoClientSettings settings = MongoClientSettings.builder() 34 | .applyConnectionString(connectionString) 35 | .serverApi(ServerApi.builder() 36 | .version(ServerApiVersion.V1) 37 | .build()) 38 | .build(); 39 | mongoClient = MongoClients.create(settings); 40 | quotesDatabase = mongoClient.getDatabase("quotes"); 41 | textDatabase = mongoClient.getDatabase("text"); 42 | karma = mongoClient.getDatabase("karma").getCollection("karma"); 43 | try { 44 | Bson command = new BsonDocument("ping", new BsonInt64(1)); 45 | Document commandResult = quotesDatabase.runCommand(command); 46 | logger.info("Connected successfully to server."); 47 | } catch (MongoException me) { 48 | logger.error("An error occurred while attempting to run a command: " + me); 49 | } 50 | } 51 | 52 | public static DatabaseManager getInstance(){return database_instance;} 53 | 54 | public MongoDatabase getQuotesDatabase(){return quotesDatabase;} 55 | public MongoCollection getKarma(){return karma;} 56 | public MongoDatabase getTextDatabase(){return textDatabase;} 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/KarmaBottom.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.CommandHandler; 4 | import ml.codeboy.thebot.data.UserData; 5 | import ml.codeboy.thebot.data.UserDataManager; 6 | import ml.codeboy.thebot.events.CommandEvent; 7 | import net.dv8tion.jda.api.EmbedBuilder; 8 | import net.dv8tion.jda.api.JDA; 9 | import net.dv8tion.jda.api.entities.MessageEmbed; 10 | 11 | import java.awt.*; 12 | import java.util.List; 13 | 14 | import static ml.codeboy.thebot.commands.KarmaTop.updateInterval; 15 | 16 | public class KarmaBottom extends Command { 17 | private CommandEvent latestEvent; 18 | 19 | public KarmaBottom() { 20 | super("KarmaBottom", "Karma Schlechtestenliste", "kb"); 21 | setGuildOnlyCommand(false); 22 | } 23 | 24 | private MessageEmbed karmaTop = new EmbedBuilder().setTitle("Loading KarmaBottom") 25 | .setDescription("please wait a few seconds\nI will update the message when I'm done").setColor(Color.RED).build(); 26 | 27 | @Override 28 | public void register(CommandHandler handler) { 29 | // updateKarmaTop(handler.getServer().getJDA());//initialisation is done when the command is first run 30 | } 31 | 32 | @Override 33 | public void run(CommandEvent event) { 34 | latestEvent = event; 35 | event.reply(getKarmaTop(event.getJdaEvent().getJDA())); 36 | } 37 | private long lastUpdated = 0; 38 | 39 | private MessageEmbed getKarmaTop(JDA jda) { 40 | if (lastUpdated + updateInterval < System.currentTimeMillis()) { 41 | updateKarmaTop(jda); 42 | } 43 | return karmaTop; 44 | } 45 | 46 | private void updateKarmaTop(JDA jda) { 47 | new Thread(() -> { 48 | EmbedBuilder builder = new EmbedBuilder(); 49 | builder.setTitle("KarmaBottom"); 50 | List karmaTop = UserDataManager.getInstance().getKarmaSorted(); 51 | for (int i = 0; i < 10; i++) { 52 | UserData data = karmaTop.get(karmaTop.size() - (i + 1)); 53 | builder.addField(i + 1 + ".", data.getTag(jda) + " " + data.getKarma(), false); 54 | } 55 | this.karmaTop = builder.build(); 56 | lastUpdated = System.currentTimeMillis(); 57 | if (latestEvent != null) 58 | latestEvent.edit(this.karmaTop); 59 | }).start(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/mensa/MensaAnnounceChannelCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.mensa; 2 | 3 | import ml.codeboy.thebot.commands.Command; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.Permission; 6 | import net.dv8tion.jda.api.entities.MessageChannel; 7 | import net.dv8tion.jda.api.entities.TextChannel; 8 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 9 | import net.dv8tion.jda.api.interactions.commands.OptionType; 10 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 11 | 12 | import java.util.List; 13 | 14 | public class MensaAnnounceChannelCommand extends Command { 15 | public MensaAnnounceChannelCommand() { 16 | super("mensaAnnounceChannel", "Sets the channel where the bot will announce the current mensa meals daily"); 17 | setRequiredPermissions(Permission.MANAGE_SERVER); 18 | } 19 | 20 | @Override 21 | public SlashCommandData getCommandData() { 22 | return super.getCommandData().addOption(OptionType.CHANNEL, "channel", "the channel to post the meals in"); 23 | } 24 | 25 | @Override 26 | public void run(CommandEvent event) { 27 | if (event.isMessageEvent()) { 28 | List channels = event.getMessageReceivedEvent().getMessage().getMentions().getChannels(TextChannel.class); 29 | if (channels.isEmpty()) { 30 | deactivate(event); 31 | } else { 32 | setUpdateChannel(event, channels.get(0)); 33 | } 34 | } else { 35 | List options = event.getSlashCommandEvent().getOptions(); 36 | MessageChannel channel = null; 37 | if (!options.isEmpty()) { 38 | channel = options.get(0).getAsChannel().asTextChannel(); 39 | } 40 | if (channel == null) { 41 | deactivate(event); 42 | } else { 43 | setUpdateChannel(event, channel); 44 | } 45 | } 46 | } 47 | 48 | private void deactivate(CommandEvent event) { 49 | event.reply("Deactivating meal announcement");//todo fix 50 | event.getGuildData().setUpdateChannelId(""); 51 | } 52 | 53 | private void setUpdateChannel(CommandEvent event, MessageChannel channel) { 54 | event.getGuildData().setUpdateChannelId(channel.getId()); 55 | event.reply("Meals will be sent to " + channel.getAsMention()); 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/image/meme/MemeGeneratorCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.image.meme; 2 | 3 | import ml.codeboy.thebot.commands.image.ImageCommand; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.util.Util; 6 | 7 | import java.awt.*; 8 | import java.awt.image.BufferedImage; 9 | import java.io.IOException; 10 | 11 | public class MemeGeneratorCommand extends ImageCommand { 12 | private String type = "jpg"; 13 | private Rectangle[] bounds; 14 | 15 | private float imageScale = 1; 16 | private BufferedImage image = null; 17 | 18 | public MemeGeneratorCommand(String image, String name, String description, String... aliases) { 19 | super(name, description, aliases); 20 | try { 21 | this.image = Util.getImageFromUrl(image); 22 | } catch (IOException e) { 23 | throw new RuntimeException(e); 24 | } 25 | } 26 | 27 | protected void setImageScale(float imageScale) { 28 | this.imageScale = imageScale; 29 | } 30 | 31 | protected void setType(String type) { 32 | this.type = type; 33 | } 34 | 35 | protected void setBounds(Rectangle... bounds) { 36 | this.bounds = bounds; 37 | for (Rectangle r:bounds){ 38 | r.x*=imageScale; 39 | r.y*=imageScale; 40 | r.width*=imageScale; 41 | r.height*=imageScale; 42 | } 43 | } 44 | 45 | @Override 46 | protected void generateImage(CommandEvent event) { 47 | String text = String.join(" ", event.getArgs()); 48 | String[] captions = text.split(";"); 49 | Image background = this.image.getScaledInstance((int) (this.image.getWidth() * imageScale), (int) (this.image.getHeight() * imageScale), Image.SCALE_DEFAULT); 50 | BufferedImage image = new BufferedImage(background.getWidth(null), background.getHeight(null), BufferedImage.TYPE_INT_RGB); 51 | 52 | Graphics g = image.createGraphics(); 53 | g.drawImage(background,0,0,null); 54 | for (int i = 0; i < bounds.length; i++) { 55 | if (captions.length <= i) 56 | break; 57 | boolean success = drawString(g, captions[i], bounds[i]); 58 | if (!success) { 59 | g.dispose(); 60 | event.replyError("That is too much text!"); 61 | return; 62 | } 63 | } 64 | g.dispose(); 65 | 66 | event.reply(image, type, getName()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/EmojiManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.InputStreamReader; 10 | import java.nio.charset.StandardCharsets; 11 | import java.util.ArrayList; 12 | import java.util.Collection; 13 | import java.util.Comparator; 14 | 15 | public class EmojiManager { 16 | private static final EmojiManager instance = new EmojiManager(); 17 | private final Logger logger 18 | = LoggerFactory.getLogger(getClass()); 19 | private final Collection emojis; 20 | 21 | public EmojiManager() { 22 | emojis = new ArrayList<>(); 23 | InputStream stream = EmojiManager.class.getResourceAsStream("/emojis.csv"); 24 | String line, name = null, word, prio = null; 25 | try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { 26 | while ((line = bufferedReader.readLine()) != null) { 27 | String[] args = line.split(","); 28 | name = args[0]; 29 | word = args[1]; 30 | MealEmoji emoji = getMatching(name); 31 | if (emoji == null) { 32 | prio = args.length > 2 ? args[2] : ""; 33 | int priority = args.length > 2 ? Integer.parseInt(prio) : getMinPriority() - 1; 34 | emoji = new MealEmoji(word, new ArrayList<>(), priority); 35 | emojis.add(emoji); 36 | } 37 | emoji.getNames().add(name); 38 | } 39 | 40 | } catch (NumberFormatException nfe) { 41 | logger.warn(name + " has invalid priority " + prio); 42 | } catch (IOException e) { 43 | throw new RuntimeException(e); 44 | } 45 | } 46 | 47 | private int getMinPriority() { 48 | MealEmoji min = emojis.stream().min(Comparator.comparing(MealEmoji::getPriority)).orElse(null); 49 | if (min == null) 50 | return 1000; 51 | return min.getPriority(); 52 | } 53 | 54 | public static EmojiManager getInstance() { 55 | return instance; 56 | } 57 | 58 | public MealEmoji getMatching(String content) { 59 | return emojis.stream().filter(e -> e.getNames().stream().anyMatch(content::contains)) 60 | .max(Comparator.comparing(MealEmoji::getPriority)).orElse(null); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/Echo.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.commands.Command; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.audio.AudioReceiveHandler; 6 | import net.dv8tion.jda.api.audio.AudioSendHandler; 7 | import net.dv8tion.jda.api.audio.CombinedAudio; 8 | import net.dv8tion.jda.api.entities.AudioChannel; 9 | import net.dv8tion.jda.api.managers.AudioManager; 10 | 11 | import java.nio.ByteBuffer; 12 | import java.util.Queue; 13 | import java.util.concurrent.ConcurrentLinkedQueue; 14 | 15 | public class Echo extends Command { 16 | public Echo() { 17 | super("echo", "makes the bot repeat everything you say"); 18 | } 19 | 20 | 21 | @Override 22 | public void run(CommandEvent event) { 23 | AudioChannel channel = event.getMember().getVoiceState() == null ? 24 | event.getGuild().getAfkChannel() : event.getMember().getVoiceState().getChannel(); 25 | if (channel == null) { 26 | event.reply("please join a voice channel and run the command again"); 27 | return; 28 | } 29 | 30 | AudioManager audioManager = event.getGuild().getAudioManager(); 31 | 32 | EchoHandler handler = new EchoHandler(); 33 | 34 | audioManager.setSendingHandler(handler); 35 | audioManager.setReceivingHandler(handler); 36 | audioManager.openAudioConnection(channel); 37 | } 38 | 39 | public static class EchoHandler implements AudioSendHandler, AudioReceiveHandler { 40 | private final Queue queue = new ConcurrentLinkedQueue<>(); 41 | 42 | 43 | @Override 44 | public boolean canReceiveCombined() { 45 | return queue.size() < 10; 46 | } 47 | 48 | @Override 49 | public void handleCombinedAudio(CombinedAudio combinedAudio) { 50 | if (combinedAudio.getUsers().isEmpty()) 51 | return; 52 | 53 | byte[] data = combinedAudio.getAudioData(1.0f); 54 | queue.add(data); 55 | } 56 | 57 | @Override 58 | public boolean canProvide() { 59 | return !queue.isEmpty(); 60 | } 61 | 62 | @Override 63 | public ByteBuffer provide20MsAudio() { 64 | byte[] data = queue.poll(); 65 | return data == null ? null : ByteBuffer.wrap(data); 66 | } 67 | 68 | @Override 69 | public boolean isOpus() { 70 | return false; 71 | } 72 | } 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/events/SlashCommandCommandEvent.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.events; 2 | 3 | import net.dv8tion.jda.api.entities.*; 4 | import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; 5 | 6 | import java.io.File; 7 | import java.util.Arrays; 8 | 9 | public class SlashCommandCommandEvent extends CommandEvent { 10 | public SlashCommandCommandEvent(SlashCommandInteractionEvent jdaEvent) { 11 | super(jdaEvent); 12 | jdaEvent.deferReply(isEphermal()).queue(); 13 | } 14 | 15 | @Override 16 | public void reply(String message) { 17 | SlashCommandInteractionEvent event = getSlashCommandEvent(); 18 | event.getHook().sendMessage(message).queue(); 19 | } 20 | 21 | @Override 22 | public void reply(MessageEmbed... embed) { 23 | if (getSlashCommandEvent().isAcknowledged()) { 24 | getSlashCommandEvent().getHook().editOriginalEmbeds(embed).queue(); 25 | } else 26 | getSlashCommandEvent().replyEmbeds(Arrays.asList(embed)).queue(); 27 | } 28 | 29 | @Override 30 | public void reply(File file, String name) { 31 | if (getSlashCommandEvent().isAcknowledged()) { 32 | getSlashCommandEvent().getHook().editOriginal(file, name).complete(); 33 | } else 34 | getSlashCommandEvent().replyFile(file, name).complete(); 35 | } 36 | 37 | @Override 38 | public void reply(String message, File file, String name) { 39 | if (getSlashCommandEvent().isAcknowledged()) { 40 | getSlashCommandEvent().getHook().editOriginal(message).addFile(file, name).complete(); 41 | } else 42 | getSlashCommandEvent().reply(message).addFile(file, name).complete(); 43 | } 44 | 45 | @Override 46 | public Guild getGuild() { 47 | return getSlashCommandEvent().getGuild(); 48 | } 49 | 50 | @Override 51 | public User getUser() { 52 | return getSlashCommandEvent().getUser(); 53 | } 54 | 55 | @Override 56 | public Member getMember() { 57 | return getSlashCommandEvent().getMember(); 58 | } 59 | 60 | @Override 61 | public void edit(String message) { 62 | getSlashCommandEvent().getHook().editOriginal(message).queue(); 63 | } 64 | 65 | @Override 66 | public void edit(MessageEmbed... embed) { 67 | getSlashCommandEvent().getHook().editOriginalEmbeds(embed).queue(); 68 | } 69 | 70 | @Override 71 | public MessageChannel getChannel() { 72 | return getSlashCommandEvent().getChannel(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/RestaurantManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.reflect.TypeToken; 5 | 6 | import java.io.*; 7 | import java.lang.reflect.Type; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class RestaurantManager { 12 | private static final String filePath = "ratings" + File.separator + "restaurants.json"; 13 | private static final RestaurantManager instance = new RestaurantManager(); 14 | private List restaurants = new ArrayList<>(); 15 | 16 | 17 | private RestaurantManager() { 18 | try { 19 | loadData(); 20 | } catch (FileNotFoundException e) { 21 | throw new RuntimeException(e); 22 | } 23 | } 24 | 25 | public static RestaurantManager getInstance() { 26 | return instance; 27 | } 28 | 29 | public List getRestaurants() { 30 | return restaurants; 31 | } 32 | 33 | public Restaurant getRestaurant(String name) { 34 | return restaurants.stream().filter(r -> r.getName().equals(name)).findFirst().orElse(null); 35 | } 36 | 37 | public boolean addRating(String name, int rating) { 38 | Restaurant restaurant = getRestaurant(name); 39 | if (restaurant == null) 40 | return false; 41 | restaurant.getRating().addRating(rating); 42 | return true; 43 | } 44 | 45 | public boolean removeRating(String name, int rating) { 46 | Restaurant restaurant = getRestaurant(name); 47 | if (restaurant == null) 48 | return false; 49 | restaurant.getRating().removeRating(rating); 50 | return true; 51 | } 52 | 53 | private void loadData() throws FileNotFoundException { 54 | Type typeOfT = new TypeToken>() { 55 | }.getType(); 56 | try { 57 | File file = new File(filePath); 58 | if (file.exists()) { 59 | restaurants = new Gson().fromJson(new FileReader(file), typeOfT); 60 | } 61 | } catch (Exception ignored) { 62 | } 63 | if (restaurants == null) 64 | restaurants = new ArrayList<>(); 65 | } 66 | 67 | public void save() { 68 | try { 69 | new File(filePath).getParentFile().mkdirs(); 70 | FileWriter writer = new FileWriter(filePath); 71 | new Gson().toJson(restaurants, writer); 72 | writer.close(); 73 | } catch (IOException ex) { 74 | ex.printStackTrace(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/WeatherCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.met.Weather4J; 4 | import ml.codeboy.met.data.Forecast; 5 | import ml.codeboy.openweathermap.data.Location; 6 | import ml.codeboy.thebot.commands.image.ImageCommand; 7 | import ml.codeboy.thebot.events.CommandEvent; 8 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 9 | import net.dv8tion.jda.api.interactions.commands.OptionType; 10 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 11 | 12 | import java.awt.image.BufferedImage; 13 | import java.time.Instant; 14 | import java.util.List; 15 | 16 | import static ml.codeboy.thebot.WeatherUtil.generateForecastImage; 17 | 18 | public class WeatherCommand extends ImageCommand { 19 | 20 | public WeatherCommand() { 21 | super("weather", "send forecast", "forecast"); 22 | setHidden(false); 23 | setGuildOnlyCommand(false); 24 | } 25 | 26 | @Override 27 | public SlashCommandData getCommandData() { 28 | return super.getCommandData().addOption(OptionType.STRING, "city", "The city for the forecast"); 29 | } 30 | 31 | @Override 32 | protected void generateImage(CommandEvent event) { 33 | List coordinates = event.getDefaultMensa().getCoordinates(); 34 | String lat = String.valueOf(coordinates.get(0)), lon = String.valueOf(coordinates.get(1)); 35 | 36 | if (event.getArgs().length > 0) { 37 | String city = String.join(" ", event.getArgs()); 38 | Location loc = ShortsCommand.getOpenWeather().getLocation(city); 39 | lat = String.valueOf(loc.getLat()); 40 | lon = String.valueOf(loc.getLon()); 41 | } else if (event.isSlashCommandEvent()) { 42 | OptionMapping option = event.getSlashCommandEvent().getOption("city"); 43 | if (option != null) { 44 | String city = option.getAsString(); 45 | Location loc = ShortsCommand.getOpenWeather().getLocation(city); 46 | lat = String.valueOf(loc.getLat()); 47 | lon = String.valueOf(loc.getLon()); 48 | } 49 | } 50 | 51 | List forecasts = Weather4J.getForecasts(lat, lon); 52 | Instant now = Instant.now(); 53 | while (forecasts.get(1).getTime().isBefore(now)) { 54 | forecasts.remove(0); 55 | } 56 | 57 | BufferedImage image = generateForecastImage(forecasts, 16); 58 | event.reply("Data from The Norwegian Meteorological Institute", image, "png", "weather_forecast"); 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/LogAppender.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot; 2 | 3 | import ch.qos.logback.classic.spi.ILoggingEvent; 4 | import ch.qos.logback.core.AppenderBase; 5 | import net.dv8tion.jda.api.JDA; 6 | import net.dv8tion.jda.api.entities.TextChannel; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collection; 12 | import java.util.List; 13 | 14 | public class LogAppender extends AppenderBase { 15 | private final Logger logger = LoggerFactory.getLogger(getClass()); 16 | private final Collection debugChannels = new ArrayList<>(); 17 | private final List loggingQueue = new ArrayList<>();//contains events from before the bot was started 18 | private boolean initialised = false; 19 | 20 | @Override 21 | protected void append(ILoggingEvent event) { 22 | if (event.getLoggerName().startsWith("org.mongodb.driver")) 23 | return;//do not log messages from mongodb 24 | if (initialised) { 25 | log(event); 26 | } else { 27 | loggingQueue.add(event); 28 | attemptInit(); 29 | } 30 | } 31 | 32 | private synchronized void attemptInit() { 33 | if (initialised) 34 | return; 35 | MensaBot bot = MensaBot.getInstance(); 36 | if (bot == null) 37 | return; 38 | JDA jda = bot.getJda(); 39 | if (jda != null && jda.getStatus() == JDA.Status.CONNECTED) { 40 | for (String channelId : Config.getInstance().debugChannels) { 41 | try { 42 | TextChannel channel = jda.getTextChannelById(channelId); 43 | if (channel != null) 44 | debugChannels.add(channel); 45 | } catch (Exception e) { 46 | logger.error("Unable to load debug channel with id " + channelId); 47 | } 48 | } 49 | //events from before the bot started are most likely uninteresting 50 | // for (ILoggingEvent event:loggingQueue){ 51 | // log(event); 52 | // } 53 | log(loggingQueue.get(loggingQueue.size() - 1));//only send latest message 54 | loggingQueue.clear(); 55 | initialised = true; 56 | } 57 | } 58 | 59 | private void log(ILoggingEvent event) { 60 | for (TextChannel channel : debugChannels) { 61 | channel.sendMessage(format(event)).queue(); 62 | } 63 | } 64 | 65 | private String format(ILoggingEvent event) { 66 | return event.getFormattedMessage(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/JokeCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import com.github.codeboy.jokes4j.Jokes4J; 4 | import com.github.codeboy.jokes4j.api.Category; 5 | import com.github.codeboy.jokes4j.api.Joke; 6 | import com.github.codeboy.jokes4j.api.JokeType; 7 | import com.github.codeboy.jokes4j.api.Language; 8 | import ml.codeboy.thebot.events.CommandEvent; 9 | import net.dv8tion.jda.api.EmbedBuilder; 10 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 11 | import net.dv8tion.jda.api.interactions.commands.OptionType; 12 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 13 | 14 | import java.awt.*; 15 | import java.util.List; 16 | 17 | public class JokeCommand extends Command { 18 | public JokeCommand() { 19 | super("joke", "tells a joke"); 20 | setGuildOnlyCommand(false); 21 | } 22 | 23 | @Override 24 | public SlashCommandData getCommandData() { 25 | return super.getCommandData().addOption(OptionType.STRING, "category", "A specific category for a joke", false, true); 26 | } 27 | 28 | @Override 29 | public void autoComplete(String option, List options) { 30 | if("category".equals(option)) { 31 | for(Category category : Category.values()) { 32 | options.add(category.toString()); 33 | } 34 | } 35 | } 36 | 37 | @Override 38 | public void run(CommandEvent event) { 39 | Joke joke = null; 40 | 41 | OptionMapping categoryMapping = event.isSlashCommandEvent() ? event.getSlashCommandEvent().getOption("category") : null; 42 | Category category = null; 43 | if(categoryMapping != null) { 44 | try { 45 | category = Category.valueOf(categoryMapping.getAsString()); 46 | } catch (IllegalArgumentException e) { 47 | event.setEphermal(true); 48 | event.reply(event.getBuilder().setTitle("Joke - Error") 49 | .setDescription("The given category is invalid. Please try again").setColor(Color.RED)); 50 | return; 51 | } 52 | } 53 | Jokes4J instance = Jokes4J.getInstance(); 54 | joke = category == null ? instance.getJoke() : instance.getJoke(Language.ENGLISH, category); 55 | 56 | EmbedBuilder builder = event.getBuilder(); 57 | if (joke.getType() == JokeType.single) { 58 | builder.setDescription(joke.getJoke()); 59 | } else if (joke.getType() == JokeType.twopart) { 60 | builder.setTitle(joke.getSetup()).setDescription(joke.getDelivery()); 61 | } 62 | event.reply(builder); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/MealImage.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import ml.codeboy.thebot.MensaBot; 4 | import net.dv8tion.jda.api.EmbedBuilder; 5 | import net.dv8tion.jda.api.entities.User; 6 | 7 | import java.awt.*; 8 | import java.util.UUID; 9 | 10 | public class MealImage { 11 | private final String author; 12 | private final String url; 13 | private final UUID id = UUID.randomUUID(); 14 | private boolean accepted = false; 15 | 16 | public MealImage(String author, String url) { 17 | this.author = author; 18 | this.url = url; 19 | } 20 | 21 | public boolean isAccepted() { 22 | return accepted; 23 | } 24 | 25 | public void setAccepted(boolean accepted) { 26 | this.accepted = accepted; 27 | } 28 | 29 | public String getAuthor() { 30 | return author; 31 | } 32 | 33 | public String getUrl() { 34 | return url; 35 | } 36 | 37 | public UUID getId() { 38 | return id; 39 | } 40 | 41 | public void accept() { 42 | setAccepted(true); 43 | FoodRatingManager.getInstance().saveImages(); 44 | UserData data = UserDataManager.getInstance().getData(getAuthor()); 45 | data.setKarma(data.getKarma() + 5); 46 | UserDataManager.getInstance().save(data); 47 | User user = MensaBot.getInstance().getJda().getUserById(getAuthor()); 48 | if (user != null) { 49 | user.openPrivateChannel().complete() 50 | .sendMessageEmbeds( 51 | new EmbedBuilder().setTitle("Your image has been accepted") 52 | .setThumbnail(getUrl()) 53 | .setDescription("Thank you for your contribution. You received 5 karma for this") 54 | .setColor(Color.GREEN) 55 | .build() 56 | ).queue(); 57 | } 58 | } 59 | 60 | public void reject(String message) { 61 | setAccepted(false); 62 | FoodRatingManager.getInstance().removeImage(this); 63 | User user = MensaBot.getInstance().getJda().getUserById(getAuthor()); 64 | if (user != null) { 65 | user.openPrivateChannel().complete() 66 | .sendMessageEmbeds( 67 | new EmbedBuilder().setTitle("Your image has been rejected") 68 | .setThumbnail(getUrl()) 69 | .setDescription(message) 70 | .setColor(Color.RED) 71 | .build() 72 | ).queue(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/quotes/AddQuote.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.quotes; 2 | 3 | import ml.codeboy.thebot.apis.mongoDB.DatabaseQuoteAPI; 4 | import ml.codeboy.thebot.commands.Command; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | import ml.codeboy.thebot.quotes.Person; 7 | import ml.codeboy.thebot.quotes.Quote; 8 | import ml.codeboy.thebot.quotes.QuoteManager; 9 | import net.dv8tion.jda.api.EmbedBuilder; 10 | import net.dv8tion.jda.api.interactions.commands.OptionType; 11 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 12 | 13 | import java.awt.*; 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | 18 | public class AddQuote extends Command { 19 | public AddQuote() { 20 | super("addquote", "adds a quote to the bots database"); 21 | } 22 | 23 | @Override 24 | public SlashCommandData getCommandData() { 25 | return super.getCommandData() 26 | .addOption(OptionType.STRING, "name", "the name of the person the quote is from", true, true) 27 | .addOption(OptionType.STRING, "content", "the content of the quote", true); 28 | } 29 | 30 | @Override 31 | public void autoComplete(String option, List options) { 32 | switch (option) { 33 | case "name": { 34 | for (Person person : QuoteManager.getInstance().getPersons()) { 35 | options.add(person.getName()); 36 | } 37 | break; 38 | } 39 | } 40 | } 41 | 42 | @Override 43 | public void run(CommandEvent event) { 44 | if (event.isSlashCommandEvent()) { 45 | String name = event.getSlashCommandEvent().getOption("name").getAsString(); 46 | String content = event.getSlashCommandEvent().getOption("content").getAsString(); 47 | 48 | addQuote(event, name, content); 49 | } else { 50 | String[] args = event.getArgs(); 51 | if (args.length < 2) 52 | event.replyError("this needs at least two arguments"); 53 | else { 54 | String name = args[0]; 55 | ArrayList a = new ArrayList<>(Arrays.asList(args)); 56 | a.remove(0); 57 | String content = String.join(" ", a); 58 | addQuote(event, name, content); 59 | } 60 | } 61 | } 62 | 63 | private void addQuote(CommandEvent event, String name, String content) { 64 | DatabaseQuoteAPI.saveQuote(new Quote(content,System.currentTimeMillis(),name,event.getMember().getId())); 65 | event.reply(new EmbedBuilder().setTitle("Added quote").setColor(Color.GREEN).build(), 66 | new EmbedBuilder().addField(" ",content+"\n||"+name+"||", false).build()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/quotes/QuoteCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.quotes; 2 | 3 | import ml.codeboy.thebot.commands.Command; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import ml.codeboy.thebot.quotes.Person; 6 | import ml.codeboy.thebot.quotes.Quote; 7 | import ml.codeboy.thebot.quotes.QuoteManager; 8 | import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; 9 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 10 | import net.dv8tion.jda.api.interactions.commands.OptionType; 11 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 12 | 13 | import java.util.List; 14 | 15 | public class QuoteCommand extends Command { 16 | public QuoteCommand() { 17 | super("quote", "sends a quote"); 18 | // setHidden(true); 19 | QuoteManager.getInstance();//this will cause the quotemanager to load all quotes 20 | } 21 | 22 | @Override 23 | public SlashCommandData getCommandData() { 24 | return super.getCommandData().addOption(OptionType.STRING, "author", "the name of the person the quote is from",false,true); 25 | } 26 | 27 | 28 | 29 | @Override 30 | public void autoComplete(String option, List options) { 31 | switch (option) { 32 | case "author": { 33 | for (Person person : QuoteManager.getInstance().getPersons()) { 34 | options.add(person.getName()); 35 | } 36 | break; 37 | } 38 | } 39 | } 40 | 41 | @Override 42 | public void run(CommandEvent event) { 43 | Quote quote; 44 | if (event.isSlashCommandEvent()) { 45 | SlashCommandInteractionEvent e = event.getSlashCommandEvent(); 46 | OptionMapping option = e.getOption("author"); 47 | if (option != null) { 48 | String name = option.getAsString(); 49 | quote = QuoteManager.getInstance().getRandomQuote(name); 50 | if (quote == null) { 51 | event.replyError("Unable to find quotes for " + name); 52 | return; 53 | } 54 | } else { 55 | quote = QuoteManager.getInstance().getRandomQuote(); 56 | } 57 | 58 | } else { 59 | String[] args = event.getArgs(); 60 | if (args.length > 0) { 61 | String name = args[0]; 62 | quote = QuoteManager.getInstance().getRandomQuote(name); 63 | if (quote == null) { 64 | event.replyError("Unable to find quotes for " + name); 65 | return; 66 | } 67 | } else { 68 | quote = QuoteManager.getInstance().getRandomQuote(); 69 | } 70 | } 71 | event.reply(quote.builder()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/quotes/AddQuoteList.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.quotes; 2 | 3 | import ml.codeboy.thebot.apis.mongoDB.DatabaseQuoteAPI; 4 | import ml.codeboy.thebot.commands.Command; 5 | import ml.codeboy.thebot.events.CommandEvent; 6 | import ml.codeboy.thebot.quotes.Person; 7 | import ml.codeboy.thebot.quotes.Quote; 8 | import ml.codeboy.thebot.quotes.QuoteManager; 9 | import net.dv8tion.jda.api.EmbedBuilder; 10 | import net.dv8tion.jda.api.interactions.commands.OptionType; 11 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 12 | 13 | import java.awt.*; 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | 18 | public class AddQuoteList extends Command { 19 | public AddQuoteList() { 20 | super("addquotelist", "adds a list of quotes to the bots database"); 21 | } 22 | 23 | @Override 24 | public SlashCommandData getCommandData() { 25 | return super.getCommandData() 26 | .addOption(OptionType.STRING, "name", "the name of the person the quote is from", true, true) 27 | .addOption(OptionType.STRING, "content", "The quotes, separated by \"`\"", true); 28 | } 29 | 30 | @Override 31 | public void autoComplete(String option, List options) { 32 | switch (option) { 33 | case "name": { 34 | for (Person person : QuoteManager.getInstance().getPersons()) { 35 | options.add(person.getName()); 36 | } 37 | break; 38 | } 39 | } 40 | } 41 | 42 | @Override 43 | public void run(CommandEvent event) { 44 | if (event.isSlashCommandEvent()) { 45 | String name = event.getSlashCommandEvent().getOption("name").getAsString(); 46 | String content = event.getSlashCommandEvent().getOption("content").getAsString(); 47 | 48 | addQuote(event, name, content); 49 | } else { 50 | String[] args = event.getArgs(); 51 | if (args.length < 2) 52 | event.replyError("this needs at least two arguments"); 53 | else { 54 | String name = args[0]; 55 | ArrayList a = new ArrayList<>(Arrays.asList(args)); 56 | a.remove(0); 57 | String content = String.join(" ", a); 58 | addQuote(event, name, content); 59 | } 60 | } 61 | } 62 | 63 | private void addQuote(CommandEvent event, String name, String content) { 64 | EmbedBuilder reply = new EmbedBuilder().setTitle("Added quote").setColor(Color.GREEN); 65 | int i=0; 66 | for(String s : content.split("`")) { 67 | DatabaseQuoteAPI.saveQuote(new Quote(s,System.currentTimeMillis(),name,event.getMember().getId())); 68 | i++; 69 | } 70 | reply.addField("Counter","Added "+i+" quotes",false); 71 | event.reply(reply.build()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/UserData.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import net.dv8tion.jda.api.JDA; 4 | import net.dv8tion.jda.api.entities.User; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | public class UserData { 11 | private final String userId; 12 | private int bedTime = -1; 13 | private int karma = 0; 14 | private Map ratings = new HashMap<>(); 15 | private Map restaurantRatings = new HashMap<>(); 16 | private ArrayList comments = new ArrayList<>(); 17 | 18 | public UserData(String userId) { 19 | this.userId = userId; 20 | } 21 | 22 | public int getBedTime() { 23 | return bedTime; 24 | } 25 | 26 | public void setBedTime(int bedTime) { 27 | this.bedTime = bedTime; 28 | } 29 | 30 | public String getId() { 31 | return userId; 32 | } 33 | 34 | public User getUser(JDA jda) { 35 | return jda.retrieveUserById(getId()).complete(); 36 | } 37 | 38 | public String getTag(JDA jda) { 39 | try { 40 | return getUser(jda).getAsTag(); 41 | } catch (Exception ignored) { 42 | } 43 | return "unknown user"; 44 | } 45 | 46 | public int getKarma() { 47 | return karma; 48 | } 49 | 50 | public void setKarma(int karma) { 51 | this.karma = karma; 52 | } 53 | 54 | public void addRating(String meal, int rating) { 55 | if (ratings == null) 56 | ratings = new HashMap<>(); 57 | if (ratings.containsKey(meal)) { 58 | FoodRatingManager.getInstance().removeRating(meal, ratings.get(meal)); 59 | } else karma++;//add one karma for rating 60 | FoodRatingManager.getInstance().addRating(meal, rating); 61 | ratings.put(meal, rating); 62 | UserDataManager.getInstance().save(this); 63 | } 64 | 65 | public boolean addRestaurantRating(String restaurant, int rating) { 66 | if (restaurantRatings == null) 67 | restaurantRatings = new HashMap<>(); 68 | Restaurant r = RestaurantManager.getInstance().getRestaurant(restaurant); 69 | if (restaurant == null) 70 | return false; 71 | if (restaurantRatings.containsKey(restaurant)) { 72 | r.getRating().removeRating(restaurantRatings.get(restaurant)); 73 | } else karma++;//add one karma for rating 74 | r.getRating().addRating(rating); 75 | restaurantRatings.put(restaurant, rating); 76 | RestaurantManager.getInstance().save(); 77 | UserDataManager.getInstance().save(this); 78 | return true; 79 | } 80 | 81 | public void clearRatings() { 82 | if (ratings != null && !ratings.isEmpty()) { 83 | ratings = new HashMap<>(); 84 | UserDataManager.getInstance().save(this); 85 | } 86 | } 87 | 88 | public ArrayList getComments() { 89 | if (comments == null) 90 | comments = new ArrayList<>(); 91 | return comments; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/apis/RWTHMensa.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.apis; 2 | 3 | import com.github.codeboy.Util; 4 | import com.github.codeboy.api.Meal; 5 | import com.github.codeboy.api.Mensa; 6 | import com.github.codeboy.api.MensaImpl; 7 | 8 | import java.util.Date; 9 | import java.util.List; 10 | import java.util.Timer; 11 | import java.util.TimerTask; 12 | 13 | public class RWTHMensa implements Mensa { 14 | private Mensa mensa; 15 | 16 | public RWTHMensa(Mensa mensa) { 17 | this.mensa = mensa; 18 | new Timer().schedule(new TimerTask() { 19 | @Override 20 | public void run() { 21 | setMensa(new MensaImpl(mensa.getId(), mensa.getName(), mensa.getCity(), mensa.getAddress(), mensa.getCoordinates())); 22 | } 23 | }, 1000 * 60 * 60, 1000 * 60 * 60);//clears the mensas cache once per hour 24 | } 25 | 26 | private void setMensa(Mensa mensa) { 27 | this.mensa = mensa; 28 | } 29 | 30 | @Override 31 | public List getMeals() { 32 | return getMeals(new Date()); 33 | } 34 | 35 | @Override 36 | public List getMeals(Date date) { 37 | return getMeals(Util.dateToString(date)); 38 | } 39 | 40 | @Override 41 | public List getMeals(String s) { 42 | List meals = mensa.getMeals(s); 43 | for (int i = 0; i < meals.size(); i++) { 44 | Meal meal = meals.get(i); 45 | if (meal.getCategory().equals("Hauptbeilagen") || meal.getCategory().equals("Nebenbeilage")) { 46 | String[] submeals = meal.getName().split(" oder "); 47 | if (submeals.length > 1 && !"".equals(submeals[1])) { 48 | meals.remove(i); 49 | i--; 50 | for (String name : submeals) { 51 | Meal submeal = new Meal(name, meal.getCategory(), meal.getNotes(), meal.getPrices()); 52 | meals.add(submeal); 53 | } 54 | } 55 | } 56 | } 57 | return meals; 58 | } 59 | 60 | @Override 61 | public boolean isOpen() { 62 | return isOpen(new Date()); 63 | } 64 | 65 | @Override 66 | public boolean isOpen(Date date) { 67 | return isOpen(Util.dateToString(date)); 68 | } 69 | 70 | @Override 71 | public boolean isOpen(String s) { 72 | return mensa.isOpen(s); 73 | } 74 | 75 | @Override 76 | public int getId() { 77 | return mensa.getId(); 78 | } 79 | 80 | @Override 81 | public String getName() { 82 | return mensa.getName(); 83 | } 84 | 85 | @Override 86 | public String getCity() { 87 | return mensa.getCity(); 88 | } 89 | 90 | @Override 91 | public String getAddress() { 92 | return mensa.getAddress(); 93 | } 94 | 95 | @Override 96 | public List getCoordinates() { 97 | return mensa.getCoordinates(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/secret/LoadKarma.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.secret; 2 | 3 | import ml.codeboy.thebot.Config; 4 | import ml.codeboy.thebot.data.UserData; 5 | import ml.codeboy.thebot.data.UserDataManager; 6 | import ml.codeboy.thebot.events.CommandEvent; 7 | import net.dv8tion.jda.api.entities.*; 8 | import net.dv8tion.jda.api.entities.emoji.Emoji; 9 | 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | 14 | public class LoadKarma extends SecretCommand { 15 | public LoadKarma() { 16 | super("loadKarma", "", "lk"); 17 | } 18 | 19 | @Override 20 | public void run(CommandEvent event) { 21 | int messagesAmount = 1000; 22 | try { 23 | messagesAmount = Integer.parseInt(event.getArgs()[1]); 24 | } catch (Exception ignored) { 25 | } 26 | HashMap karmaMap = new HashMap<>(); 27 | Guild guild = event.getJdaEvent().getJDA().getGuildById(event.getArgs()[0]); 28 | event.reply("loading karma for " + guild.getName()); 29 | for (GuildChannel channel : guild.getChannels()) { 30 | if (channel instanceof TextChannel) { 31 | 32 | try { 33 | event.reply("loading karma for " + channel.getAsMention()); 34 | TextChannel tc = (TextChannel) channel; 35 | List messages = tc.getIterableHistory().takeAsync(messagesAmount) 36 | .thenApply(ArrayList::new).get(); 37 | for (Message message : messages) { 38 | User user = message.getAuthor(); 39 | int karma = karmaMap.getOrDefault(user, 0); 40 | for (MessageReaction r : message.getReactions()) { 41 | if (r.getEmoji().getType() == Emoji.Type.CUSTOM) { 42 | int multiplier = 0; 43 | if (Config.getInstance().isDownvote(r.getEmoji().asCustom().getId())) 44 | multiplier = 1; 45 | if (Config.getInstance().isUpvote(r.getEmoji().asCustom().getId())) 46 | multiplier = -1; 47 | karma += r.getCount() * multiplier; 48 | } 49 | } 50 | karmaMap.put(user, karma); 51 | } 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | } 55 | } 56 | } 57 | event.reply("finished loading karma for " + karmaMap.keySet().size() + " users"); 58 | for (User user : karmaMap.keySet()) { 59 | UserData data = UserDataManager.getInstance().getData(user); 60 | int karma = data.getKarma(); 61 | data.setKarma(karmaMap.get(user)); 62 | if (karma != data.getKarma())//only save if changed 63 | UserDataManager.getInstance().save(data); 64 | } 65 | event.reply("finished saving karma"); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/tracker/BedTimeTracker.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.tracker; 2 | 3 | import ml.codeboy.thebot.Bot; 4 | import ml.codeboy.thebot.data.UserData; 5 | import ml.codeboy.thebot.data.UserDataManager; 6 | import ml.codeboy.thebot.util.Util; 7 | import net.dv8tion.jda.api.EmbedBuilder; 8 | import net.dv8tion.jda.api.OnlineStatus; 9 | import net.dv8tion.jda.api.entities.Member; 10 | import net.dv8tion.jda.api.entities.User; 11 | 12 | import java.awt.*; 13 | import java.text.SimpleDateFormat; 14 | import java.time.Duration; 15 | import java.time.ZoneId; 16 | import java.time.ZonedDateTime; 17 | import java.util.Date; 18 | import java.util.Timer; 19 | import java.util.TimerTask; 20 | 21 | public class BedTimeTracker { 22 | private static final SimpleDateFormat format = new SimpleDateFormat("hh:mm"); 23 | private static final int millisPerDay = 1000 * 60 * 60 * 24; 24 | 25 | public BedTimeTracker(Bot bot) { 26 | scheduleReminders(bot); 27 | } 28 | 29 | private void scheduleReminders(Bot bot) { 30 | Timer timer = new Timer(); 31 | ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Berlin")); 32 | for (UserData data : UserDataManager.getInstance().getAllUserData()) { 33 | if(data.getBedTime() < 0) 34 | continue; 35 | User user = bot.getJda().retrieveUserById(data.getId()).complete(); 36 | if (user == null) 37 | continue; 38 | int seconds = data.getBedTime(); 39 | int hours = seconds / 3600; 40 | seconds -= hours * 3600; 41 | int minutes = seconds / 60; 42 | seconds -= minutes * 60; 43 | ZonedDateTime nextRun = now.withHour(hours).withMinute(minutes).withSecond(seconds); 44 | if (now.compareTo(nextRun) > 0) 45 | nextRun = nextRun.plusDays(1); 46 | 47 | Duration duration = Duration.between(now, nextRun); 48 | long delay = duration.getSeconds() * 1000; 49 | delay += 500;//make sure messages don't get sent too early 50 | timer.schedule(new TimerTask() { 51 | @Override 52 | public void run() { 53 | Member member = Util.getAsMember(user); 54 | if (member == null) 55 | return; 56 | if (member.getOnlineStatus() != OnlineStatus.OFFLINE 57 | && member.getOnlineStatus() != OnlineStatus.UNKNOWN) { 58 | remindOfBedtime(user); 59 | } 60 | } 61 | }, delay); 62 | } 63 | timer.schedule(new TimerTask() { 64 | @Override 65 | public void run() { 66 | scheduleReminders(bot); 67 | } 68 | }, millisPerDay); 69 | } 70 | 71 | private void remindOfBedtime(User user) { 72 | EmbedBuilder builder = new EmbedBuilder(); 73 | builder.setTitle("Time to go to bed").setColor(Color.RED) 74 | .setDescription("it is already " + format.format(new Date())); 75 | user.openPrivateChannel().flatMap(c -> c.sendMessageEmbeds(builder.build())).queue(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/ShortsCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.openweathermap.OpenWeatherApi; 4 | import ml.codeboy.openweathermap.data.ApiResponse; 5 | import ml.codeboy.openweathermap.data.HourlyForecast; 6 | import ml.codeboy.openweathermap.data.Location; 7 | import ml.codeboy.thebot.Config; 8 | import ml.codeboy.thebot.events.CommandEvent; 9 | import net.dv8tion.jda.api.EmbedBuilder; 10 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 11 | import net.dv8tion.jda.api.interactions.commands.OptionType; 12 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 13 | 14 | import java.awt.*; 15 | import java.io.IOException; 16 | import java.util.List; 17 | 18 | public class ShortsCommand extends Command { 19 | private static OpenWeatherApi openWeather; 20 | 21 | public ShortsCommand() { 22 | super("ShouldIWearShortsToday", "Lets you know if you should wear shorts today", "shorts"); 23 | openWeather = new OpenWeatherApi(Config.getInstance().openWeatherApiKey); 24 | setGuildOnlyCommand(false); 25 | } 26 | 27 | public static OpenWeatherApi getOpenWeather() { 28 | return openWeather; 29 | } 30 | 31 | @Override 32 | public SlashCommandData getCommandData() { 33 | return super.getCommandData().addOption(OptionType.STRING, "city", "The city you are in"); 34 | } 35 | 36 | @Override 37 | public void run(CommandEvent event) { 38 | ApiResponse response = null; 39 | List coordinates = event.getDefaultMensa().getCoordinates(); 40 | String lat = String.valueOf(coordinates.get(0)), lon = String.valueOf(coordinates.get(1)); 41 | 42 | if (event.getArgs().length > 0) { 43 | String city = String.join(" ", event.getArgs()); 44 | Location loc = ShortsCommand.getOpenWeather().getLocation(city); 45 | lat = String.valueOf(loc.getLat()); 46 | lon = String.valueOf(loc.getLon()); 47 | } else if (event.isSlashCommandEvent()) { 48 | OptionMapping option = event.getSlashCommandEvent().getOption("city"); 49 | if (option != null) { 50 | String city = option.getAsString(); 51 | Location loc = ShortsCommand.getOpenWeather().getLocation(city); 52 | lat = String.valueOf(loc.getLat()); 53 | lon = String.valueOf(loc.getLon()); 54 | } 55 | } 56 | try { 57 | response = openWeather.getForecast(lat, lon, "metric", "de"); 58 | } catch (IOException e) { 59 | throw new RuntimeException(e); 60 | } 61 | int sunrise = response.getCity().getSunrise(); 62 | int sunset = response.getCity().getSunset(); 63 | int lowestTempForShorts = 15; 64 | float lowestTempToday = 100; 65 | boolean shortsWeather = true; 66 | for (HourlyForecast hf : response.getList()) { 67 | if (hf.getDt() > sunrise && hf.getDt() < sunset) { 68 | if (hf.getMain().getTemp_min() < lowestTempToday) { 69 | lowestTempToday = hf.getMain().getFeels_like(); 70 | } 71 | } 72 | } 73 | shortsWeather = lowestTempToday > lowestTempForShorts; 74 | EmbedBuilder builder = event.getBuilder(); 75 | builder.setColor(shortsWeather ? Color.GREEN : Color.RED); 76 | builder.setTitle(shortsWeather ? "It is shorts weather today" : "It isn't shorts weather today"); 77 | event.reply(builder); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/AudioCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import ml.codeboy.thebot.commands.Command; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.entities.GuildVoiceState; 6 | import net.dv8tion.jda.api.entities.Member; 7 | import net.dv8tion.jda.api.managers.AudioManager; 8 | 9 | import java.io.File; 10 | import java.net.MalformedURLException; 11 | import java.net.URL; 12 | 13 | public abstract class AudioCommand extends Command { 14 | public AudioCommand(String name) { 15 | this(name, ""); 16 | } 17 | 18 | public AudioCommand(String name, String usage, String... aliases) { 19 | super(name, usage, aliases); 20 | setHidden(true); 21 | } 22 | 23 | @Override 24 | public void run(CommandEvent event) { 25 | 26 | } 27 | 28 | @Override 29 | public void execute(CommandEvent event) { 30 | event.setEphermal(true); 31 | super.execute(event); 32 | // event.getManager().scheduler.setLatestEvent(event);//song info will now only be send if current is run 33 | } 34 | 35 | protected boolean ensureConnected(CommandEvent event) { 36 | final Member self = event.getGuild().getSelfMember(); 37 | final GuildVoiceState selfVoiceState = self.getVoiceState(); 38 | 39 | 40 | final Member member = event.getMember(); 41 | final GuildVoiceState memberVoiceState = member.getVoiceState(); 42 | 43 | if (memberVoiceState.getChannel() == null) { 44 | event.reply("You need to be in a voice channel for this command to work"); 45 | return false; 46 | } 47 | 48 | AudioManager audioManager = event.getGuild().getAudioManager(); 49 | 50 | if (selfVoiceState.getChannel() == null) { 51 | audioManager.openAudioConnection(memberVoiceState.getChannel()); 52 | return true; 53 | } 54 | 55 | if (!memberVoiceState.getChannel().equals(selfVoiceState.getChannel())) { 56 | event.reply("You need to be in the same voice channel as me for this to work"); 57 | return false; 58 | } 59 | //already connected 60 | return true; 61 | } 62 | 63 | protected void queue(CommandEvent event, String link) { 64 | queue(event, link, false); 65 | } 66 | 67 | protected void queue(CommandEvent event, String link, boolean playNext) { 68 | link = toYtUrl(link); 69 | 70 | PlayerManager.getInstance().load(event, link, false, playNext); 71 | } 72 | 73 | protected void play(CommandEvent event, String link) { 74 | play(event, link, false); 75 | } 76 | 77 | protected void play(CommandEvent event, String link, boolean shuffle) { 78 | link = toYtUrl(link); 79 | 80 | PlayerManager.getInstance().load(event, link, true, true, false, shuffle); 81 | } 82 | 83 | private String toYtUrl(String link) { 84 | if (!isUrl(link)) { 85 | File file = new File("music" + File.separator + link + ".mp3"); 86 | if (file.exists())//music available offline 87 | { 88 | return "file://" + file.getPath(); 89 | } 90 | link = "ytsearch:" + link; 91 | } 92 | return link; 93 | } 94 | 95 | private boolean isUrl(String url) { 96 | try { 97 | new URL(url); 98 | return true; 99 | } catch (MalformedURLException e) { 100 | return false; 101 | } 102 | } 103 | 104 | protected void shuffle(CommandEvent event) { 105 | event.getManager().scheduler.shuffle(); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/quotes/QuoteManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.quotes; 2 | 3 | import ml.codeboy.thebot.apis.mongoDB.DatabaseQuoteAPI; 4 | import org.bson.Document; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collection; 10 | import java.util.HashMap; 11 | import java.util.Random; 12 | 13 | public class QuoteManager { 14 | private static final QuoteManager instance = new QuoteManager(); 15 | private final HashMap persons = new HashMap<>(); 16 | private final ArrayList quotes = new ArrayList<>(); 17 | private final Random random = new Random(); 18 | private final Logger logger 19 | = LoggerFactory.getLogger(getClass()); 20 | 21 | private QuoteManager() { 22 | loadPersons(); 23 | } 24 | 25 | public static QuoteManager getInstance() { 26 | return instance; 27 | } 28 | 29 | private void loadPersons() { 30 | for (String p : DatabaseQuoteAPI.getPersons()) { 31 | loadPerson(p); 32 | } 33 | logger.info("loaded " + persons.size() + " persons with a total of " + quotes.size() + " quotes"); 34 | } 35 | 36 | public void registerPerson(Person person) { 37 | persons.put(person.getName(), person); 38 | for (Quote quote : person.getQuotes()) { 39 | quote.setPerson(person.getName()); 40 | } 41 | quotes.addAll(person.getQuotes()); 42 | logger.info("registered " + person.getName() + " with " + person.getQuotes().size() + " quotes"); 43 | } 44 | 45 | private void loadPerson(String p) { 46 | Person person = new Person(p); 47 | Quote q = null; 48 | ArrayList list = new ArrayList<>(); 49 | for(Document d : DatabaseQuoteAPI.getQuotes(p)) { 50 | q = new Quote( 51 | d.getString("content"), 52 | d.getLong("time"), 53 | d.getString("name"), 54 | d.getString("authorId")); 55 | list.add(q); 56 | } 57 | person.setQuotes(list); 58 | if (person != null) 59 | registerPerson(person); 60 | } 61 | 62 | public CollectiongetPersons(){ 63 | return persons.values(); 64 | } 65 | 66 | public Quote getRandomQuote() { 67 | return getRandomQuote(quotes); 68 | } 69 | 70 | public Quote getRandomQuote(String person) { 71 | Person p = persons.get(person); 72 | if(p==null){ 73 | p = new Person(); 74 | p.setName(person); 75 | } 76 | if (p.getQuotes().isEmpty()) 77 | return null; 78 | return getRandomQuote(p.getQuotes()); 79 | } 80 | 81 | public Quote getRandomQuote(ArrayList quotes) { 82 | return quotes.get(random.nextInt(quotes.size())); 83 | } 84 | 85 | public String getRandomQuoteContent() { 86 | return getRandomQuote().getContent(); 87 | } 88 | 89 | public void addQuote(Quote quote) { 90 | try { 91 | persons.get(quote.getPerson()).getQuotes().add(quote); 92 | }catch (NullPointerException e) 93 | { 94 | persons.put(quote.getPerson(),new Person(quote.getPerson())); 95 | persons.get(quote.getPerson()).getQuotes().add(quote); 96 | } 97 | quotes.add(quote); 98 | } 99 | 100 | /** 101 | * This method returns all quotes from the given person 102 | * @param person 103 | * @return A list of all the quotes 104 | */ 105 | public ArrayListgetQuotes(String person) 106 | { 107 | return persons.get(person).getQuotes(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/WeatherUtil.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot; 2 | 3 | import ml.codeboy.met.data.Forecast; 4 | 5 | import javax.imageio.ImageIO; 6 | import java.awt.*; 7 | import java.awt.image.BufferedImage; 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.time.ZoneId; 11 | import java.time.format.DateTimeFormatter; 12 | import java.util.List; 13 | 14 | import static ml.codeboy.thebot.commands.image.ImageCommand.drawString; 15 | 16 | public class WeatherUtil { 17 | 18 | private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:00") 19 | .withZone(ZoneId.systemDefault()); 20 | 21 | private static final Color transparentYellow = new Color(255, 255, 0, 50); 22 | 23 | public static BufferedImage generateForecastImage(List forecasts, int values) { 24 | final int size = 200, space = size / 5; 25 | BufferedImage image = new BufferedImage((space + size) * values + space, 6 * size, BufferedImage.TYPE_INT_ARGB); 26 | Graphics2D g = image.createGraphics(); 27 | 28 | g.setColor(new Color(54, 57, 63)); 29 | g.fillRect(0, 0, image.getWidth(), image.getHeight()); 30 | 31 | double min = forecasts.get(0).getAirTemperature(), max = min; 32 | for (int i = 1; i < values; i++) { 33 | double temp = forecasts.get(i).getAirTemperature(); 34 | if (temp < min) 35 | min = temp; 36 | if (temp > max) 37 | max = temp; 38 | } 39 | 40 | Forecast last = null; 41 | for (int i = 0; i < values; i++) { 42 | Forecast forecast = forecasts.get(i); 43 | 44 | double lastTemp = forecast.getAirTemperature(); 45 | if (last != null) { 46 | lastTemp = last.getAirTemperature(); 47 | } 48 | last = forecast; 49 | 50 | int startY = (int) (size * 3.3 + space - size * 2.5 * (lastTemp - min) / (max - min)); 51 | int endY = (int) (size * 3.3 + space - size * 2.5 * (forecast.getAirTemperature() - min) / (max - min)); 52 | 53 | g.setColor(Color.ORANGE); 54 | 55 | int startX = (i - 1) * (size + space) + space, endX = i * (size + space) + space; 56 | g.drawLine(startX, startY, endX, endY); 57 | 58 | g.setColor(transparentYellow); 59 | 60 | g.fillPolygon(new int[]{startX, endX, endX, startX}, new int[]{startY, endY, image.getHeight(), image.getHeight()}, 4); 61 | 62 | if (i == values - 1) { 63 | g.setColor(Color.ORANGE); 64 | startX += (size + space); 65 | endX += (size + space); 66 | 67 | g.drawLine(startX, endY, endX, endY); 68 | 69 | g.setColor(transparentYellow); 70 | 71 | g.fillPolygon(new int[]{startX, endX, endX, startX}, new int[]{endY, endY, image.getHeight(), image.getHeight()}, 4); 72 | } 73 | 74 | g.setColor(Color.BLACK); 75 | int x = i * (size + space) - space / 2; 76 | if (i != 0) 77 | g.drawLine(x + space, 0, x + space, image.getHeight()); 78 | 79 | drawString(g, formatter.format(forecast.getTime()), new Rectangle((size + space) * i + space, 4 * size, size, size), Color.WHITE); 80 | drawString(g, forecast.getAirTemperature() + "°", new Rectangle((size + space) * i + space, 3 * size, size, size), Color.WHITE); 81 | try { 82 | Image symbol = ImageIO.read(new File("images/weather/png/" + forecast.getSymbol() + ".png")); 83 | 84 | g.drawImage(symbol, (size + space) * i + space, space, size, size, null); 85 | } catch (IOException e) { 86 | throw new RuntimeException(e); 87 | } 88 | } 89 | drawString(g, "Data from The Norwegian Meteorological Institute", new Rectangle(image.getWidth() - 4 * size, image.getHeight() - 4 * space, 4 * size - space, 3 * space), Color.WHITE); 90 | g.dispose(); 91 | return image; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/DönerrateCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.MensaUtil; 4 | import ml.codeboy.thebot.data.Restaurant; 5 | import ml.codeboy.thebot.data.RestaurantManager; 6 | import ml.codeboy.thebot.data.UserDataManager; 7 | import ml.codeboy.thebot.events.CommandEvent; 8 | import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; 9 | import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; 10 | import net.dv8tion.jda.api.interactions.commands.OptionType; 11 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | public class DönerrateCommand extends Command { 17 | 18 | private final int maxDaysAgo = 2; 19 | 20 | public DönerrateCommand() { 21 | super("dönerrate", "Rate döner places"); 22 | } 23 | 24 | @Override 25 | public SlashCommandData getCommandData() { 26 | return super.getCommandData() 27 | .addOption(OptionType.STRING, "restaurant", "The restaurant to rate", true, true) 28 | .addOption(OptionType.STRING, "rating", "The rating to give - a number between 1 and 5", true, true); 29 | } 30 | 31 | @Override 32 | public void autoComplete(CommandAutoCompleteInteractionEvent event) { 33 | List options = new ArrayList<>(); 34 | String selected = event.getFocusedOption().getName(); 35 | 36 | 37 | switch (selected) { 38 | case "restaurant": { 39 | for (Restaurant r : RestaurantManager.getInstance().getRestaurants()) 40 | options.add(r.getName()); 41 | break; 42 | } 43 | case "rating": { 44 | options.add("1"); 45 | options.add("2"); 46 | options.add("3"); 47 | options.add("4"); 48 | options.add("5"); 49 | break; 50 | } 51 | } 52 | 53 | List choices = new ArrayList<>(); 54 | String value = event.getFocusedOption().getValue().toLowerCase(); 55 | for (String option : options) { 56 | if (choices.size() >= 25)//choices limited to 25 57 | break; 58 | if (option.toLowerCase().contains(value)) { 59 | net.dv8tion.jda.api.interactions.commands.Command.Choice choice = new net.dv8tion.jda.api.interactions.commands.Command.Choice(option, option); 60 | if (!choices.contains(choice)) 61 | choices.add(choice); 62 | } 63 | } 64 | event.replyChoices(choices).queue(); 65 | } 66 | 67 | @Override 68 | public void run(CommandEvent event) { 69 | if (event.isMessageEvent()) 70 | event.replyError("Please use the slashcommand"); 71 | else { 72 | SlashCommandInteractionEvent scie = event.getSlashCommandEvent(); 73 | String restaurant = scie.getOption("restaurant").getAsString(); 74 | int rating = scie.getOption("rating").getAsInt(); 75 | if (rating <= 5 && rating >= 1) { 76 | boolean success = UserDataManager.getInstance().getData(event.getUser()).addRestaurantRating(restaurant, rating); 77 | Restaurant r = RestaurantManager.getInstance().getRestaurant(restaurant); 78 | if (!success) { 79 | event.replyError("Failed to rate " + restaurant); 80 | return; 81 | } 82 | event.reply("Rating added: " + restaurant + "\n" 83 | + MensaUtil.getRatingString(rating) + " added \n" 84 | + MensaUtil.getRatingString(r.getRating().getAverage()) 85 | + " (" + r.getRating().getRatings() + ") total"); 86 | 87 | } else { 88 | event.reply("Invalid number. Has to be between 1 and 5"); 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/UserDataManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import com.google.gson.Gson; 4 | import net.dv8tion.jda.api.entities.User; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.*; 9 | import java.util.*; 10 | 11 | public class UserDataManager { 12 | private final Logger logger = LoggerFactory.getLogger(getClass()); 13 | private static final String userDataFolder = "users"; 14 | 15 | private static final UserDataManager instance = new UserDataManager(); 16 | private final HashMap userData = new HashMap<>(); 17 | 18 | private final long karmaTopUpdate = 600000; 19 | private long lastUpdatedKarmaTop = 0; 20 | 21 | public static UserDataManager getInstance() { 22 | return instance; 23 | } 24 | 25 | public UserData getData(User user) { 26 | return getData(user.getId()); 27 | } 28 | 29 | private final Thread initThread; 30 | 31 | 32 | public UserData loadData(User user) throws FileNotFoundException { 33 | return loadData(user.getId()); 34 | } 35 | 36 | 37 | private UserData loadData(String id) throws FileNotFoundException { 38 | UserData data = new Gson().fromJson(new FileReader(userDataFolder + File.separator + id), UserData.class); 39 | return data; 40 | } 41 | 42 | private UserDataManager() { 43 | initThread = new Thread(this::loadUserData); 44 | initThread.start(); 45 | } 46 | 47 | public void save(UserData data) { 48 | try { 49 | new File(userDataFolder).mkdirs(); 50 | FileWriter writer = new FileWriter(userDataFolder + File.separator + data.getId()); 51 | new Gson().toJson(data, writer); 52 | writer.close(); 53 | } catch (IOException ex) { 54 | ex.printStackTrace(); 55 | } 56 | } 57 | 58 | private List karmaSorted; 59 | 60 | public UserData getData(String userId) { 61 | waitTilInit(); 62 | UserData data = userData.get(userId); 63 | if (data != null) { 64 | return data; 65 | } 66 | try { 67 | return loadData(userId); 68 | } catch (FileNotFoundException ignored) { 69 | } 70 | data = new UserData(userId); 71 | userData.put(userId, data); 72 | return data; 73 | } 74 | 75 | public Collection getAllUserData() { 76 | waitTilInit(); 77 | return userData.values(); 78 | } 79 | 80 | private void waitTilInit() { 81 | if (initThread != null) { 82 | try { 83 | initThread.join(); 84 | } catch (InterruptedException e) { 85 | throw new RuntimeException(e); 86 | } 87 | } 88 | } 89 | 90 | private void loadUserData() { 91 | File folder = new File(userDataFolder); 92 | if (folder.exists()) { 93 | for (File file : folder.listFiles()) { 94 | try { 95 | userData.put(file.getName(), loadData(file.getName())); 96 | } catch (FileNotFoundException e) { 97 | e.printStackTrace(); 98 | } 99 | } 100 | } 101 | logger.info("finished loading user data for users"); 102 | } 103 | 104 | 105 | public List getKarmaSorted() { 106 | if (System.currentTimeMillis() - karmaTopUpdate > lastUpdatedKarmaTop) { 107 | updateKarmaTop(); 108 | } 109 | karmaSorted.sort(Comparator.comparingInt(UserData::getKarma).reversed()); 110 | return karmaSorted; 111 | } 112 | 113 | private void updateKarmaTop() { 114 | karmaSorted = new ArrayList<>(getAllUserData()); 115 | karmaSorted.removeIf(d->d.getKarma()==0); 116 | karmaSorted.sort(Comparator.comparingInt(UserData::getKarma).reversed()); 117 | // karmaSorted = karmaSorted.subList(0, 20); 118 | lastUpdatedKarmaTop = System.currentTimeMillis(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/ExecuteCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import com.github.codeboy.piston4j.api.ExecutionOutput; 4 | import com.github.codeboy.piston4j.api.ExecutionResult; 5 | import com.github.codeboy.piston4j.api.Piston; 6 | import com.github.codeboy.piston4j.api.Runtime; 7 | import ml.codeboy.thebot.Config; 8 | import ml.codeboy.thebot.events.CommandEvent; 9 | import net.dv8tion.jda.api.EmbedBuilder; 10 | import net.dv8tion.jda.api.entities.MessageEmbed; 11 | import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; 12 | import net.dv8tion.jda.api.interactions.commands.OptionType; 13 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 14 | 15 | import java.util.List; 16 | 17 | public class ExecuteCommand extends Command { 18 | public ExecuteCommand() { 19 | super("run", "runs code in the specified language"); 20 | setGuildOnlyCommand(false); 21 | } 22 | 23 | @Override 24 | public SlashCommandData getCommandData() { 25 | return super.getCommandData().addOption(OptionType.STRING, "language", "see available languages using the languages command", true, true) 26 | .addOption(OptionType.STRING, "code", "the code to run", true); 27 | } 28 | 29 | 30 | @Override 31 | public void autoComplete(String option, List options) { 32 | switch (option) { 33 | case "language": { 34 | for (Runtime runtime : Piston.getDefaultApi().getRuntimes()) { 35 | options.add(runtime.getLanguage()); 36 | } 37 | break; 38 | } 39 | } 40 | } 41 | 42 | @Override 43 | public void run(CommandEvent event) { 44 | if (event.isMessageEvent()) { 45 | String language = event.getArgs()[0]; 46 | String content = event.getMessageReceivedEvent().getMessage().getContentRaw(); 47 | content = content.replaceFirst(Config.getInstance().prefix, ""); 48 | content = content.split(" ", 2)[1]; 49 | String code = content.substring(language.length() + 1); 50 | run(event, language, code); 51 | } else { 52 | SlashCommandInteractionEvent e = event.getSlashCommandEvent(); 53 | run(event, e.getOption("language").getAsString(), e.getOption("code").getAsString()); 54 | } 55 | } 56 | 57 | private void run(CommandEvent event, String language, String code) { 58 | //Initialise runtime 59 | Runtime r = Piston.getDefaultApi().getRuntimeUnsafe(language); 60 | if (r == null) { 61 | event.replyError("Language not found"); 62 | } else { 63 | //ExecutionResults 64 | ExecutionResult result = r.execute(code); 65 | ExecutionOutput output = result.getOutput(); 66 | ExecutionOutput error = result.getCompileOutput(); 67 | //Message builder 68 | EmbedBuilder input = new EmbedBuilder(); 69 | EmbedBuilder out = new EmbedBuilder(); 70 | EmbedBuilder err = new EmbedBuilder(); 71 | //Messages 72 | MessageEmbed[] ret; 73 | //Strings 74 | String errValue; 75 | String codeValue; 76 | //input builder 77 | input.setTitle("Execution output").setDescription("Language: " + result.getLanguage()); 78 | codeValue = "```" + language + "\n" + code + "\n```"; 79 | if (codeValue.length() > 1024) 80 | codeValue = "Code too long to fit in this message :("; 81 | input.addField("code", codeValue, false); 82 | //out builder 83 | out.addField("output", output.getOutput(), false); 84 | //err builder 85 | err.setTitle("Error output"); 86 | if (error != null && error.getCode() != 0) { 87 | err.addField("Error:", "```bash\n" + error.getStderr() + "\n```", false); 88 | ret = new MessageEmbed[]{input.build(), out.build(), err.build()}; 89 | } else { 90 | ret = new MessageEmbed[]{input.build(), out.build()}; 91 | } 92 | event.reply(ret); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ml.codeboy 8 | the-bot 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | jitpack.io 19 | https://jitpack.io 20 | 21 | 22 | dv8tion 23 | m2-dv8tion 24 | https://m2.dv8tion.net/releases 25 | 26 | 27 | 28 | 29 | 30 | net.dv8tion 31 | JDA 32 | 5.0.0-alpha.17 33 | 34 | 35 | club.minnced 36 | opus-java 37 | 38 | 39 | 40 | 41 | com.github.the-codeboy 42 | Mensa4J 43 | 584a9914c2 44 | 45 | 46 | ch.qos.logback 47 | logback-classic 48 | 1.2.11 49 | 50 | 51 | com.google.code.gson 52 | gson 53 | 2.9.0 54 | 55 | 56 | com.github.the-codeboy 57 | Piston4J 58 | 0.0.7 59 | 60 | 61 | 62 | com.sedmelluq 63 | lavaplayer 64 | 1.3.77 65 | 66 | 67 | com.github.the-codeboy 68 | Jokes4J 69 | 152d62e0 70 | 71 | 72 | org.mongodb 73 | mongodb-driver-sync 74 | 4.6.0 75 | 76 | 77 | com.github.the-codeboy 78 | Weather4J 79 | 98e42ee8ed 80 | 81 | 82 | 83 | com.github.RealCerus 84 | JGif 85 | 1.0.0 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | org.apache.maven.plugins 94 | maven-shade-plugin 95 | 3.2.4 96 | 97 | 98 | package 99 | 100 | shade 101 | 102 | 103 | 104 | 105 | ml.codeboy.thebot.MensaBot 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/java,kotlin,gradle,intellij,dotenv 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=java,kotlin,gradle,intellij,dotenv 4 | 5 | ### dotenv ### 6 | .env 7 | 8 | ### Intellij ### 9 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 10 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 11 | 12 | # User-specific stuff 13 | .idea/**/workspace.xml 14 | .idea/**/tasks.xml 15 | .idea/**/usage.statistics.xml 16 | .idea/**/dictionaries 17 | .idea/**/shelf 18 | 19 | # AWS User-specific 20 | .idea/**/aws.xml 21 | 22 | # Generated files 23 | .idea/**/contentModel.xml 24 | 25 | # Sensitive or high-churn files 26 | .idea/**/dataSources/ 27 | .idea/**/dataSources.ids 28 | .idea/**/dataSources.local.xml 29 | .idea/**/sqlDataSources.xml 30 | .idea/**/dynamic.xml 31 | .idea/**/uiDesigner.xml 32 | .idea/**/dbnavigator.xml 33 | 34 | # Gradle 35 | .idea/**/gradle.xml 36 | .idea/**/libraries 37 | 38 | # Gradle and Maven with auto-import 39 | # When using Gradle or Maven with auto-import, you should exclude module files, 40 | # since they will be recreated, and may cause churn. Uncomment if using 41 | # auto-import. 42 | # .idea/artifacts 43 | # .idea/compiler.xml 44 | # .idea/jarRepositories.xml 45 | # .idea/modules.xml 46 | # .idea/*.iml 47 | # .idea/modules 48 | # *.iml 49 | # *.ipr 50 | 51 | # CMake 52 | cmake-build-*/ 53 | 54 | # Mongo Explorer plugin 55 | .idea/**/mongoSettings.xml 56 | 57 | # File-based project format 58 | *.iws 59 | 60 | # IntelliJ 61 | out/ 62 | 63 | # mpeltonen/sbt-idea plugin 64 | .idea_modules/ 65 | 66 | # JIRA plugin 67 | atlassian-ide-plugin.xml 68 | 69 | # Cursive Clojure plugin 70 | .idea/replstate.xml 71 | 72 | # Crashlytics plugin (for Android Studio and IntelliJ) 73 | com_crashlytics_export_strings.xml 74 | crashlytics.properties 75 | crashlytics-build.properties 76 | fabric.properties 77 | 78 | # Editor-based Rest Client 79 | .idea/httpRequests 80 | 81 | # Android studio 3.1+ serialized cache file 82 | .idea/caches/build_file_checksums.ser 83 | 84 | ### Intellij Patch ### 85 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 86 | 87 | # *.iml 88 | # modules.xml 89 | # .idea/misc.xml 90 | # *.ipr 91 | 92 | # Sonarlint plugin 93 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 94 | .idea/**/sonarlint/ 95 | 96 | # SonarQube Plugin 97 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 98 | .idea/**/sonarIssues.xml 99 | 100 | # Markdown Navigator plugin 101 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 102 | .idea/**/markdown-navigator.xml 103 | .idea/**/markdown-navigator-enh.xml 104 | .idea/**/markdown-navigator/ 105 | 106 | # Cache file creation bug 107 | # See https://youtrack.jetbrains.com/issue/JBR-2257 108 | .idea/$CACHE_FILE$ 109 | 110 | # CodeStream plugin 111 | # https://plugins.jetbrains.com/plugin/12206-codestream 112 | .idea/codestream.xml 113 | 114 | ### Java ### 115 | # Compiled class file 116 | *.class 117 | 118 | # Log file 119 | *.log 120 | 121 | # BlueJ files 122 | *.ctxt 123 | 124 | # Mobile Tools for Java (J2ME) 125 | .mtj.tmp/ 126 | 127 | # Package Files # 128 | *.jar 129 | *.war 130 | *.nar 131 | *.ear 132 | *.zip 133 | *.tar.gz 134 | *.rar 135 | 136 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 137 | hs_err_pid* 138 | 139 | ### Kotlin ### 140 | # Compiled class file 141 | 142 | # Log file 143 | 144 | # BlueJ files 145 | 146 | # Mobile Tools for Java (J2ME) 147 | 148 | # Package Files # 149 | 150 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 151 | 152 | ### Gradle ### 153 | .gradle 154 | build/ 155 | 156 | # Ignore Gradle GUI config 157 | gradle-app.setting 158 | 159 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 160 | !gradle-wrapper.jar 161 | 162 | # Cache of project 163 | .gradletasknamecache 164 | 165 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 166 | # gradle/wrapper/gradle-wrapper.properties 167 | 168 | ### Gradle Patch ### 169 | **/build/ 170 | 171 | # Eclipse Gradle plugin generated files 172 | # Eclipse Core 173 | .project 174 | # JDT-specific (Eclipse Java Development Tools) 175 | .classpath 176 | 177 | # End of https://www.toptal.com/developers/gitignore/api/java,kotlin,gradle,intellij,dotenv 178 | 179 | .idea/ 180 | config.json 181 | target/classes/logback.xml 182 | 183 | *.pem 184 | quotes/ 185 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/data/FoodRatingManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.data; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.reflect.TypeToken; 5 | import net.dv8tion.jda.api.entities.User; 6 | 7 | import java.io.*; 8 | import java.lang.reflect.Type; 9 | import java.util.*; 10 | 11 | public class FoodRatingManager { 12 | 13 | private static final String filePath = "ratings" + File.separator + "ratings.json"; 14 | private static final String imagesPath = "ratings" + File.separator + "images.json"; 15 | private static final FoodRatingManager instance = new FoodRatingManager(); 16 | 17 | private FoodRatingManager() { 18 | try { 19 | loadData(); 20 | } catch (FileNotFoundException e) { 21 | throw new RuntimeException(e); 22 | } 23 | } 24 | 25 | 26 | public static FoodRatingManager getInstance() { 27 | return instance; 28 | } 29 | 30 | private Map ratings = new HashMap<>(); 31 | private Map> images = new HashMap<>(); 32 | 33 | public double getRating(String meal) { 34 | Rating rating = ratings.getOrDefault(meal, null); 35 | if (rating == null) 36 | return -1; 37 | return rating.getAverage(); 38 | } 39 | 40 | public int getRatings(String meal) { 41 | Rating rating = ratings.getOrDefault(meal, null); 42 | if (rating == null) 43 | return -1; 44 | return rating.getRatings(); 45 | } 46 | 47 | public void addRating(String meal, int rating) { 48 | Rating r = ratings.computeIfAbsent(meal, m -> new Rating()); 49 | r.addRating(rating); 50 | saveRatings(); 51 | } 52 | 53 | public void removeRating(String meal, int rating) { 54 | Rating r = ratings.computeIfAbsent(meal, m -> new Rating()); 55 | r.removeRating(rating); 56 | saveRatings(); 57 | } 58 | 59 | public MealImage addImage(String meal, String url, User author) { 60 | MealImage image = new MealImage(author.getId(), url); 61 | images.computeIfAbsent(meal, e -> new ArrayList<>()).add(image); 62 | saveImages(); 63 | return image; 64 | } 65 | 66 | public void removeImage(MealImage image) { 67 | for (Collection im : images.values()) { 68 | if (im != null) 69 | im.remove(image); 70 | } 71 | saveImages(); 72 | } 73 | 74 | public String getImage(String meal) { 75 | for (MealImage image : images.getOrDefault(meal, Collections.emptyList())) { 76 | if (image != null && image.isAccepted() && image.getUrl() != null) 77 | return image.getUrl(); 78 | } 79 | return ""; 80 | } 81 | 82 | public MealImage getImage(UUID id) { 83 | for (Collection meals : images.values()) { 84 | for (MealImage meal : meals) { 85 | if (meal != null && meal.getId() != null && meal.getId().equals(id)) 86 | return meal; 87 | } 88 | } 89 | return null; 90 | } 91 | 92 | private void loadData() throws FileNotFoundException { 93 | Type typeOfT = new TypeToken>() { 94 | }.getType(); 95 | try { 96 | File file = new File(filePath); 97 | if (file.exists()) { 98 | ratings = new Gson().fromJson(new FileReader(file), typeOfT); 99 | } 100 | } catch (Exception ignored) { 101 | } 102 | if (ratings == null) 103 | ratings = new HashMap<>(); 104 | typeOfT = new TypeToken>>() { 105 | }.getType(); 106 | try { 107 | File file = new File(imagesPath); 108 | if (file.exists()) { 109 | images = new Gson().fromJson(new FileReader(file), typeOfT); 110 | } 111 | } catch (Exception ignored) { 112 | } 113 | if (images == null) 114 | images = new HashMap<>(); 115 | } 116 | 117 | private void saveRatings() { 118 | try { 119 | new File(filePath).getParentFile().mkdirs(); 120 | FileWriter writer = new FileWriter(filePath); 121 | new Gson().toJson(ratings, writer); 122 | writer.close(); 123 | } catch (IOException ex) { 124 | ex.printStackTrace(); 125 | } 126 | } 127 | 128 | public void saveImages() { 129 | try { 130 | new File(imagesPath).getParentFile().mkdirs(); 131 | FileWriter writer = new FileWriter(imagesPath); 132 | new Gson().toJson(images, writer); 133 | writer.close(); 134 | } catch (IOException ex) { 135 | ex.printStackTrace(); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/Command.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands; 2 | 3 | import ml.codeboy.thebot.CommandHandler; 4 | import ml.codeboy.thebot.events.CommandEvent; 5 | import net.dv8tion.jda.api.EmbedBuilder; 6 | import net.dv8tion.jda.api.Permission; 7 | import net.dv8tion.jda.api.entities.Member; 8 | import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; 9 | import net.dv8tion.jda.api.interactions.commands.build.Commands; 10 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import java.awt.*; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | public abstract class Command { 19 | private final String name, description; 20 | private final String[] aliases; 21 | private Permission[] requiredPermisions = new Permission[0]; 22 | private boolean hidden = false, guildOnlyCommand = true; 23 | private final Logger logger = LoggerFactory.getLogger(getClass()); 24 | 25 | public Command(String name, String description, String... aliases) { 26 | this.name = name; 27 | if (description == null || description.isEmpty()) 28 | description = "unknown"; 29 | this.description = description; 30 | this.aliases = aliases; 31 | } 32 | 33 | protected Permission[] getRequiredPermisions() { 34 | return requiredPermisions; 35 | } 36 | 37 | protected void setRequiredPermissions(Permission... requiredPermisions) { 38 | this.requiredPermisions = requiredPermisions; 39 | } 40 | 41 | public void execute(CommandEvent event) { 42 | if (isGuildOnlyCommand() && event.getGuild() == null) { 43 | event.replyError("You can only use this command on a server. If you think this is a mistake just send the bot a message"); 44 | return; 45 | } 46 | if (!hasPermission(event)) { 47 | event.reply("Insufficient permissions"); 48 | return; 49 | } 50 | try { 51 | run(event); 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | event.replyError(e.getMessage()); 55 | } 56 | } 57 | 58 | private boolean hasPermission(CommandEvent event) { 59 | Member member = event.getMember(); 60 | if (member == null) 61 | return getRequiredPermisions().length == 0; 62 | return member.hasPermission(getRequiredPermisions()); 63 | } 64 | 65 | public abstract void run(CommandEvent event); 66 | 67 | public SlashCommandData getCommandData() { 68 | return Commands.slash(getName().toLowerCase(), getDescription()); 69 | } 70 | 71 | protected EmbedBuilder newBuilder() {//allows to configure default values for embeds like color 72 | EmbedBuilder newBuilder = new EmbedBuilder(); 73 | newBuilder.setColor(Color.black);//Black—like my soul 74 | return newBuilder; 75 | } 76 | 77 | public String getName() { 78 | return name; 79 | } 80 | 81 | public String getDescription() { 82 | return description; 83 | } 84 | 85 | public String[] getAliases() { 86 | return aliases; 87 | } 88 | 89 | public boolean isHidden() { 90 | return hidden; 91 | } 92 | 93 | public void setHidden(boolean hidden) { 94 | this.hidden = hidden; 95 | } 96 | 97 | public boolean isGuildOnlyCommand() { 98 | return guildOnlyCommand; 99 | } 100 | 101 | protected void setGuildOnlyCommand(boolean guildOnlyCommand) { 102 | this.guildOnlyCommand = guildOnlyCommand; 103 | } 104 | 105 | public void autoComplete(CommandAutoCompleteInteractionEvent event) { 106 | if (!event.isFromGuild() && isGuildOnlyCommand())//no autocompletion if the command isn't supported 107 | return; 108 | List options = new ArrayList<>(); 109 | autoComplete(event.getFocusedOption().getName(), options); 110 | 111 | List choices = new ArrayList<>(); 112 | String value = event.getFocusedOption().getValue().toLowerCase(); 113 | for (String option : options) { 114 | if (choices.size() >= 25)//choices limited to 25 115 | break; 116 | if (option.toLowerCase().contains(value)) 117 | choices.add(new net.dv8tion.jda.api.interactions.commands.Command.Choice(option, option)); 118 | } 119 | event.replyChoices(choices).queue(); 120 | } 121 | 122 | public void register(CommandHandler handler) { 123 | //do nothing 124 | } 125 | 126 | public void autoComplete(String option, List options) { 127 | //do nothing by default 128 | } 129 | 130 | public Logger getLogger() { 131 | return logger; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/mensa/DetailCommand.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.mensa; 2 | 3 | import com.github.codeboy.api.Meal; 4 | import com.github.codeboy.api.Mensa; 5 | import ml.codeboy.thebot.MensaUtil; 6 | import ml.codeboy.thebot.commands.Command; 7 | import ml.codeboy.thebot.data.CommentManager; 8 | import ml.codeboy.thebot.data.FoodRatingManager; 9 | import ml.codeboy.thebot.data.GuildManager; 10 | import ml.codeboy.thebot.data.MealEmoji; 11 | import ml.codeboy.thebot.events.CommandEvent; 12 | import ml.codeboy.thebot.util.Replyable; 13 | import net.dv8tion.jda.api.EmbedBuilder; 14 | import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; 15 | import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; 16 | import net.dv8tion.jda.api.interactions.commands.OptionType; 17 | import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Date; 21 | import java.util.List; 22 | 23 | public class DetailCommand extends Command { 24 | 25 | private final int maxDaysAgo = 2; 26 | 27 | public DetailCommand() { 28 | super("detail", "gives details about a meal", "meal"); 29 | } 30 | 31 | @Override 32 | public SlashCommandData getCommandData() { 33 | return super.getCommandData() 34 | .addOption(OptionType.STRING, "meal", "The meal to rate", true, true); 35 | } 36 | 37 | @Override 38 | public void autoComplete(CommandAutoCompleteInteractionEvent event) { 39 | List options = new ArrayList<>(); 40 | String selected = event.getFocusedOption().getName(); 41 | 42 | 43 | switch (selected) { 44 | case "meal": { 45 | Mensa mensa = GuildManager.getInstance().getData(event.getGuild()).getDefaultMensa(); 46 | for (int i = 0; i <= maxDaysAgo; i++) { 47 | Date date = new Date(System.currentTimeMillis() - 3600000L * 24 * i); 48 | for (Meal meal : mensa.getMeals(date)) { 49 | options.add(meal.getName()); 50 | } 51 | } 52 | break; 53 | } 54 | case "rating": { 55 | options.add("1"); 56 | options.add("2"); 57 | options.add("3"); 58 | options.add("4"); 59 | options.add("5"); 60 | break; 61 | } 62 | } 63 | 64 | List choices = new ArrayList<>(); 65 | String value = event.getFocusedOption().getValue().toLowerCase(); 66 | for (String option : options) { 67 | if (choices.size() >= 25)//choices limited to 25 68 | break; 69 | if (option.toLowerCase().contains(value)) { 70 | net.dv8tion.jda.api.interactions.commands.Command.Choice choice = new net.dv8tion.jda.api.interactions.commands.Command.Choice(option, option); 71 | if (!choices.contains(choice)) 72 | choices.add(choice); 73 | } 74 | } 75 | event.replyChoices(choices).queue(); 76 | } 77 | 78 | @Override 79 | public void run(CommandEvent event) { 80 | String name = null; 81 | if (event.isSlashCommandEvent()) { 82 | SlashCommandInteractionEvent scie = event.getSlashCommandEvent(); 83 | name = scie.getOption("meal").getAsString(); 84 | } 85 | if (name == null) 86 | name = String.join(" ", event.getArgs()); 87 | 88 | Mensa mensa = GuildManager.getInstance().getData(event.getGuild()).getDefaultMensa(); 89 | for (int i = 0; i <= maxDaysAgo; i++) { 90 | Date date = new Date(System.currentTimeMillis() - 3600000L * 24 * i); 91 | for (Meal meal : mensa.getMeals(date)) { 92 | if (meal.getName().equalsIgnoreCase(name)) { 93 | sendDetails(event, meal); 94 | return; 95 | } 96 | } 97 | } 98 | event.replyError("Can not find meal"); 99 | } 100 | 101 | public static void sendDetails(Replyable event, Meal meal) { 102 | EmbedBuilder builder = new EmbedBuilder(); 103 | builder.setTitle(MensaUtil.getTitleString(meal)); 104 | String url = FoodRatingManager.getInstance().getImage(meal.getName()); 105 | if (url != null && url.length() > 0) 106 | builder.setImage(url); 107 | builder.addBlankField(false); 108 | for (String note : meal.getNotes()) { 109 | MealEmoji emoji = MensaUtil.getEmojiForWord(note); 110 | builder.addField((emoji == null ? "" : emoji.getEmoji()) + " " + note, "", true); 111 | } 112 | builder.addBlankField(false); 113 | for (String comment : CommentManager.getInstance().getComments(meal.getName())) { 114 | builder.addField("", comment, false); 115 | } 116 | 117 | event.reply(builder.build()); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/TrackScheduler.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; 4 | import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter; 5 | import com.sedmelluq.discord.lavaplayer.track.AudioTrack; 6 | import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; 7 | import ml.codeboy.thebot.events.CommandEvent; 8 | import ml.codeboy.thebot.util.Util; 9 | import net.dv8tion.jda.api.EmbedBuilder; 10 | 11 | import java.util.*; 12 | 13 | public class TrackScheduler extends AudioEventAdapter { 14 | private final AudioPlayer player; 15 | private final ArrayList queue = new ArrayList<>(); 16 | private ArrayList nextQueue = null; 17 | private CommandEvent latestEvent = null; 18 | private int loop = 0, currentLoop = 0; 19 | private boolean destroyed = false; 20 | private final GuildMusicManager manager; 21 | 22 | public TrackScheduler(GuildMusicManager manager) { 23 | this.player = manager.audioPlayer; 24 | this.manager = manager; 25 | } 26 | 27 | public void queue(AudioTrack track) { 28 | queue(track, false); 29 | } 30 | 31 | public void queue(AudioTrack track, boolean playNext) { 32 | if (!this.player.startTrack(track, true)) { 33 | if (playNext) 34 | this.queue.add(0, track); 35 | else 36 | this.queue.add(track); 37 | } 38 | } 39 | 40 | public void playNext(AudioTrack track) { 41 | if (!this.player.startTrack(track, true)) { 42 | this.queue.add(0, track); 43 | } 44 | } 45 | 46 | public void nextTrack() { 47 | if (destroyed) 48 | return; 49 | 50 | AudioTrack track = queue.size() > 0 ? this.queue.remove(0) : null; 51 | 52 | if (track == null && nextQueue != null) { 53 | for (AudioTrack t : nextQueue) 54 | queue.add(t.makeClone()); 55 | track = queue.size() > 0 ? this.queue.remove(0) : null; 56 | 57 | } 58 | 59 | if (track == null) { 60 | PlayerManager.getInstance().destroy(manager.guild); 61 | // if(latestEvent!=null) 62 | // latestEvent.replyError("There are no more tracks in the queue"); 63 | return; 64 | } 65 | play(track); 66 | currentLoop = 0; 67 | } 68 | 69 | public void play(AudioTrack track) { 70 | this.player.startTrack(track, false); 71 | if (latestEvent != null) { 72 | Util.sendTrackInfo(latestEvent, track); 73 | } 74 | } 75 | 76 | public void loop(int times) { 77 | loop = times; 78 | } 79 | 80 | public void loopQueue() { 81 | nextQueue = new ArrayList<>(queue); 82 | } 83 | 84 | public void dontLoopQueue() { 85 | nextQueue = null; 86 | } 87 | 88 | @Override 89 | public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { 90 | if (endReason == AudioTrackEndReason.FINISHED && currentLoop++ < loop) { 91 | play(track.makeClone()); 92 | } else if (endReason != AudioTrackEndReason.REPLACED) { 93 | if (endReason.mayStartNext || nextQueue != null) 94 | nextTrack(); 95 | else if (latestEvent != null) 96 | PlayerManager.getInstance().destroy(latestEvent.getGuild()); 97 | } 98 | } 99 | 100 | public void sendQueueInfo(CommandEvent event) { 101 | EmbedBuilder builder = event.getBuilder(); 102 | Util.sign(builder, event).setTitle("Current queue"); 103 | if (queue.isEmpty()) 104 | builder.setDescription("empty"); 105 | else 106 | for (int i = 0; i < queue.size(); i++) { 107 | if (i > 5) 108 | break; 109 | AudioTrack track = queue.get(i); 110 | builder.addField((i + 1) + ". " + track.getInfo().title, 111 | "by " + track.getInfo().author, 112 | true); 113 | } 114 | event.reply(builder); 115 | } 116 | 117 | public void setLatestEvent(CommandEvent latestEvent) { 118 | this.latestEvent = latestEvent; 119 | } 120 | 121 | public void shuffle() { 122 | List tracks = Arrays.asList(queue.toArray(new AudioTrack[0])); 123 | Collections.shuffle(tracks); 124 | queue.clear(); 125 | queue.addAll(tracks); 126 | } 127 | 128 | public int songsInQueue() { 129 | return queue.size(); 130 | } 131 | 132 | public boolean removeTrack(int id) { 133 | Iterator iterator = queue.iterator(); 134 | int i = 1; 135 | while (iterator.hasNext()) { 136 | AudioTrack track = iterator.next(); 137 | if (i++ == id) { 138 | iterator.remove(); 139 | return true; 140 | } 141 | } 142 | return false; 143 | } 144 | 145 | 146 | public void destroy() { 147 | destroyed = true; 148 | } 149 | } -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/util/ASCII.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.util; 2 | 3 | import java.awt.*; 4 | import java.awt.geom.AffineTransform; 5 | import java.awt.image.AffineTransformOp; 6 | import java.awt.image.BufferedImage; 7 | 8 | /*Copyright (c) 2011 Aravind Rao 9 | Modifications by Sam Barnum, 360Works 2012 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 11 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to 12 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 13 | * to whom the Software is furnished to do so, subject to the following conditions: 14 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 16 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 18 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | public final class ASCII { 22 | 23 | public static String convert(final BufferedImage image) { 24 | return convert(image, false); 25 | } 26 | 27 | public static String convert(BufferedImage image, boolean negative) { 28 | StringBuilder sb = new StringBuilder((image.getWidth() + 1) * image.getHeight()); 29 | for (int y = 0; y < image.getHeight(); y++) { 30 | if (sb.length() != 0) sb.append("\n"); 31 | for (int x = 0; x < image.getWidth(); x++) { 32 | Color pixelColor = new Color(image.getRGB(x, y)); 33 | double gValue = (double) pixelColor.getRed() * 0.2989 + (double) pixelColor.getBlue() * 0.5870 + (double) pixelColor.getGreen() * 0.1140; 34 | final char s = negative ? returnStrNeg(gValue) : returnStrPos(gValue); 35 | sb.append(s); 36 | } 37 | } 38 | return sb.toString(); 39 | } 40 | 41 | public static BufferedImage scale(BufferedImage image) { 42 | int x = image.getWidth() + 1, y = image.getHeight(); 43 | int size = x * y; 44 | if (size >= 2000) { 45 | double scale = Math.sqrt(1999f / size); 46 | x = (int) (x * scale) - 1; 47 | y = (int) (y * scale); 48 | BufferedImage after = new BufferedImage(x, y, BufferedImage.TYPE_INT_ARGB); 49 | AffineTransform at = new AffineTransform(); 50 | at.scale(scale, scale); 51 | AffineTransformOp scaleOp = 52 | new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); 53 | image = scaleOp.filter(image, after); 54 | } 55 | return image; 56 | } 57 | 58 | /** 59 | * Create a new string and assign to it a string based on the grayscale value. 60 | * If the grayscale value is very high, the pixel is very bright and assign characters 61 | * such as . and , that do not appear very dark. If the grayscale value is very lowm the pixel is very dark, 62 | * assign characters such as # and @ which appear very dark. 63 | * 64 | * @param g grayscale 65 | * @return char 66 | */ 67 | private static char returnStrPos(double g)//takes the grayscale value as parameter 68 | { 69 | final char str; 70 | 71 | if (g >= 230.0) { 72 | str = ' '; 73 | } else if (g >= 200.0) { 74 | str = '.'; 75 | } else if (g >= 180.0) { 76 | str = '*'; 77 | } else if (g >= 160.0) { 78 | str = ':'; 79 | } else if (g >= 130.0) { 80 | str = 'o'; 81 | } else if (g >= 100.0) { 82 | str = '&'; 83 | } else if (g >= 70.0) { 84 | str = '8'; 85 | } else if (g >= 50.0) { 86 | str = '#'; 87 | } else { 88 | str = '@'; 89 | } 90 | return str; // return the character 91 | 92 | } 93 | 94 | /** 95 | * Same method as above, except it reverses the darkness of the pixel. A dark pixel is given a light character and vice versa. 96 | * 97 | * @param g grayscale 98 | * @return char 99 | */ 100 | private static char returnStrNeg(double g) { 101 | final char str; 102 | 103 | if (g >= 230.0) { 104 | str = '@'; 105 | } else if (g >= 200.0) { 106 | str = '#'; 107 | } else if (g >= 180.0) { 108 | str = '8'; 109 | } else if (g >= 160.0) { 110 | str = '&'; 111 | } else if (g >= 130.0) { 112 | str = 'o'; 113 | } else if (g >= 100.0) { 114 | str = ':'; 115 | } else if (g >= 70.0) { 116 | str = '*'; 117 | } else if (g >= 50.0) { 118 | str = '.'; 119 | } else { 120 | str = ' '; 121 | } 122 | return str; 123 | 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/commands/sound/PlayerManager.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.commands.sound; 2 | 3 | import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; 4 | import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; 5 | import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; 6 | import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; 7 | import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; 8 | import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; 9 | import com.sedmelluq.discord.lavaplayer.track.AudioTrack; 10 | import ml.codeboy.thebot.events.CommandEvent; 11 | import net.dv8tion.jda.api.entities.Guild; 12 | 13 | import java.util.Collections; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | public class PlayerManager { 18 | 19 | private static PlayerManager INSTANCE; 20 | private final Map musicManagers; 21 | private final AudioPlayerManager audioPlayerManager; 22 | 23 | private PlayerManager() { 24 | this.musicManagers = new HashMap<>(); 25 | this.audioPlayerManager = new DefaultAudioPlayerManager(); 26 | 27 | AudioSourceManagers.registerRemoteSources(this.audioPlayerManager); 28 | AudioSourceManagers.registerLocalSource(this.audioPlayerManager); 29 | } 30 | 31 | public static PlayerManager getInstance() { 32 | if (INSTANCE == null) { 33 | INSTANCE = new PlayerManager(); 34 | } 35 | 36 | return INSTANCE; 37 | } 38 | 39 | public GuildMusicManager getMusicManager(Guild guild) { 40 | return this.musicManagers.computeIfAbsent(guild.getIdLong(), (guildId) -> { 41 | final GuildMusicManager guildMusicManager = new GuildMusicManager(this.audioPlayerManager, guild); 42 | 43 | guild.getAudioManager().setSendingHandler(guildMusicManager.getSendHandler()); 44 | 45 | return guildMusicManager; 46 | }); 47 | } 48 | 49 | public void load(CommandEvent event, String trackUrl, boolean play, boolean playNext) { 50 | load(event, trackUrl, play, true, playNext); 51 | } 52 | 53 | public void load(CommandEvent event, String trackUrl, boolean play, boolean notify, boolean playNext) { 54 | load(event, trackUrl, play, notify, playNext, false); 55 | } 56 | 57 | public void load(CommandEvent event, String trackUrl, boolean play, boolean notify, boolean playNext, boolean shuffle) { 58 | load(event, event.getGuild(), trackUrl, play, notify, playNext, shuffle); 59 | } 60 | 61 | public void load(CommandEvent event, Guild guild, String trackUrl, boolean play, boolean notify, boolean playNext, boolean shuffle) { 62 | final GuildMusicManager musicManager = this.getMusicManager(guild); 63 | 64 | this.audioPlayerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler() { 65 | @Override 66 | public void trackLoaded(AudioTrack track) { 67 | if (!play) { 68 | musicManager.scheduler.queue(track, playNext); 69 | 70 | if (notify) 71 | songAddedToQueue(event, track); 72 | } else { 73 | musicManager.audioPlayer.startTrack(track, false); 74 | 75 | if (notify) 76 | songPlaying(event, track); 77 | } 78 | } 79 | 80 | @Override 81 | public void playlistLoaded(AudioPlaylist playlist) { 82 | if (playlist.isSearchResult() && playlist.getTracks().size() > 0) { 83 | trackLoaded(playlist.getTracks().get(0)); 84 | return; 85 | } 86 | 87 | if (shuffle) 88 | Collections.shuffle(playlist.getTracks()); 89 | for (AudioTrack track : playlist.getTracks()) { 90 | musicManager.scheduler.queue(track); 91 | } 92 | 93 | if (notify) 94 | playlistAddedToQueue(event, playlist); 95 | } 96 | 97 | @Override 98 | public void noMatches() { 99 | if (notify) 100 | event.reply("No matches"); 101 | } 102 | 103 | @Override 104 | public void loadFailed(FriendlyException exception) { 105 | exception.printStackTrace(); 106 | System.err.println("load failed"); 107 | event.replyErrorUnknown(); 108 | } 109 | }); 110 | } 111 | 112 | public void songAddedToQueue(CommandEvent event, AudioTrack track) { 113 | event.reply(event.getBuilder().setTitle("Song added to queue") 114 | .addField(track.getInfo().title, "by `" + track.getInfo().author + '`', true)); 115 | } 116 | 117 | public void songPlaying(CommandEvent event, AudioTrack track) { 118 | event.reply(event.getBuilder().setTitle("Now playing") 119 | .addField(track.getInfo().title, " by `" + track.getInfo().author + '`', true)); 120 | } 121 | 122 | public void playlistAddedToQueue(CommandEvent event, AudioPlaylist playlist) { 123 | event.reply(event.getBuilder().setTitle("Playlist added to queue") 124 | .addField(playlist.getName(), "with " + playlist.getTracks().size() + " tracks", true)); 125 | } 126 | 127 | public void destroy(Guild guild) { 128 | GuildMusicManager musicManager = musicManagers.remove(guild.getIdLong()); 129 | if (musicManager != null) 130 | musicManager.destroy(); 131 | guild.getAudioManager().closeAudioConnection(); 132 | } 133 | 134 | 135 | } -------------------------------------------------------------------------------- /src/main/java/ml/codeboy/thebot/events/CommandEvent.java: -------------------------------------------------------------------------------- 1 | package ml.codeboy.thebot.events; 2 | 3 | import com.github.codeboy.OpenMensa; 4 | import com.github.codeboy.api.Mensa; 5 | import ml.codeboy.thebot.Config; 6 | import ml.codeboy.thebot.commands.sound.GuildMusicManager; 7 | import ml.codeboy.thebot.commands.sound.PlayerManager; 8 | import ml.codeboy.thebot.data.GuildData; 9 | import ml.codeboy.thebot.data.GuildManager; 10 | import ml.codeboy.thebot.util.Replyable; 11 | import net.dv8tion.jda.api.EmbedBuilder; 12 | import net.dv8tion.jda.api.entities.*; 13 | import net.dv8tion.jda.api.events.Event; 14 | import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; 15 | import net.dv8tion.jda.api.events.message.MessageReceivedEvent; 16 | import net.dv8tion.jda.api.interactions.commands.OptionMapping; 17 | 18 | import javax.imageio.ImageIO; 19 | import java.awt.*; 20 | import java.awt.image.BufferedImage; 21 | import java.io.File; 22 | import java.io.IOException; 23 | import java.util.ArrayList; 24 | import java.util.Random; 25 | 26 | public abstract class CommandEvent implements Replyable { 27 | private static final Random random = new Random(); 28 | private final Event jdaEvent; 29 | private boolean ephermal = false; 30 | 31 | public CommandEvent(Event jdaEvent) { 32 | this.jdaEvent = jdaEvent; 33 | } 34 | 35 | public abstract void reply(String message); 36 | 37 | public abstract void reply(MessageEmbed... embed); 38 | 39 | public abstract void reply(String message, File file, String name); 40 | 41 | public abstract User getUser(); 42 | 43 | public abstract Member getMember(); 44 | 45 | public void reply(EmbedBuilder builder) { 46 | reply(builder.build()); 47 | } 48 | 49 | 50 | public abstract void edit(String message); 51 | 52 | public abstract void edit(MessageEmbed... embed); 53 | 54 | public void edit(EmbedBuilder builder) { 55 | edit(builder.build()); 56 | } 57 | 58 | public abstract void reply(File file, String name); 59 | 60 | public void reply(BufferedImage image, String type) { 61 | reply(image, type, "image"); 62 | } 63 | 64 | public void reply(BufferedImage image, String type, String name) { 65 | reply(null, image, type, name); 66 | } 67 | 68 | public void reply(String message, BufferedImage image, String type) { 69 | reply(message, image, type, "image"); 70 | } 71 | 72 | public void reply(String message, BufferedImage image, String type, String name) { 73 | File file = new File("images/" + random.nextInt() + "." + type); 74 | try { 75 | ImageIO.write(image, type, file); 76 | } catch (IOException e) { 77 | throw new RuntimeException(e); 78 | } 79 | if (message == null) 80 | reply(file, name + "." + type); 81 | else reply(message, file, name + "." + type); 82 | file.delete(); 83 | } 84 | 85 | public void replyError(String error) { 86 | reply(new EmbedBuilder().setTitle("Error").setDescription(error).setColor(Color.RED).build()); 87 | } 88 | 89 | //region getter 90 | public MessageReceivedEvent getMessageReceivedEvent() { 91 | return (MessageReceivedEvent) jdaEvent; 92 | } 93 | 94 | public SlashCommandInteractionEvent getSlashCommandEvent() { 95 | return (SlashCommandInteractionEvent) jdaEvent; 96 | } 97 | 98 | public String[] getArgs() {// TODO: Add better way to use arguments. Maybe something similar to JDAs slash commands 99 | if (isMessageEvent()) { 100 | String content = getMessageReceivedEvent().getMessage().getContentRaw(); 101 | content = content.replaceFirst(Config.getInstance().prefix, ""); 102 | 103 | String[] splitContent = content.split(" ", 2); 104 | 105 | if (splitContent.length == 1) 106 | return new String[0]; 107 | 108 | String withoutCommand = splitContent[1]; 109 | return withoutCommand.split(" "); 110 | } else { 111 | ArrayList arguments = new ArrayList<>(); 112 | for (OptionMapping o : getSlashCommandEvent().getOptions()) { 113 | arguments.add(o.getAsString()); 114 | } 115 | return arguments.toArray(new String[0]); 116 | } 117 | } 118 | 119 | public Event getJdaEvent() { 120 | return jdaEvent; 121 | } 122 | 123 | public boolean isMessageEvent() { 124 | return this instanceof MessageCommandEvent; 125 | } 126 | 127 | public boolean isSlashCommandEvent() { 128 | return this instanceof SlashCommandCommandEvent; 129 | } 130 | 131 | public abstract Guild getGuild(); 132 | 133 | public GuildData getGuildData() { 134 | return GuildManager.getInstance().getData(getGuild()); 135 | } 136 | 137 | public abstract MessageChannel getChannel(); 138 | 139 | public Message send(String message) { 140 | return getChannel().sendMessage(message).complete(); 141 | } 142 | 143 | public Message send(MessageEmbed message) { 144 | return getChannel().sendMessageEmbeds(message).complete(); 145 | } 146 | 147 | public Message send(EmbedBuilder builder) { 148 | return send(builder.build()); 149 | } 150 | 151 | public void replyErrorUnknown() { 152 | replyError("unknown error"); 153 | } 154 | 155 | public EmbedBuilder getBuilder() { 156 | return new EmbedBuilder(); 157 | } 158 | 159 | public GuildMusicManager getManager() { 160 | return PlayerManager.getInstance().getMusicManager(getGuild()); 161 | } 162 | 163 | public boolean isEphermal() { 164 | return ephermal; 165 | } 166 | 167 | public void setEphermal(boolean ephermal) { 168 | this.ephermal = ephermal; 169 | } 170 | 171 | public Mensa getDefaultMensa() { 172 | if (getGuild() == null) 173 | return OpenMensa.getInstance().getMensa(187); 174 | return getGuildData().getDefaultMensa(); 175 | } 176 | 177 | //endregion 178 | } 179 | --------------------------------------------------------------------------------