Initial Commit

This commit is contained in:
Malcom Green
2017-05-23 13:19:15 -04:00
commit e0a5379ecf
94 changed files with 3394 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
package me.savvy.rixa;
import me.savvy.rixa.commands.general.HelpCommand;
import me.savvy.rixa.commands.general.InfoCommand;
import me.savvy.rixa.commands.general.ServerInfoCommand;
import me.savvy.rixa.commands.handlers.CommandHandler;
import me.savvy.rixa.events.MessageEvent;
import me.savvy.rixa.modules.reactions.handlers.ReactionManager;
import me.savvy.rixa.modules.reactions.react.HelpReaction;
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.OnlineStatus;
import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.exceptions.RateLimitedException;
import net.dv8tion.jda.core.hooks.AnnotatedEventManager;
import javax.security.auth.login.LoginException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
/**
* Created by Timber on 5/7/2017.
*/
public class Rixa {
private static List<JDA> shardsList;
private static long timeUp;
private static Rixa instance; // String search = event.getMessage().getContent().substring(event.getMessage().getContent().indexOf(" ") + 1);
public static void main(String[] args) throws LoginException, InterruptedException, RateLimitedException {
instance = new Rixa();
shardsList = new LinkedList<>();
int shards = 4;
for(int i = 1; i < shards; i++){
Logger.getLogger("Rixa").info("Loading shard #" + i);
JDABuilder jda = new JDABuilder(AccountType.BOT)
.setToken("MjkxNTM5Njg2NTEyNTI1MzMy.C6r1OA.-hRemXk-b3nP5GvT9kjh2V7RXDo")
.setEventManager(new AnnotatedEventManager())
.addEventListener(new MessageEvent())
.setGame(Game.of("Rixa 1.0 | In Dev", "http://rixa.io"))
.setAutoReconnect(true)
.setStatus(OnlineStatus.ONLINE)
.setAudioEnabled(true)
.useSharding(i, shards);
shardsList.add(jda.buildBlocking());
Logger.getLogger("Rixa").info("Shard #" + i + " has been loaded");
}
timeUp = System.currentTimeMillis();
CommandHandler.registerCommand(new InfoCommand());
CommandHandler.registerCommand(new ServerInfoCommand());
CommandHandler.registerCommand(new HelpCommand());
ReactionManager.registerReaction(new HelpReaction());
}
public static Rixa getInstance() {
return instance;
}
public long getTimeUp() {
return timeUp;
}
}

View File

@@ -0,0 +1,46 @@
package me.savvy.rixa.commands.general;
import me.savvy.rixa.commands.handlers.Command;
import me.savvy.rixa.commands.handlers.CommandExec;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.entities.ChannelType;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.core.exceptions.ErrorResponseException;
import net.dv8tion.jda.core.exceptions.PermissionException;
/**
* Created by Timber on 5/7/2017.
*/
public class HelpCommand implements CommandExec {
@Command(usage = "%phelp",
channelType = ChannelType.TEXT,
description = "Receive information about the server!",
aliases = "", mainCommand = "help")
public void execute(GuildMessageReceivedEvent event) {
try {
event.getMessage().delete().complete();
} catch (PermissionException ignored) {}
EmbedBuilder embedBuilder = new EmbedBuilder();
String stringBuilder = "\u2753" +
" **Help**" +
"\n" +
"Click the corresponding number for more information about the command menu.";
embedBuilder.setTitle("Help", "http://rixa.io")
.setDescription(stringBuilder)
.addField("1 - General Commands", "Reveals usable commands intended for `everyone`", false)
.addField("2 - Staff Commands", "Reveals usable commands intended for `staff` use only", false)
.addField("3 - Music Commands", "Reveals usable commands to configure Rixa for your discord!", false)
.setColor(event.getMember().getColor());
Message message = event.getAuthor().openPrivateChannel().complete().sendMessage(embedBuilder.build()).complete();
event.getChannel().sendMessage(event.getMember().getAsMention()
+ ", the help menu has been private messaged to you!").queue();
try {
message.addReaction("\u0031\u20E3").queue();
message.addReaction("\u0032\u20E3").queue();
message.addReaction("\u0033\u20E3").queue();
message.addReaction("\uD83D\uDDD1").queue();
} catch (ErrorResponseException ignored) {}
}
}

View File

