inital commit

This commit is contained in:
nora 2021-04-02 16:50:07 +02:00
commit 5d4df2c9c9
27 changed files with 1157 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
/target
Secrets.java
.idea
*.iml

7
dbschema Normal file
View file

@ -0,0 +1,7 @@
(:User {id:number})
(:Thing {type:string, name:string, tags:[string]})
type: s(show), g(game), m(movie), o(other)
(:User) - [:SUBS_TO] -> (:User)
(:User) - [:LIKES] -> (:Thing)

49
pom.xml Normal file
View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>relationship-bot</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>4.2.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jcenter</id>
<name>jcenter-bintray</name>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
</project>

View file

@ -0,0 +1,31 @@
package com.github.nilstrieb.recommendationbot.cofig;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.JDA;
import java.awt.*;
public class Config {
public static final String PREFIX = "r-";
public static final Color DEFAULT_COLOR = new Color(40, 38, 38);
public static final String VERSION = "0.1.0";
public static long thisId = 0;
private static JDA jda;
private static final String GUILD_COUNT_FILE_NAME = "guild_count.txt";
private static int guildCount;
public static void setJda(JDA jda) {
Config.jda = jda;
}
public static EmbedBuilder getDefaultEmbed() {
EmbedBuilder builder = new EmbedBuilder();
builder.setColor(Config.DEFAULT_COLOR).
setThumbnail(jda.getSelfUser().getAvatarUrl());
return builder;
}
}

View file

@ -0,0 +1,32 @@
package com.github.nilstrieb.recommendationbot.commands.info;
import com.github.nilstrieb.recommendationbot.core.command.Command;
import com.github.nilstrieb.recommendationbot.core.command.CommandHandler;
import net.dv8tion.jda.api.entities.MessageEmbed;
public class HelpCommand extends Command {
public HelpCommand() {
super("help");
setDescription("Shows this message");
setExampleUsage("help invite");
setArguments("(command name)");
}
@Override
public void called(String args) {
if (args.length() == 0) {
MessageEmbed[] helpList = CommandHandler.getHelpList();
if (helpList.length == 1) {
reply(helpList[0]);
} else {
reply(helpList);
}
} else {
MessageEmbed help = CommandHandler.getCommandHelp(args);
if (help != null) {
reply(help);
}
}
}
}

View file

@ -0,0 +1,29 @@
package com.github.nilstrieb.recommendationbot.commands.info;
import com.github.nilstrieb.recommendationbot.cofig.Config;
import com.github.nilstrieb.recommendationbot.core.command.Command;
import net.dv8tion.jda.api.entities.MessageEmbed;
import java.text.NumberFormat;
import java.util.Locale;
public class InfoCommand extends Command {
public InfoCommand() {
super("info");
setDescription("Info about me!");
}
@Override
public void called(String args) {
NumberFormat nf = NumberFormat.getInstance(Locale.ENGLISH);
MessageEmbed embed = Config.getDefaultEmbed()
.setTitle("Info about me")
.setDescription("Get recommendations for things from you friends and people who like the same things!")
.setFooter("Version v" + Config.VERSION).build();
reply(embed);
}
}

View file

@ -0,0 +1,22 @@
package com.github.nilstrieb.recommendationbot.commands.info;
import com.github.nilstrieb.recommendationbot.cofig.Config;
import com.github.nilstrieb.recommendationbot.core.command.Command;
import net.dv8tion.jda.api.entities.MessageEmbed;
public class InviteCommand extends Command {
public InviteCommand() {
super("invite");
setDescription("Get the invite link for this bot");
}
@Override
public void called(String args) {
MessageEmbed builder = Config.getDefaultEmbed()
.setTitle("Invite me!")
.setDescription("[Click here](https://www.youtube.com/watch?v=dQw4w9WgXcQ)").build();
reply(builder);
}
}

View file

@ -0,0 +1,22 @@
package com.github.nilstrieb.recommendationbot.commands.info;
import com.github.nilstrieb.recommendationbot.core.command.Command;
public class RebootCommand extends Command {
public RebootCommand() {
super("reboot");
setHidden();
}
@Override
public void called(String args) {
long id = event.getMember().getUser().getIdLong();
if (id == 414755070161453076L) {
event.getTextChannel().sendMessage("Rebooting!").queue();
System.exit(409);
} else {
event.getTextChannel().sendMessage("Sorry, you don't seem to have sufficient Permissions for this!").queue();
}
}
}

