Merge branch 'feature/plugins' into develop

This commit is contained in:
Matthew Cech
2019-04-20 02:09:25 -07:00
11 changed files with 205 additions and 24 deletions
+1
View File
@@ -13,5 +13,6 @@
<classpathentry kind="lib" path="lib/slf4j-jdk14-1.7.25.jar"/>
<classpathentry kind="lib" path="lib/twitter4j-core-4.0.7-javadoc.jar"/>
<classpathentry kind="lib" path="lib/twitter4j-core-4.0.7.jar"/>
<classpathentry kind="lib" path="lib/luaj-jse-3.0.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
Binary file not shown.
+13 -13
View File
@@ -16,7 +16,7 @@ RollInfo=Based on input of xdy where x is number of dice and y is faces kitty wi
[CommandGuildRoleAllowed]
GuildRoleAllowedInfo=
GuildRoleAllowedSuccess=Added %s to the allowed roles!
GuildRoleAllowedDuplicate=Can't add the same role twice!
GuildRoleAllowedDuplicate=Can't add the same role twice!
[CommandStats]
StatsInfo=Displays the actively running KittyBot application information
@@ -26,7 +26,7 @@ TweetInfo=Kitty will tweet to her personal twitter account
TweetError=Tweet command failed!
[CommandGuildRoleAdd]
GuildRoleAddSuccess=Added %s to %s
GuildRoleAddSuccess=Added %s to %s
GuildRoleAddFailure=Failed to add %s to %s
GuildRoleAddNotAllowed=You are not allowed to add %s!
GuildRoleAddInfo=Add a role to yourself!
@@ -133,14 +133,14 @@ BoopStandard=Woah! %s booped me! That's %s total!
BoopMultiple=%s booped several others - %s!
[CommandFetch]
FetchError=That no picture!
FetchEat=Me eat now *monch %s*
FetchError=That no picture!
FetchEat=Me eat now *monch %s*
FetchInfo=Throw a custom emote and me bring it back!
FetchCatchRun=*Catches and runs away with %s*
FetchRunAway=*Runs away and doesn't return for a long time*
FetchBringBack=Me gots it! %s
FetchBringBackWrong=Me gots it! %s
FetchStare=*Stares at %s*
FetchCatchRun=*Catches and runs away with %s*
FetchRunAway=*Runs away and doesn't return for a long time*
FetchBringBack=Me gots it! %s
FetchBringBackWrong=Me gots it! %s
FetchStare=*Stares at %s*
[CommandInfo]
InfoResponse=I'm made by `Rin#8904` and `Reverie Wisp#3703`!\nYou can find more info about me along with a Patreon link to support us and GitHub link for filing bugs https://www.rinsnowmew.com/bot/
@@ -183,10 +183,10 @@ EightBallYes10=Signs point to yes.
InviteInfo=Provides a direct invite link for KittyBot
[CommandGuildRoleRemove]
GuildRoleRemoveNotAllowed=You're not allowed to add %s
GuildRoleRemoveFailure=Couldn't remove %s from %s
GuildRoleRemoveSuccess=Removed %s from %s!
GuildRoleRemoveInfo=
GuildRoleRemoveNotAllowed=You're not allowed to add %s
GuildRoleRemoveFailure=Couldn't remove %s from %s
GuildRoleRemoveSuccess=Removed %s from %s!
GuildRoleRemoveInfo=
[CommandWolfram]
WolframError=Something went wrong!
+6
View File
@@ -0,0 +1,6 @@
-- Example plugin stub. This function is called and passed the input message.
-- If nil is returned, the plugin is considered to have not run, but if any
-- other value is returned, it's interpreted as a string and sent back to the user.
function plugin(message)
return nil;
end
+14
View File
@@ -6,6 +6,7 @@ import java.util.List;
import java.util.concurrent.Semaphore;
import commands.*;
import core.lua.PluginManager;
import dataStructures.*;
import net.dv8tion.jda.core.entities.Emote;
import net.dv8tion.jda.core.entities.Member;
@@ -38,6 +39,9 @@ public class ObjectBuilderFactory
// RPManger for tracking RP system
private static RPManager rpManager;
// Plugin manager
private static PluginManager pluginManager;
// Localization classes - these are singletons, but should be initialized before almost all other
// things so their inclusion in the factory is to ensure they're started at the correct time.
@SuppressWarnings("unused") private static LocStrings locStrings;
@@ -408,6 +412,16 @@ public class ObjectBuilderFactory
return rpManager;
}
public static PluginManager ConstructPluginManager()
{
LazyInit();
if(pluginManager == null)
pluginManager = new PluginManager("./plugins/");
return pluginManager;
}
public static Integer GetGuildCount()
{ synchronized(guildCache)
{
+34
View File
@@ -0,0 +1,34 @@
package core.lua;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
//To promote flexibility, plugins are lua file with predefined callbacks.
//They are executed between the initial built-in preprocessing and the command parsing.
public class Plugin
{
public Path filepath;
public String contents;
public Plugin(Path filepath)
{
this.filepath = filepath;
StringBuilder contentBuilder = new StringBuilder();
try
{
Stream<String> stream = Files.lines(filepath, StandardCharsets.UTF_8);
stream.forEach(str -> contentBuilder.append(str).append("\n"));
stream.close();
contents = contentBuilder.toString();
}
catch (IOException e)
{
PluginLog.Error(e.getMessage());
}
}
}
+42
View File
@@ -0,0 +1,42 @@
package core.lua;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;
// This class wraps the lua layer - provides all the processing and function
// calls to the lua binding.
public class PluginLoader
{
private Globals globals;
public PluginLoader()
{
globals = JsePlatform.standardGlobals();
PluginLog.Log("Created new PluginLoader lua environment");
}
public String Process(Plugin toProcess, String args)
{
globals.load(toProcess.contents).call();
LuaValue pluginFunc = globals.get("plugin");
String output = null;
try
{
LuaValue res = pluginFunc.call(LuaValue.valueOf(args));
if(res.isnil())
output = null;
else
output = res.toString();
}
catch(Exception e)
{
output = null;
}
return output;
}
}
+11
View File
@@ -0,0 +1,11 @@
package core.lua;
import utils.GlobalLog;
import utils.LogFilter;
public class PluginLog
{
public static void Log(String s) { GlobalLog.Log(LogFilter.Plugin, s); }
public static void Warn(String s) { GlobalLog.Warn(LogFilter.Plugin, s); }
public static void Error(String s) { GlobalLog.Error(LogFilter.Plugin, s); }
}
+64
View File
@@ -0,0 +1,64 @@
package core.lua;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.stream.Stream;
//Reads in, handles, and manipulates plugins. Plugins are
//loaded in the order they appear in the folder.
public class PluginManager
{
public PluginLoader pluginLoader;
public final String pluginFolder;
public ArrayList<Plugin> plugins;
public void AddPlugin(Path path)
{
plugins.add(new Plugin(path));
}
public PluginManager(String folder)
{
this.pluginFolder = folder;
plugins = new ArrayList<Plugin>();
this.pluginLoader = new PluginLoader();
try
{
try (Stream<Path> paths = Files.walk(Paths.get(this.pluginFolder)))
{
paths.filter(Files::isRegularFile).forEach((path)->{ AddPlugin(path); });
}
}
catch(Exception e)
{
PluginLog.Error(e.getMessage());
}
}
public String CallAll(String input)
{
for(int i = 0; i < plugins.size(); ++i)
{
Plugin script = plugins.get(i);
String out = pluginLoader.Process(script, input);
if(out != null)
{
PluginLog.Log("Executed plugin at " + script.filepath);
return out;
}
}
return null;
}
public void PrintAll()
{
for(int i = 0; i < plugins.size(); ++i)
PluginLog.Log(plugins.get(i).contents.toString());
}
}
+19 -10
View File
@@ -2,6 +2,7 @@ package main;
import javax.security.auth.login.LoginException;
import core.*;
import core.lua.PluginManager;
import dataStructures.KittyChannel;
import dataStructures.KittyGuild;
import dataStructures.KittyRole;
@@ -22,14 +23,15 @@ import net.dv8tion.jda.core.*;
@SuppressWarnings("unused")
public class Main extends ListenerAdapter
{
// Variables and stuff
// Variables and bot specific objects
private static JDA kitty;
private static CommandManager commandManager;
private static CommandEnabler commandEnabler;
private static DatabaseManager databaseManager;
private static CommandEnabler commandEnabler;
private static CommandManager commandManager;
private static Stats stats;
private static RPManager rpManager;
private static PluginManager pluginManager;
// Main test location
public static void main(String[] args) throws InterruptedException, LoginException, Exception
{
@@ -37,8 +39,9 @@ public class Main extends ListenerAdapter
databaseManager = ObjectBuilderFactory.ConstructDatabaseManager();
commandEnabler = ObjectBuilderFactory.ConstructCommandEnabler();
commandManager = ObjectBuilderFactory.ConstructCommandManager(commandEnabler);
rpManager = ObjectBuilderFactory.ConstructRPManager();
stats = ObjectBuilderFactory.ConstructStats(commandManager);
rpManager = ObjectBuilderFactory.ConstructRPManager();
pluginManager = ObjectBuilderFactory.ConstructPluginManager();
// Bot startup
kitty = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking();
@@ -61,19 +64,25 @@ public class Main extends ListenerAdapter
// Specialized uncached objects
Response response = new Response(event, kitty);
UserInput input = new UserInput(event, guild);
// Tweak object construction as necessary
if(!PostProcessSetup(event, user, guild, channel, response, input))
return;
// Track beans!
user.ChangeBeans(1);
user.ChangeBeans(1);
// RP logging system
RPManager.instance.addLine(channel, user, input);
// Issue the command
commandManager.InvokeOnNewThread(guild, channel, user, input, response);
// Run plugins right before invoking the commands but after all other setup
String output = pluginManager.CallAll(input.message);
// Spin up the command if no plugins ran. Otherwise, send a response.
if(output == null)
commandManager.InvokeOnNewThread(guild, channel, user, input, response);
else
response.Call(output);
// Run any upkeep we need to
PerCommandUpkeep();
+1 -1
View File
@@ -3,7 +3,7 @@ package utils;
public enum LogFilter
{
// Assign numbers as flags, so we can | ('or') them together as necessary
Debug(0), Command(1), Core(2), Util(4), Database(8), Response(16), Network(32), Strings(64);
Debug(0), Command(1), Core(2), Util(4), Database(8), Response(16), Network(32), Strings(64), Plugin(128);
private final int value;
private LogFilter(int value)