@@ -0,0 +1,52 @@
package me.savvy.rixa.commands.general;
import me.savvy.rixa.Rixa;
import com.lunaticdev.rixa.commands.handler.CommandType;
import me.savvy.rixa.commands.handlers.Command;
import me.savvy.rixa.commands.handlers.CommandExec;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.entities.ChannelType;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* Created by Timber on 5/7/2017.
*/
public class InfoCommand implements CommandExec {
@Command(aliases = {""},
description = "Receive information about Rixa",
type = CommandType.USER,
channelType = ChannelType.TEXT,
usage = "%pinfo", mainCommand = "info")
public void execute(GuildMessageReceivedEvent event) {
EmbedBuilder messageEmbed = new EmbedBuilder();
User botOwner = event.getJDA().getUserById("202944101333729280");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
Date date1 = new Date(Rixa.getInstance().getTimeUp());
Date date2 = new Date();
long difference = date2.getTime() - date1.getTime();
long seconds = difference / 1000;
int day = (int)TimeUnit.SECONDS.toDays(seconds);
long hours = TimeUnit.SECONDS.toHours(seconds) - (day *24);
long minute = TimeUnit.SECONDS.toMinutes(seconds) - (TimeUnit.SECONDS.toHours(seconds)* 60);
long second = TimeUnit.SECONDS.toSeconds(seconds) - (TimeUnit.SECONDS.toMinutes(seconds) *60);
messageEmbed
.setTitle("Rixa Discord Bot", "http://rixa.io/")
.setDescription("Rixa is a user-friendly, multi-purpose bot that is capable of being customized to your discord server needs. " +
"Rixa is complete with a dashboard, user profile, server statistics system, and many more features such as assigning " +
"roles on user join, music module, levels, and more. Rixa was created to bring ease and simplicity to managing discord" +
" servers, it has since then grown into much more than just a bot used for moderation.")
.addField("Created", event.getJDA().getSelfUser().getCreationTime().format(formatter), true)
.addField("Bot Uptime ", "Online For: " + day + " days " + hours + " hours " + minute + " minutes " + second + " seconds.", true)
.addField("Total Guilds", event.getJDA().getGuilds().size() + "", true)
.addField("Total Users", event.getJDA().getUsers().size() + "", true)
.addField("Rixa Developer", botOwner.getName() + "#" + botOwner.getDiscriminator(), true)
.setFooter("Requested by " + event.getAuthor().getName() + "#" + event.getAuthor().getDiscriminator(), event.getAuthor().getAvatarUrl());
event.getChannel().sendMessage(messageEmbed.build()).queue();
}
}

View File

@@ -0,0 +1,39 @@
package me.savvy.rixa.commands.general;
import me.savvy.rixa.commands.handlers.Command;
import me.savvy.rixa.commands.handlers.CommandExec;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.entities.ChannelType;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import java.time.format.DateTimeFormatter;
/**
* Created by Timber on 5/7/2017.
*/
public class ServerInfoCommand implements CommandExec {
@Command(usage = "%pserverinfo",
channelType = ChannelType.TEXT,
description = "Receive information about the server!",
aliases = "sinfo", mainCommand = "serverinfo")
public void execute(GuildMessageReceivedEvent event) {
EmbedBuilder messageEmbed = new EmbedBuilder();
User owner = event.getGuild().getOwner().getUser();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
messageEmbed
.setTitle(event.getGuild().getName(), "http://rixa.io/servers/" + event.getGuild().getId())
.setDescription("Description")
.addField("Created", event.getGuild().getCreationTime().format(formatter), true)
.addField("Region", event.getGuild().getRegion().toString(), true)
.addField("Users", String.valueOf(event.getGuild().getMembers().size()), true)
.addField("Text Channels", String.valueOf(event.getGuild().getTextChannels().size()), true)
.addField("Voice Channels", String.valueOf(event.getGuild().getVoiceChannels().size()), true)
.addField("Roles", String.valueOf(event.getGuild().getRoles().size()), true)
.addField("Owner", owner.getName() + "#" + owner.getDiscriminator(), true)
.setThumbnail(event.getGuild().getIconUrl())
.setFooter("ServerID: " + event.getGuild().getId(), event.getGuild().getIconUrl());
event.getChannel().sendMessage(messageEmbed.build()).queue();
}
}