View file

@ -0,0 +1,23 @@
package com.github.nilstrieb.recommendationbot.commands.reco;
import com.github.nilstrieb.recommendationbot.core.command.Command;
import com.github.nilstrieb.recommendationbot.db.Neo4jConnection;
public class RecommendCommand extends Command {
public RecommendCommand() {
super("recommend");
setAlias("reco");
setAlias("r");
setDescription("Recommend something!");
setArguments("<name>");
setExampleUsage("recommend hunter x hunter");
}
@Override
public void called(String args) {
String uid = event.getAuthor().getId();
Neo4jConnection.getInstance().createRecommendation(uid, args);
}
}

View file

@ -0,0 +1,40 @@
package com.github.nilstrieb.recommendationbot.commands.reco;
import com.github.nilstrieb.recommendationbot.core.command.Command;
import com.github.nilstrieb.recommendationbot.db.Neo4jConnection;
import net.dv8tion.jda.api.entities.Member;
import java.util.List;
public class SubCommand extends Command {
public SubCommand() {
super("subscribe");
setAlias("sub");
setAlias("s");
}
@Override
public void called(String args) {
String uid = event.getAuthor().getId();
List<Member> mentions = event.getMessage().getMentionedMembers();
if (mentions.size() < 1) {
reply("Mention at least one member");
return;
}
Neo4jConnection connection = Neo4jConnection.getInstance();
String target = mentions.get(0).getId();
if (connection.isSubbed(uid, target)) {
reply("You are already subscribed to the user");
return;
}
connection.createSub(uid, target);
}
}

View file

@ -0,0 +1,63 @@
package com.github.nilstrieb.recommendationbot.core;
import com.github.nilstrieb.recommendationbot.cofig.Config;
import com.github.nilstrieb.recommendationbot.cofig.Secrets;
import com.github.nilstrieb.recommendationbot.commands.info.HelpCommand;
import com.github.nilstrieb.recommendationbot.commands.info.InfoCommand;
import com.github.nilstrieb.recommendationbot.commands.info.InviteCommand;
import com.github.nilstrieb.recommendationbot.commands.info.RebootCommand;
import com.github.nilstrieb.recommendationbot.commands.reco.RecommendCommand;
import com.github.nilstrieb.recommendationbot.commands.reco.SubCommand;
import com.github.nilstrieb.recommendationbot.core.command.CommandListener;
import com.github.nilstrieb.recommendationbot.core.reactions.ReactionEventListener;
import com.github.nilstrieb.recommendationbot.core.sections.ChannelMessageListener;
import com.github.nilstrieb.recommendationbot.db.Neo4jConnection;
import com.github.nilstrieb.recommendationbot.listeners.StartUpListener;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.Compression;
import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import javax.security.auth.login.LoginException;
public class Main {
public static void main(String[] args) throws LoginException {
JDABuilder builder =
JDABuilder.createDefault(Secrets.BOT_TOKEN);
builder.setCompression(Compression.ZLIB);
builder.setStatus(OnlineStatus.ONLINE);
builder.setAutoReconnect(true);
builder.setActivity(Activity.listening(Config.PREFIX + "help"));
builder.setDisabledIntents(GatewayIntent.GUILD_PRESENCES, GatewayIntent.GUILD_MEMBERS);
builder.setMemberCachePolicy(MemberCachePolicy.NONE);
builder.disableCache(CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS, CacheFlag.ROLE_TAGS, CacheFlag.MEMBER_OVERRIDES, CacheFlag.EMOTE, CacheFlag.VOICE_STATE);
builder.addEventListeners(
new StartUpListener(),
new ChannelMessageListener(),
new CommandListener(),
new ReactionEventListener()
);
JDA jda = builder.build();
Config.setJda(jda);
setupCommands();
Neo4jConnection.create("bolt://localhost:7687", "neo4j", Secrets.NEO4J_PW);
}
private static void setupCommands() {
new HelpCommand();
new InviteCommand();
new InfoCommand();
new RebootCommand();
new RecommendCommand();
new SubCommand();
}
}

