pingex
/
DiscordBot
Archived
1
0
Fork 0

Modules foundation + loader

Also added missing documentation
master
Pingex aka Raphaël 9 years ago
parent 9a6a7946f7
commit e5fb48cb6a

@ -4,4 +4,9 @@
isBot = false
email = bot@example.com
password = samplePassword
; token = sampleToken
; token = sampleToken
[plugins]
; Comma-separated list of modules to load
; enable = net.pingex.discordbot.HelloWorldModule, net.pingex.discordbot.AnothaModule, fr.w4rell.discordbot.ThemeSombreModule
enable = net.pingex.discordbot.HelloWorldModule

@ -0,0 +1,32 @@
package net.pingex.discordbot;
import sx.blah.discord.api.IDiscordClient;
import java.util.ArrayList;
import java.util.logging.Logger;
/**
* Defines a basic bot module
* @version 0.1-dev
* @author Raphael "Pingex" NAAS
*/
public abstract class AbstractModule
{
/**
* Contains all `AbstractModule` instances created.
*/
private static final ArrayList<AbstractModule> REGISTERED = new ArrayList<>();
protected Logger logger;
/**
* Constructor doing all the basic stuff, like registering as a Listener to Discord, getting a logger, etc.
* @param client Discord Client instance used to register self.
*/
public AbstractModule(IDiscordClient client)
{
REGISTERED.add(this);
client.getDispatcher().registerListener(this);
logger = Logger.getLogger(this.getClass().getName());
logger.info("Loading module " + this.getClass().getName());
}
}

@ -94,6 +94,6 @@ public final class Configuration
*/
public static boolean exists(String section, String key)
{
return (datastore.get(section, key) != null) ? true : false;
return (datastore.get(section, key) != null);
}
}

@ -1,12 +1,12 @@
package net.pingex.discordbot;
import sx.blah.discord.api.ClientBuilder;
import sx.blah.discord.api.Event;
import sx.blah.discord.api.IDiscordClient;
import sx.blah.discord.api.IListener;
import sx.blah.discord.handle.impl.events.ReadyEvent;
import sx.blah.discord.util.DiscordException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Logger;
/**
@ -17,15 +17,61 @@ import java.util.logging.Logger;
public class DiscordBot
{
private static final Logger LOGGER = Logger.getLogger(DiscordBot.class.getName());
/**
* Discord Client instance
*/
private IDiscordClient client;
public DiscordBot(IDiscordClient client)
/**
* Constructor of the singleton
* @param client Discord client instance used to Bootstrap the whole program
*/
private DiscordBot(IDiscordClient client)
{
this.client = client;
LOGGER.info("Successfully logged in !");
this.client.getDispatcher().registerListener((IListener<ReadyEvent>) event ->
LOGGER.info("Logged in as \"" + event.getClient().getOurUser().getName() + "#" + event.getClient().getOurUser().getDiscriminator() + "\" (#" + event.getClient().getOurUser().getID() + ")"));
enableModules();
}
private void enableModules()
{
LOGGER.info("Enabling modules");
if(!Configuration.exists("plugins", "enable") || Configuration.getValue("plugins", "enable").isEmpty())
{
LOGGER.warning("Key \"plugins/enable\" doesn't exist in Configuration. No module will be enabled.");
return;
}
for(String i : Configuration.getValue("plugins", "enable").split(","))
{
i = i.trim();
try
{
Class<?> clazz = Class.forName(i);
if(!AbstractModule.class.isAssignableFrom(clazz))
throw new InvalidModuleException(i + " isn't a valid module.");
clazz.getConstructor(IDiscordClient.class).newInstance(client);
} catch (ClassNotFoundException e)
{
LOGGER.warning("Class " + i + " wasn't found, thus won't be loaded.");
} catch (InvalidModuleException e)
{
LOGGER.warning(e.getMessage());
} catch (NoSuchMethodException e)
{
LOGGER.warning("No valid Constructor for " + i + " was found.");
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e)
{
LOGGER.warning("An error occured while creating an instance of " + i);
e.printStackTrace();
}
}
}
// ====================================================
@ -43,7 +89,7 @@ public class DiscordBot
// LOAD CONFIGURATION
try
{
Configuration.loadConfiguration("config.ini");
Configuration.loadConfiguration("config.ini"); // TODO: pass configuration file using commandline argument
} catch (IOException e)
{
LOGGER.severe("Could not load Configuration, reason: " + e.getMessage());
@ -65,6 +111,12 @@ public class DiscordBot
}
}
/**
* Discord login subroutine. Called by `main()` once
* @return Instance of DiscordBot if login was successful
* @throws ConfigurationException When token/email/password field in config.ini isn't filled
* @throws DiscordException
*/
private static DiscordBot loginToDiscord() throws ConfigurationException, DiscordException
{
ClientBuilder builder = new ClientBuilder();

@ -0,0 +1,28 @@
package net.pingex.discordbot;
import sx.blah.discord.api.EventSubscriber;
import sx.blah.discord.api.IDiscordClient;
import sx.blah.discord.handle.impl.events.ReadyEvent;
/**
* Very first Discord module, written for testing purposes
* @version 0.1-dev
* @author Raphael "Pingex" NAAS
*/
public class HelloWorldModule extends AbstractModule
{
/**
* Constructor doing all the basic stuff, like registering as a Listener to Discord, getting a logger, etc.
* @param client Discord Client instance used to register self.
*/
public HelloWorldModule(IDiscordClient client)
{
super(client);
}
@EventSubscriber
public void onReadyEvent(ReadyEvent event)
{
logger.info("READY");
}
}

@ -0,0 +1,24 @@
package net.pingex.discordbot;
import java.util.Hashtable;
/**
* Implemented by modules which can be controlled using Discord Commands
* @version 0.1-dev
* @author Raphael "Pingex" NAAS
*/
public interface IControllable
{
/**
* A list of prefixes the module uses to identify itself.
* @return List of prefixes
*/
String[] getPrefixes();
/**
* Get a list of shortened commands.
* Example: command !module:myCommand can be shortened as !myc, !mc, or !myco, so the table would be like "myCommand" => ["myc", "mc", "myco"]
* @return Hastable containing all shortened commands. Key is the real command, Value is a list of eligible short commands.
*/
Hashtable<String, String[]> getShorthands();
}

@ -0,0 +1,34 @@
package net.pingex.discordbot;
/**
* Exception thrown when trying to load a module which isn't one.
* @version 0.1-dev
* @author Raphael "Pingex" NAAS
*/
public class InvalidModuleException extends Exception
{
public InvalidModuleException(String message)
{
super(message);
}
protected InvalidModuleException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
{
super(message, cause, enableSuppression, writableStackTrace);
}
public InvalidModuleException(Throwable cause)
{
super(cause);
}
public InvalidModuleException(String message, Throwable cause)
{
super(message, cause);
}
public InvalidModuleException()
{
super();
}
}