View File

@@ -0,0 +1,30 @@
package me.savvy.rixa.commands.handlers;
import net.dv8tion.jda.core.entities.ChannelType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by Timber on 5/7/2017.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Command {
String mainCommand();
String[] aliases();
String description() default "";
String usage() default "";
CommandType type() default CommandType.USER;
boolean showInHelp() default true;
ChannelType channelType() default ChannelType.PRIVATE;
}

View File

@@ -0,0 +1,11 @@
package me.savvy.rixa.commands.handlers;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
/**
* Created by Timber on 5/7/2017.
*/
public interface CommandExec {
public void execute(GuildMessageReceivedEvent event);
}

View File

@@ -0,0 +1,52 @@
package me.savvy.rixa.commands.handlers;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Timber on 5/7/2017.
*/
public class CommandHandler {
private static final Map<String, CommandRegistrar> commands = new HashMap<>();
public static void registerCommand(CommandExec command) {
for (Method method : command.getClass().getMethods()) {
Command annotation = method.getAnnotation(Command.class);
if (annotation == null) continue;
CommandRegistrar cmd = new CommandRegistrar(annotation, method, command);
commands.put(annotation.mainCommand(), cmd);
}
}
public static boolean hasCommand(String s) {
if(getCommands().containsKey(s)) {
return true;
} else {
for (CommandRegistrar commandRegistrar : getCommands().values()) {
for (String string : commandRegistrar.getCommandAnnotation().aliases()) {
if (string.equalsIgnoreCase(s)) return true;
}
}
return false;
}
}
public static CommandRegistrar get(String s) {
if(getCommands().containsKey(s)) {
return getCommands().get(s);
} else {
for (CommandRegistrar commandRegistrar : getCommands().values()) {
for (String string : commandRegistrar.getCommandAnnotation().aliases()) {
if (string.equalsIgnoreCase(s)) return commandRegistrar;
}
}
return null;
}
}
public static Map<String, CommandRegistrar> getCommands() {
return commands;
}
}

View File

@@ -0,0 +1,31 @@
package me.savvy.rixa.commands.handlers;
import java.lang.reflect.Method;
/**
* Created by Timber on 5/7/2017.
*/
public class CommandRegistrar {
private final Command annotation;
private final Method method;
private final CommandExec executor;
CommandRegistrar(Command annotation, Method method, CommandExec executor) {
this.annotation = annotation;
this.method = method;
this.executor = executor;
}
public Command getCommandAnnotation() {
return annotation;
}
public Method getMethod() {
return method;
}
public CommandExec getExecutor() {
return executor;
}
}

View File

@@ -0,0 +1,8 @@
package me.savvy.rixa.commands.handlers;
/**
* Created by Timber on 5/22/2017.
*/
public enum CommandType {
USER, MOD, ADMIN, BOT_OWNER;
}

View File