View file

@ -0,0 +1,80 @@
package com.github.nilstrieb.recommendationbot.core.command;
/**
* The base command class. Every command should extend this class.
*/
public abstract class Command extends MessageSender {
private String name;
private String description;
private String exampleUsage;
private String arguments;
private String detailDescription;
//Array of all command aliases
private String[] aliases;
//whether the command should be displayed on the help page
//note: this does not make the command restricted in any way
private boolean hidden;
/**
* Create a new command
* @param name name
*/
public Command(String name) {
this.name = name;
this.description = "";
this.exampleUsage = "";
this.arguments = "";
this.detailDescription = "";
CommandHandler.addCommand(name, this);
}
protected void setAlias(String alias) {
CommandHandler.addAlias(alias, this);
}
protected void setDescription(String description) {
this.description = description;
}
protected void setExampleUsage(String exampleUsage) {
this.exampleUsage = exampleUsage;
}
protected void setArguments(String arguments) {
this.arguments = arguments;
}
protected void setDetailDescription(String detailDescription) {
this.detailDescription = detailDescription;
}
protected void setHidden() {
this.hidden = true;
CommandHandler.hide(this);
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getExampleUsage() {
return exampleUsage;
}
public String getArguments() {
return arguments;
}
public String getDetailDescription() {
return detailDescription;
}
public boolean isHidden() {
return hidden;
}
}

View file

@ -0,0 +1,138 @@
package com.github.nilstrieb.recommendationbot.core.command;
import com.github.nilstrieb.recommendationbot.cofig.Config;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import java.util.*;
/**
* The CommandHandler handles everything about the commands
*/
public class CommandHandler {
public static final int MAX_HELP_PAGE_LENGTH = 10;
private static final Map<String, Command> commands = new HashMap<>();
private static final HashSet<Command> uniqueVisibleCommands = new HashSet<>();
private static final CommandParser parser = new CommandParser();
/**
* Add a new command to the handler. This is normally done by the{@code Command}.
*
* @param key The key (command name)
* @param cmd The command object
*/
static void addCommand(String key, Command cmd) {
commands.put(key, cmd);
if (!cmd.isHidden()) {
uniqueVisibleCommands.add(cmd);
}
}
/**
* Add an alias for a command
*
* @param alias The alias
* @param command The command object
*/
static void addAlias(String alias, Command command) {
commands.put(alias, command);
}
/**
* Hide a command
*
* @param command The command to be hidden
*/
static void hide(Command command) {
uniqueVisibleCommands.remove(command);
}
/**
* This method is called by the{@code CommandListener}
*
* @param event The {@code MessageReceivedEvent}
*/
static void call(MessageReceivedEvent event) {
if (event.getMessage().getContentRaw().toLowerCase().startsWith(Config.PREFIX)) {
String[] split = parser.splitOffCommandName(event.getMessage().getContentRaw());
String command = split[0];
if (commands.containsKey(command)) {
commands.get(command).onMessageReceived(event, split[1]);
}
}
}
/**
* Get a list of all commands, returns many pages if there are lots of commands
*
* @return The pages
*/
public static MessageEmbed[] getHelpList() {
List<MessageEmbed> embeds = new ArrayList<>();
EmbedBuilder builder = Config.getDefaultEmbed()
.setTitle("Touka's Commands");
int length = 0;
for (Command cmd : uniqueVisibleCommands) {
if (length == MAX_HELP_PAGE_LENGTH) {
embeds.add(builder.build());
builder = Config.getDefaultEmbed()
.setTitle("Touka's Commands");
}
builder.addField(Config.PREFIX + cmd.getName(), "`" + cmd.getDescription() + "`", false);
length++;
}
if (builder.getFields().size() != 0) {
embeds.add(builder.build());
}
MessageEmbed[] array = new MessageEmbed[embeds.size()];
for (int i = 0; i < embeds.size(); i++) {
array[i] = embeds.get(i);
}
return array;
}
/**
* Returns the help page for a single command
*
* @param command The command name
* @return The help page
*/
public static MessageEmbed getCommandHelp(String command) {
Command cmd = commands.get(command);
if (cmd != null) {
EmbedBuilder builder = Config.getDefaultEmbed()
.setTitle("Touka help for: " + Config.PREFIX + cmd.getName())
.addField("Name", cmd.getName(), true);
if (!cmd.getDescription().equals("")) {
builder.addField("Description:", cmd.getDescription(), true);
}
if (cmd.getExampleUsage().equals("")) {
builder.addField("Example usage", "`" + Config.PREFIX + cmd.getName() + "`", true);
} else {
builder.addField("Example usage", "`" + Config.PREFIX + cmd.getExampleUsage() + "`", true);
}
if (!cmd.getArguments().equals("")) {
builder.addField("Arguments", "`" + cmd.getArguments() + "`", true);
}
if (!cmd.getDetailDescription().equals("")) {
builder.addField("Details:", "`" + cmd.getDetailDescription() + "`", true);
}
return builder.build();
}
return null;
}
}

View file

@ -0,0 +1,14 @@
package com.github.nilstrieb.recommendationbot.core.command;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
public class CommandListener extends ListenerAdapter {
@Override
public void onMessageReceived(@NotNull MessageReceivedEvent event) {
if (!event.getAuthor().isBot()) {
CommandHandler.call(event);
}
}
}

View file

@ -0,0 +1,29 @@
package com.github.nilstrieb.recommendationbot.core.command;
import com.github.nilstrieb.recommendationbot.cofig.Config;
/**
* A parser for parsing commands
*/
public class CommandParser {
public static String[] splitArgs(String args){
return args.split(" ");
}
/**
* Split the full message into command name + args
* @param contentRaw The full message (including prefix!)
* @return a String array where [0] is the command name and [1] are the args (the text after the name + an optional space)
*/
public String[] splitOffCommandName(String contentRaw) {
String[] returns = new String[2];
String beheaded = contentRaw.substring(Config.PREFIX.length());
String[] split = beheaded.split(" ");
returns[0] = split[0];
String commandRemoved = beheaded.replaceAll(split[0] + " ?(.*)", "$1");
returns[1] = commandRemoved;
return returns;
}
}

View file

@ -0,0 +1,128 @@
package com.github.nilstrieb.recommendationbot.core.command;
import com.github.nilstrieb.recommendationbot.core.util.MultiPageEmbed;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import java.util.concurrent.TimeUnit;
/**
* An abstract class for classes that interact with the chat.
* Removes all the boilerplate code associated with sending messages over JDA
*/
public abstract class MessageSender {
protected MessageReceivedEvent event;
/**
* Called by the specific handler.
*
* @param event The MessageReceivedEvent
* @param args The arguments
*/
public void onMessageReceived(MessageReceivedEvent event, String args) {
this.event = event;
called(args);
}
/**
* This method gets called by this object after the MessageReceivedEvent has been saved.
*
* @param args The arguments/text of the sent message
*/
public abstract void called(String args);
/**
* Send a simple String message to the chat the original message came from.
* Equivalent to {@code event.getTextChannel().sendMessage(message).queue();}
* Will not send empty Strings.
*
* @param message The message
*/
protected void reply(String message) {
if (!message.isEmpty()) {
event.getTextChannel().sendMessage(message).queue();
}
}
/**
* Send a simple embed message to the chat original message came from.
* Equivalent to {@code event.getTextChannel().sendMessage(embed).queue();}
* Will not send empty Embeds
*
* @param embed The embed
*/
protected void reply(MessageEmbed embed) {
if (!embed.isEmpty()) {
event.getTextChannel().sendMessage(embed).queue();
}
}
/**
* Send multiple embeds in one message message as a {@code MultiPageEmbed} to the chat original message came from.
* Equivalent to {@code new MultiPageEmbed(event, embeds);}
* Will not send empty Embeds
*
* @param embeds The embeds
*/
protected void reply(MessageEmbed... embeds) {
if (embeds[0].isEmpty()) {
return;
}
if (embeds.length == 1) {
reply(embeds[0]);
} else {
new MultiPageEmbed(event, embeds);
}
}
/**
* Send multiple embeds in one message message as a {@code MultiPageEmbed} to the chat original message came from.
* Equivalent to {@code new MultiPageEmbed(event, embeds);}
* Will not send empty Embeds
*
* @param timeout The timeout in milliseconds
* @param embeds The embeds
*/
protected void reply(long timeout, MessageEmbed... embeds) {
if (!embeds[0].isEmpty()) {
new MultiPageEmbed(event, timeout, embeds);
}
}
/**
* Send multiple embeds in one message message as a {@code MultiPageEmbed} to the chat original message came from.
* Equivalent to {@code new MultiPageEmbed(event, embeds);}
* Will not send empty Embeds
*
* @param embeds The embeds
* @param emote1 The emote for scrolling to the left
* @param emote2 The emote for scrolling to the right
*/
protected void reply(String emote1, String emote2, MessageEmbed... embeds) {
if (!embeds[0].isEmpty()) {
new MultiPageEmbed(event, emote1, emote2, embeds);
}
}
/**
* Delete the original message after a specific delay in s.
*
* @param delay The delay in s
*/
protected void deleteMsg(long delay) {
event.getMessage().delete().queueAfter(delay, TimeUnit.SECONDS);
}
/**
* Delete the original message after a specific delay in ms.
*/
protected void deleteMsg() {
event.getMessage().delete().queue();
}
}

View file

@ -0,0 +1,48 @@
package com.github.nilstrieb.recommendationbot.core.reactions;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent;
/**
* The adapter for the ReactionListener
*/
public abstract class ReactionAdapter implements ReactionListener {
private long message;
/**
* This method has to be called with the message ID
* @param message The message ID
*/
protected void create(long message) {
this.message = message;
ReactionEventManager.addMessage(message, this);
}
/**
* This method can be called to remove the Listener class from the Handlerr
*/
protected void dispose() {
ReactionEventManager.removeMessage(message);
}
/**
* This method gets called from the Handler after a reaction is added to this message
* @param event The event
*/
@Override
public void onReactionAdded(MessageReactionAddEvent event) {
}
/**
* This method gets called from the Handler after a reaction is removed to this message
* @param event The event
*/
@Override
public void onReactionRemoved(MessageReactionRemoveEvent event) {
}
public long getMessage() {
return message;
}
}

View file

@ -0,0 +1,22 @@
package com.github.nilstrieb.recommendationbot.core.reactions;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
public class ReactionEventListener extends ListenerAdapter {
@Override
public void onMessageReactionAdd(@NotNull MessageReactionAddEvent event) {
if (event.getUser() == null || !event.getUser().isBot()) {
ReactionEventManager.onReactionAdd(event);
}
}
@Override
public void onMessageReactionRemove(@NotNull MessageReactionRemoveEvent event) {
if (event.getUser() == null || !event.getUser().isBot()) {
ReactionEventManager.onReactionRemove(event);
}
}
}

View file

@ -0,0 +1,34 @@
package com.github.nilstrieb.recommendationbot.core.reactions;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent;
import java.util.HashMap;
public class ReactionEventManager {
private static final HashMap<Long, ReactionListener> currentReactions = new HashMap<>();
public static void addMessage(long message, ReactionListener listener){
currentReactions.put(message, listener);
}
public static void removeMessage(Long message){
currentReactions.remove(message);
}
public static void onReactionAdd(MessageReactionAddEvent event){
long message = event.getMessageIdLong();
ReactionListener listener = currentReactions.get(message);
if (listener != null) {
listener.onReactionAdded(event);
}
}
public static void onReactionRemove(MessageReactionRemoveEvent event){
long message = event.getMessageIdLong();
ReactionListener listener = currentReactions.get(message);
if (listener != null) {
listener.onReactionRemoved(event);
}
}
}

View file

@ -0,0 +1,9 @@
package com.github.nilstrieb.recommendationbot.core.reactions;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent;
public interface ReactionListener {
void onReactionAdded(MessageReactionAddEvent event);
void onReactionRemoved(MessageReactionRemoveEvent event);
}

View file

@ -0,0 +1,9 @@
package com.github.nilstrieb.recommendationbot.core.sections;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
public interface ChannelListener {
void messageReceived(MessageReceivedEvent event);
long getUserID();
long getChannelID();
}

View file

@ -0,0 +1,58 @@
package com.github.nilstrieb.recommendationbot.core.sections;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import java.util.*;
public class ChannelMessageEventManager {
private static final HashMap<Long, List<ChannelListener>> listeners = new HashMap<>();
private static final List<ChannelListener> removeBuffer = new ArrayList<>();
private static final Set<Long> removedChannels = new HashSet<>();
public static void addListener(ChannelListener listener, long channel) {
if (!listeners.containsKey(channel)) {
listeners.put(channel, new ArrayList<>());
}
listeners.get(channel).add(listener);
}
public static void removeListener(ChannelListener listener) {
if (listeners.containsKey(listener.getChannelID())) {
removeBuffer.add(listener);
}
}
public static void onMessageReceived(MessageReceivedEvent event) {
long id = event.getTextChannel().getIdLong();
//if the message is relevant
if (listeners.containsKey(id)) {
//notify all listeners
List<ChannelListener> list = listeners.get(id);
for (ChannelListener channelListener : list) {
if (channelListener.getUserID() == 0) {
channelListener.messageReceived(event);
} else if (channelListener.getUserID() == event.getAuthor().getIdLong()) {
channelListener.messageReceived(event);
}
}
//remove the listeners that got removed during the calling
for (ChannelListener channelListener : removeBuffer) {
listeners.get(channelListener.getChannelID()).remove(channelListener);
removedChannels.add(channelListener.getChannelID());
}
//remove the channels if all listeners for that channel have been removed
for (Long removedChannel : removedChannels) {
list = listeners.get(removedChannel);
if (list.isEmpty()) {
listeners.remove(removedChannel);
}
}
//clear the buffers
removedChannels.clear();
removeBuffer.clear();
}
}
}

View file

@ -0,0 +1,14 @@
package com.github.nilstrieb.recommendationbot.core.sections;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
public class ChannelMessageListener extends ListenerAdapter {
@Override
public void onMessageReceived(@NotNull MessageReceivedEvent event) {
if (!event.getAuthor().isBot() && event.isFromGuild()) {
ChannelMessageEventManager.onMessageReceived(event);
}
}
}

View file

@ -0,0 +1,74 @@
package com.github.nilstrieb.recommendationbot.core.sections;
import com.github.nilstrieb.recommendationbot.core.command.MessageSender;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import java.util.Timer;
import java.util.TimerTask;
/**
* The section class can be extended to create sections where the user is asked to write multiple messages
*/
public abstract class Section extends MessageSender implements ChannelListener {
private final long textChannelID;
private final long userID;
/**
* Create a new section for a specific user
*
* @param textChannelID The channel ID
* @param userID The user ID
*/
public Section(long textChannelID, long userID) {
this.textChannelID = textChannelID;
this.userID = userID;
ChannelMessageEventManager.addListener(this, textChannelID);
}
/**
* Create a new section for all users in a channel
*
* @param textChannelID The channel ID
*/
public Section(long textChannelID) {
this.textChannelID = textChannelID;
this.userID = 0;
}
@Override
public void messageReceived(MessageReceivedEvent event) {
this.event = event;
called(event.getMessage().getContentRaw());
}
/**
* End the section.
*/
protected void dispose() {
ChannelMessageEventManager.removeListener(this);
}
@Override
public long getUserID() {
return userID;
}
@Override
public long getChannelID() {
return textChannelID;
}
protected void setSectionTimeout(long timeout) {
//SECTION TIMEOUT
//is safe because listeners can be removed multiple times
final Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
dispose();
t.cancel();
}
}, timeout);
}
}

