完成框架

1. 完成框架
2. 添加 /op 和 /about 指令
This commit is contained in:
2019-06-06 21:15:50 +08:00
commit 3df286ebbf
28 changed files with 1118 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
package ren.taske.nativebot;
import org.bukkit.plugin.java.JavaPlugin;
import ren.taske.nativebot.core.NativeBot;
public class MinecraftPlugin extends JavaPlugin {
protected final NativeBot core = new NativeBot(this);
@Override
public void onEnable() {
core.onEnable();
super.onEnable();
}
@Override
public void onDisable() {
core.onDisable();
super.onDisable();
}
}

View File

@@ -0,0 +1,80 @@
package ren.taske.nativebot.bot;
import java.util.Collection;
import java.util.List;
import cc.moecraft.icq.PicqBotX;
import cc.moecraft.icq.PicqConfig;
import cc.moecraft.icq.command.CommandManager;
import cc.moecraft.icq.command.interfaces.IcqCommand;
import cc.moecraft.icq.sender.IcqHttpApi;
import cc.moecraft.logger.environments.ColorSupportLevel;
import ren.taske.nativebot.commons.Config;
public class Bot extends Thread {
protected final PicqBotX bot;
public Bot() {
this(Config.port_in, Config.port_out, Config.url_out, Config.prefixes);
}
/**
* new bot!
* @param portIn the port to receive messages from HttpApi
* @param portOut the port to send messages to HttpApi
* @param urlOut the url to send messages to HttpApi
* @param prefixes the prefixes of commands in Tencent
*/
public Bot(int portIn, int portOut, String urlOut, String...prefixes) {
PicqConfig botconfig = new PicqConfig(portIn).setColorSupportLevel(ColorSupportLevel.DISABLED);
bot = new PicqBotX(botconfig);
bot.addAccount("NightBot", urlOut, portOut);
bot.enableCommandManager(prefixes);
}
/**
* Add commands for bot
* @param cmds the commands
*/
public void register(IcqCommand...cmds) {
bot.getCommandManager().registerCommands(cmds);
}
/**
* Add commands for bot
* @param cmds the commands
*/
public void register(Collection<IcqCommand> cmds) {
register(cmds.toArray(new IcqCommand[0]));
}
/**
* To start the bot. <br>
* But wait! Did you {@code register} the commands?
*/
public void run() {
bot.startBot();
}
public CommandManager getCommandManager() {
return bot.getCommandManager();
}
public List<String> getCommands(){
return getCommandManager().getCommandNameList();
}
public IcqHttpApi getApi() {
return bot.getAccountManager().getNonAccountSpecifiedApi();
}
public void sendGroupMessage(long gid, String msg) {
getApi().sendGroupMsg(gid, msg);
}
public void sendPrivateMessage(long uid, String msg) {
getApi().sendPrivateMsg(uid, msg);
}
}

View File

@@ -0,0 +1,24 @@
package ren.taske.nativebot.bot.command;
import java.util.ArrayList;
import cc.moecraft.icq.event.events.message.EventMessage;
import cc.moecraft.icq.user.User;
import ren.taske.nativebot.util.MessageUtils;
public class CommandAbout extends CommandBase {
public CommandAbout() {
super("about", null, "bot", "help");
}
@Override
public String execute(EventMessage evt, User user, long userid, String command, ArrayList<String> args) {
return MessageUtils.retAt(userid, "Yes, sir!",
"(command with * requires OP_PERMISSION_NODE)",
"/about[/bot|/help] - show this notice",
"/op - query if you're operator",
"/op* [userid] - set user as operator");
}
}

View File

@@ -0,0 +1,41 @@
package ren.taske.nativebot.bot.command;
import java.util.ArrayList;
import cc.moecraft.icq.command.CommandProperties;
import cc.moecraft.icq.command.interfaces.EverywhereCommand;
import cc.moecraft.icq.event.events.message.EventMessage;
import cc.moecraft.icq.user.User;
import ren.taske.nativebot.commons.Reference;
import ren.taske.nativebot.core.profile.UserTencent;
import ren.taske.nativebot.util.MessageLib;
public abstract class CommandBase implements EverywhereCommand {
final CommandProperties properties;
final String node;
public CommandBase(String name, String node, String...alias) {
this.properties = new CommandProperties(name, alias);
this.node = node;
}
@Override
public CommandProperties properties() {
return properties;
}
@Override
public String run(EventMessage event, User sender, String command, ArrayList<String> args) {
long userid = sender.getId();
if(node == null || node.equals("") || UserTencent.of(userid).hasPermission(node) || UserTencent.of(userid).hasPermission(Reference.NODE_OP)) {
return execute(event, sender, userid, command, args);
} else {
return MessageLib.getUnauthorizedMessage(sender);
}
}
public abstract String execute(EventMessage evt, User user, long userid, String command, ArrayList<String> args);
}