@@ -0,0 +1,57 @@
package me.savvy.rixa.events;
import com.mysql.jdbc.StringUtils;
import me.savvy.rixa.commands.handlers.CommandHandler;
import me.savvy.rixa.commands.handlers.CommandRegistrar;
import me.savvy.rixa.modules.reactions.handlers.ReactRegistrar;
import me.savvy.rixa.modules.reactions.handlers.ReactionManager;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.MessageEmbed;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.core.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.core.hooks.SubscribeEvent;
import java.lang.reflect.Method;
/**
* Created by Timber on 5/7/2017.
*/
public class MessageEvent {
@SubscribeEvent
public void handle(GuildMessageReceivedEvent event) {
if (event.getGuild() == null) return;
String prefix = "/";
if (!event.getMessage().getContent().startsWith(prefix)) return;
// Map<String, CommandRegistrar> commands = CommandHandler.getCommands();
String[] splitContent = event.getMessage().getContent().replace(prefix, "").split(" ");
if(!CommandHandler.hasCommand(splitContent[0])) { return; }
//if (!commands.containsKey(splitContent[0])) return;
CommandRegistrar cmd = CommandHandler.get(splitContent[0]);
//CommandRegistrar cmd = commands.get(splitContent[0]);
Method m = cmd.getMethod();
try {
m.invoke(cmd.getExecutor(), event);
} catch (Exception e) {
e.printStackTrace();
}
}
@SubscribeEvent
public void onReact(MessageReactionAddEvent event) {
Message message = event.getChannel().getMessageById(event.getMessageId()).complete();
if(message == null || message.getEmbeds().size() != 1) return;
MessageEmbed embed = message.getEmbeds().get(0);
if(StringUtils.isNullOrEmpty(embed.getTitle())) return;
String[] titleSplit = embed.getTitle().split(": ");
if(ReactionManager.getReactions().containsKey(titleSplit[0])) {
ReactRegistrar reactRegistrar = ReactionManager.getReactions().get(titleSplit[0]);
Method m = reactRegistrar.getMethod();
try {
m.invoke(reactRegistrar.getExecutor(), event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,11 @@
package me.savvy.rixa.modules;
/**
* Created by Timber on 5/23/2017.
*/
public interface RixaModule {
String getName();
String getDescription();
}

View File

@@ -0,0 +1,18 @@
package me.savvy.rixa.modules.levels;
import me.savvy.rixa.modules.RixaModule;
/**
* Created by Timber on 5/23/2017.
*/
public class LevelsModule implements RixaModule {
@Override
public String getName() {
return "Levels";
}
@Override
public String getDescription() {
return "";
}
}

View File

@@ -0,0 +1,18 @@
package me.savvy.rixa.modules.music;
import me.savvy.rixa.modules.RixaModule;
/**
* Created by Timber on 5/23/2017.
*/
public class MusicModule implements RixaModule {
@Override
public String getName() {
return "Music";
}
@Override
public String getDescription() {
return "";
}
}

View File

@@ -0,0 +1,7 @@
package me.savvy.rixa.modules.reactions;
/**
* Created by Timber on 5/23/2017.
*/
public class ReactionModule {
}

View File

@@ -0,0 +1,11 @@
package me.savvy.rixa.modules.reactions.handlers;
import net.dv8tion.jda.core.events.message.react.MessageReactionAddEvent;
/**
* Created by Timber on 5/7/2017.
*/
public interface React {
public void reactionTrigger(MessageReactionAddEvent event);
}

View File

@@ -0,0 +1,18 @@
package me.savvy.rixa.modules.reactions.handlers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by Timber on 5/7/2017.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ReactHandle {
String title() default "";
String description() default "";
}

View File

@@ -0,0 +1,31 @@
package me.savvy.rixa.modules.reactions.handlers;
import java.lang.reflect.Method;
/**
* Created by Timber on 5/7/2017.
*/
public class ReactRegistrar {
private final ReactHandle annotation;
private final Method method;
private final React executor;
ReactRegistrar(ReactHandle annotation, Method method, React executor) {
this.annotation = annotation;
this.method = method;
this.executor = executor;
}
public ReactHandle getReactAnnotation() {
return annotation;
}
public Method getMethod() {
return method;
}
public React getExecutor() {
return executor;
}
}

View File

@@ -0,0 +1,26 @@
package me.savvy.rixa.modules.reactions.handlers;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Timber on 5/7/2017.
*/
public class ReactionManager {
private static final Map<String, ReactRegistrar> reactions = new HashMap<>();
public static void registerReaction(React react) {
for (Method method : react.getClass().getMethods()) {
ReactHandle annotation = method.getAnnotation(ReactHandle.class);
if (annotation == null) continue;
ReactRegistrar ant = new ReactRegistrar(annotation, method, react);
reactions.put(annotation.title(), ant);
}
}
public static Map<String, ReactRegistrar> getReactions() {
return reactions;
}
}

View File

@@ -0,0 +1,89 @@
package me.savvy.rixa.modules.reactions.react;
import com.lunaticdev.rixa.commands.handler.CommandHandler;
import com.lunaticdev.rixa.commands.handler.CommandType;
import me.savvy.rixa.modules.reactions.handlers.React;
import me.savvy.rixa.modules.reactions.handlers.ReactHandle;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.entities.ChannelType;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.core.exceptions.ErrorResponseException;
/**
* Created by Timber on 5/21/2017.
*/
public class HelpReaction implements React {
@Override
@ReactHandle(title = "Help", description = "Help menu for Rixa")
public void reactionTrigger(MessageReactionAddEvent event) {
if(event.getChannel().getType() != ChannelType.PRIVATE
|| event.getUser().getId().equalsIgnoreCase(event.getJDA().getSelfUser().getId())) {
return;
}
Message message = event.getChannel().getMessageById(event.getMessageId()).complete();
EmbedBuilder embedBuilder;
try {
switch(event.getReaction().getEmote().getName()) {
case "\uD83D\uDDD1":// waste bin
if (message.getAuthor().getId().equalsIgnoreCase(event.getJDA().getSelfUser().getId())) {
message.delete().complete();
}
break;
case "\u0031\u20E3":// one emoji
embedBuilder = new EmbedBuilder();
String stringBuilder = "\u2753" +
" **General Commands Help**" +
"\n" +
"Click a number below for information about other commands.";
embedBuilder.setTitle("Help", "http://rixa.io");
embedBuilder.setDescription(stringBuilder);
CommandHandler.getCommands().values().stream().filter(cmd -> cmd.getType() == CommandType.USER)
.forEach(cmd -> embedBuilder.addField("/"/*prefix*/ + cmd.getPrefix(), cmd.getDescription(), false));
message.editMessage(embedBuilder.build()).queue();// = event.getChannel().sendMessage(embedBuilder.build()).complete();
break;
case "\u0032\u20E3": // two emoji
embedBuilder = new EmbedBuilder();
stringBuilder = "\u2753" +
" **Staff Commands Help**" +
"\n" +
"Click a number below for information about other commands.";
embedBuilder.setTitle("Help", "http://rixa.io");
embedBuilder.setDescription(stringBuilder);
CommandHandler.getCommands().values().stream().filter(cmd -> cmd.getType() == CommandType.ADMIN || cmd.getType() == CommandType.MOD)
.forEach(cmd -> embedBuilder.addField("/"/*prefix*/ + cmd.getPrefix(), cmd.getDescription(), false));
message.editMessage(embedBuilder.build()).queue();
break;
case "\u0033\u20E3": // three emoji
embedBuilder = new EmbedBuilder();
stringBuilder = "\u2753" +
" **Music Commands Help**" +
"\n" +
"Click a number below for information about other commands.";
embedBuilder.setTitle("Help", "http://rixa.io");
embedBuilder.setDescription(stringBuilder);
String prefix = "/";
embedBuilder.addField(prefix + "music join [name]", "Joins a voice channel that has the provided name", false)
.addField(prefix + "music join [id]", "Joins a voice channel based on the provided id.", false)
.addField(prefix + "music leave", "Leaves the voice channel that the bot is currently in.", false)
.addField(prefix + "music play", "Plays songs from the current queue. Starts playing again if it was previously paused", false)
.addField(prefix + "music play [url]", "Adds a new song to the queue and starts playing if it wasn't playing already", false)
.addField(prefix + "music pplay", "Adds a playlist to the queue and starts playing if not already playing", false)
.addField(prefix + "music pause", "Pauses audio playback", false)
.addField(prefix + "music stop", "Completely stops audio playback, skipping the current song.", false)
.addField(prefix + "music skip", "Skips the current song, automatically starting the next", false)
.addField(prefix + "music nowplaying", "Prints information about the currently playing song (title, current time)", false)
.addField(prefix + "music np", "Alias for nowplaying", false)
.addField(prefix + "music list", "Lists the songs in the queue", false)
.addField(prefix + "music volume [vol]", "Sets the volume of the MusicPlayer [10 - 100]", false)
.addField(prefix + "music restart", "Restarts the current song or restarts the previous song if there is no current song playing.", false)
.addField(prefix + "music repeat", "Makes the player repeat the currently playing song", false)
.addField(prefix + "music reset", "Completely resets the player, fixing all errors and clearing the queue.", false);
message.editMessage(embedBuilder.build()).queue();
break;
}
} catch (ErrorResponseException ignored) {
}
}
}

View File

@@ -0,0 +1,18 @@
package me.savvy.rixa.modules.reactions.react;
import me.savvy.rixa.modules.reactions.handlers.React;
import me.savvy.rixa.modules.reactions.handlers.ReactHandle;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.events.message.react.MessageReactionAddEvent;
/**
* Created by Timber on 5/7/2017.
*/
public class PollReaction implements React {
@Override
@ReactHandle(title = "Poll", description = "Host polls right from your discord server!")
public void reactionTrigger(MessageReactionAddEvent event) {
Message message = event.getChannel().getMessageById(event.getMessageId()).complete();
}
}