View file

@ -0,0 +1,91 @@
package com.github.nilstrieb.recommendationbot.core.util;
import com.github.nilstrieb.recommendationbot.core.reactions.ReactionAdapter;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import java.util.Timer;
import java.util.TimerTask;
/**
* This class sends a message to the channel in the event that contains multiple pages that can be navigated using reactinos
*/
public class MultiPageEmbed extends ReactionAdapter {
private static final String NEXT_PAGE_DEFAULT_REACTION = "\u25b6\ufe0f";
private static final String PREVIOUS_PAGE_DEFAULT_REACTION = "\u25c0\ufe0f";
private Message message;
private final MessageEmbed[] pages;
private int currentState;
private final String prevReaction;
private final String nextReaction;
/**
* Create a new MultiPageEmbed with the default emotes
*
* @param event The event
* @param pages The pages
*/
public MultiPageEmbed(MessageReceivedEvent event, MessageEmbed... pages) {
this(event, PREVIOUS_PAGE_DEFAULT_REACTION, NEXT_PAGE_DEFAULT_REACTION, pages);
}
/**
* Create a new MultiPageEmbed with custom emotes
*
* @param event The event
* @param pages The pages
*/
public MultiPageEmbed(MessageReceivedEvent event, String prevReaction, String nextReaction, MessageEmbed[] pages) {
this.prevReaction = prevReaction;
this.nextReaction = nextReaction;
this.pages = pages;
event.getTextChannel().sendMessage(pages[0]).queue(message1 -> {
message = message1;
message.addReaction(prevReaction).queue();
message.addReaction(nextReaction).queue();
create(message1.getIdLong());
});
}
public MultiPageEmbed(MessageReceivedEvent event, long timeout, MessageEmbed[] pages) {
this(event, PREVIOUS_PAGE_DEFAULT_REACTION, NEXT_PAGE_DEFAULT_REACTION, pages);
//MPE TIMEOUT
//is safe because listeners can be removed multiple times
final Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
dispose();
t.cancel();
}
}, timeout);
}
@Override
public void onReactionAdded(MessageReactionAddEvent event) {
String name = event.getReaction().getReactionEmote().getName();
if (name.equals(nextReaction)) {
if (currentState + 1 < pages.length) {
currentState++;
if (!pages[currentState].isEmpty()) {
message.editMessage(pages[currentState]).queue();
}
}
} else if (name.equals(prevReaction)) {
if (currentState > 0) {
currentState--;
if (!pages[currentState].isEmpty()) {
message.editMessage(pages[currentState]).queue();
}
}
}
if (event.getUser() != null) {
event.getReaction().removeReaction(event.getUser()).queue();
}
}
}