View File

@@ -0,0 +1,58 @@
package ren.taske.nativebot.bot.command;
import java.util.ArrayList;
import cc.moecraft.icq.event.events.message.EventMessage;
import cc.moecraft.icq.user.User;
import ren.taske.data.util.ParseUtil;
import ren.taske.nativebot.core.profile.UserTencent;
import ren.taske.nativebot.util.MessageLib;
import ren.taske.nativebot.util.MessageUtils;
public class CommandOperator extends CommandBase {
public CommandOperator() {
super("op", null, "operator");
}
public static final String OP_PERM_NODE = "op";
@Override
public String execute(EventMessage evt, User user, long userid, String command, ArrayList<String> args) {
UserTencent u = UserTencent.of(userid);
String message = "";
/* Mode: check */
if(args.size() == 0) {
boolean perm = u.hasPermission(OP_PERM_NODE);
message = "You're "+(perm?"an operator!":"not an operator");
}
/* Mode: set */
if(args.size() == 1) {
if(u.hasPermission(OP_PERM_NODE)) {
// Authorized
Long uid = ParseUtil.parseLong(args.get(0));
if(uid != null) {
UserTencent u2 = UserTencent.of(uid);
// Check if has OP_PERM_NODE
if(u2.hasPermission(OP_PERM_NODE)) {
u2.setPermission(OP_PERM_NODE, false);
message = "["+uid+"] now is NOT operator!";
} else {
u2.setPermission(OP_PERM_NODE, true);
message = "["+uid+"] now is operator!";
}
} else {
message = "NumberFormatException!";
}
} else {
// Unauthorized
return MessageLib.getUnauthorizedMessage(userid);
}
}
return MessageUtils.retAt(userid, message);
}
}

View File

@@ -0,0 +1,31 @@
package ren.taske.nativebot.commons;
import TConfig.Configuration;
public class Config {
public static final Configuration cfg;
static {
cfg = new Configuration(Reference.FILE_CONFIGURATION);
refresh();
}
// The Bot Constructor
public static int port_in;
public static int port_out;
public static String url_out;
public static String[] prefixes;
public static void refresh() {
port_in = cfg.getInt("in", "constructor", 25560, 0, 65535, "The port for receiving messages");
port_out = cfg.getInt("out", "constructor", 25561, 0, 65535, "The port for sending message to HttpApi");
url_out = cfg.getString("url", "constructor", "127.0.0.1", "The url for sending message to HttpApi");
prefixes = cfg.getStringList("prefixes", "constructor", new String[] {"/"}, "The prefixes of commands in Tencent");
cfg.save();
}
}

View File

@@ -0,0 +1,23 @@
package ren.taske.nativebot.commons;
import java.io.File;
import ren.taske.nativebot.bot.command.CommandOperator;
public class Reference {
public static final File DATA_FOLDER = new File("NativeBot");
public static final File FILE_CONFIGURATION = new File(DATA_FOLDER+"/config.cfg");
public static File getTencentProfile(long userid) {
return new File(DATA_FOLDER+"/tencent/"+userid+".profile");
}
public static File getMinecraftProfile(String userid) {
return new File(DATA_FOLDER+"/minecraft/"+userid+".profile");
}
public static final String NODE_OP = CommandOperator.OP_PERM_NODE;
}

View File

@@ -0,0 +1,49 @@
package ren.taske.nativebot.core;
import java.util.logging.Logger;
import org.bukkit.plugin.java.JavaPlugin;
import cc.moecraft.icq.command.interfaces.IcqCommand;
import ren.taske.nativebot.bot.Bot;
import ren.taske.nativebot.bot.command.CommandAbout;
import ren.taske.nativebot.bot.command.CommandOperator;
import ren.taske.nativebot.util.ClassUtils;
public class NativeBot {
protected static Logger logger;
@SuppressWarnings("unchecked")
private static final Class<IcqCommand>[] COMMAND_CLASSES = new Class[] {
CommandAbout.class,
CommandOperator.class
};
protected final JavaPlugin plugin;
protected final Bot bot;
public NativeBot(JavaPlugin plugin) {
this.plugin = plugin;
this.bot = new Bot();
logger = plugin.getLogger();
}
public static Logger logger() {
return logger;
}
public void onEnable() {
bot.register(ClassUtils.instantiate(COMMAND_CLASSES));
bot.start();
for(String cmd : bot.getCommands()) logger.info("[C] "+cmd);
}
public void onDisable() {
}
}

View File

@@ -0,0 +1,21 @@
package ren.taske.nativebot.core.profile;
import ren.taske.data.SimpleDataStorage;
public abstract class User {
protected final String userid;
public User(String userid) {
this.userid = userid;
}
public String getUserId() {
return this.userid;
}
public abstract SimpleDataStorage getData();
public abstract void reload();
public abstract void onUnload();
}

View File

@@ -0,0 +1,42 @@
package ren.taske.nativebot.core.profile;
import java.util.HashMap;
import ren.taske.data.SimpleDataStorage;
import ren.taske.nativebot.commons.Reference;
public class UserMinecraft extends User {
protected static final HashMap<String, UserMinecraft> PROFILES = new HashMap<>();
protected final SimpleDataStorage data;
private UserMinecraft(String userid) {
super(userid);
data = new SimpleDataStorage(Reference.getMinecraftProfile(userid));
}
public static UserMinecraft of(String userid) {
if(!PROFILES.containsKey(userid)) {
UserMinecraft user = new UserMinecraft(userid);
PROFILES.put(userid, user);
}
return PROFILES.get(userid);
}
@Override
public SimpleDataStorage getData() {
return data;
}
@Override
public void onUnload() {
data.save();
}
@Override
public void reload() {
}
}

View File

@@ -0,0 +1,55 @@
package ren.taske.nativebot.core.profile;
import java.util.HashMap;
import ren.taske.data.SimpleDataStorage;
import ren.taske.nativebot.commons.Reference;
public class UserTencent extends User {
protected static final HashMap<Long, UserTencent> PROFILES = new HashMap<>();
protected final SimpleDataStorage data;
private UserTencent(long userid) {
super(Long.toString(userid));
data = new SimpleDataStorage(Reference.getTencentProfile(userid));
}
public static UserTencent of(long userid) {
if(!PROFILES.containsKey(userid)) {
UserTencent user = new UserTencent(userid);
PROFILES.put(userid, user);
}
return PROFILES.get(userid);
}
@Override
public SimpleDataStorage getData() {
return data;
}
@Override
public void reload() {
}
@Override
public void onUnload() {
data.save();
}
public boolean hasPermission(String node) {
if(node != null) {
data.setDefault(node, false);
data.save();
}
return data.getBoolean(node, false);
}
public void setPermission(String node, boolean val) {
data.setBoolean(node, val);
data.save();
}
}

View File

@@ -0,0 +1,27 @@
package ren.taske.nativebot.util;
import java.util.List;
import com.google.common.collect.Lists;
import cc.moecraft.icq.command.interfaces.IcqCommand;
import ren.taske.nativebot.core.NativeBot;
public class ClassUtils {
@SuppressWarnings("unchecked")
public static List<IcqCommand> instantiate(Class<IcqCommand>...classes) {
List<IcqCommand> ret = Lists.newArrayList();
for(Class<IcqCommand> clazz : classes) {
try {
IcqCommand cmd = clazz.newInstance();
ret.add(cmd);
} catch(Exception e) {
NativeBot.logger().warning("Error when loading IcqCommand "+clazz.getName());
NativeBot.logger().warning(e.getMessage());
}
}
return ret;
}
}

View File

@@ -0,0 +1,12 @@
package ren.taske.nativebot.util;
public class MessageLib {
public static final String _NEWLINE = "\n";
public static final String _UNAUTHORIZED = "You have no permission!";
public static String getUnauthorizedMessage(Object user) {
return MessageUtils.at(user)+_NEWLINE+_UNAUTHORIZED;
}
}

View File

@@ -0,0 +1,34 @@
package ren.taske.nativebot.util;
import cc.moecraft.icq.sender.message.MessageBuilder;
import cc.moecraft.icq.sender.message.components.ComponentAt;
import cc.moecraft.icq.user.User;
public class MessageUtils {
public static String at(Object object, String defaultVal) {
if(object instanceof Long) return at((Long) object);
if(object instanceof User) return at((User) object);
return defaultVal;
}
public static String at(Object object) {
return at(object, null);
}
public static String at(long userid) {
return new ComponentAt(userid).toString();
}
public static String at(User user) {
return at(user.getId());
}
public static String retAt(long userid, String...lines) {
MessageBuilder mb = new MessageBuilder();
mb.add(at(userid)).newLine();
for(String line : lines) mb.add(line).newLine();
return mb.toString().trim();
}
}