View file

@ -0,0 +1,75 @@
package com.github.nilstrieb.recommendationbot.db;
import org.neo4j.driver.*;
import static org.neo4j.driver.Values.parameters;
public class Neo4jConnection implements AutoCloseable {
private static Neo4jConnection connection;
private final Driver driver;
public static void create(String uri, String user, String password) {
connection = new Neo4jConnection(uri, user, password);
}
private Neo4jConnection(String uri, String user, String password) {
driver = GraphDatabase.driver(uri, AuthTokens.basic(user, password));
}
@Override
public void close() throws Exception {
driver.close();
}
public void createRecommendation(String uid, String name) {
try (Session session = driver.session()) {
session.writeTransaction(tx -> {
tx.run("""
MERGE (u:User {id:$uid})
MERGE (t:Thing {name:$name})
CREATE (u) - [:LIKES] -> (t)
""",
parameters("uid", uid, "name", name));
return 0;
});
}
System.out.println("inserted :LIKES");
}
public void createSub(String uid, String targetId) {
try (Session session = driver.session()) {
session.writeTransaction(tx -> {
tx.run("""
MERGE (u:User {id:$uid})
MERGE (t:User {id:$target})
CREATE (u) - [:SUBS_TO] -> (t)
""",
parameters("uid", uid, "target", targetId));
return 0;
});
}
System.out.println("inserted :SUBS_TO");
}
public boolean isSubbed(String uid, String targetId) {
return false;
}
public void printGreeting(String message) {
try (Session session = driver.session()) {
String greeting = session.writeTransaction(tx -> {
Result result = tx.run("CREATE (a:Greeting) " +
"SET a.message = $message " +
"RETURN a.message + ', from node ' + id(a)",
parameters("message", message));
return result.single().get(0).asString();
});
}
}
public static Neo4jConnection getInstance() {
return connection;
}
}

View file

@ -0,0 +1,12 @@
package com.github.nilstrieb.recommendationbot.listeners;
import net.dv8tion.jda.api.events.ReadyEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
public class StartUpListener extends ListenerAdapter {
@Override
public void onReady(@NotNull ReadyEvent event) {
System.out.println("[Startup] Bot started");
}
}