From 883bd390266f2b0f9927a22bb45c21eb7b10279f Mon Sep 17 00:00:00 2001 From: slhaf <2998813882@qq.com> Date: Thu, 3 Oct 2024 23:18:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BA=86owner=E7=9A=84?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8C=87=E4=BB=A4=EF=BC=9B=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E7=BE=A4=E8=81=8A=E9=BB=91=E5=90=8D=E5=8D=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=9B=20=E5=AE=8C=E5=96=84=E4=BA=86?= =?UTF-8?q?=E6=B8=85=E7=90=86=E7=BA=BF=E7=A8=8B=E8=B6=85=E6=97=B6=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E4=BB=A5=E5=8F=8A=E6=9C=80=E8=BF=91=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E7=9A=84=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=9B=20=E6=94=B9=E6=AD=A3=E4=BA=86=E4=B9=8B=E5=89=8D?= =?UTF-8?q?=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F=E4=B8=AD=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E9=94=99=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/plugin/App.java | 22 ++-- src/main/java/plugin/constant/AIConstant.java | 1 + .../java/plugin/constant/ChatConstant.java | 2 +- .../java/plugin/constant/ConfigConstant.java | 2 + .../listener/FriendMessageListener.java | 19 ++- .../plugin/listener/GroupMessageListener.java | 3 +- .../plugin/listener/OwnerMessageListener.java | 112 ++++++++++++++++++ src/main/java/plugin/pojo/Config.java | 31 +++++ .../plugin/pojo/UserCustomLatestTime.java | 53 +++++++++ src/main/java/plugin/utils/AIUtil.java | 110 ++++++++++++----- src/main/java/plugin/utils/ConfigUtil.java | 109 +++++++++++++---- src/test/java/MyTest.java | 47 +++++++- 12 files changed, 429 insertions(+), 82 deletions(-) create mode 100644 src/main/java/plugin/pojo/UserCustomLatestTime.java diff --git a/src/main/java/plugin/App.java b/src/main/java/plugin/App.java index 025dafd..c855ead 100644 --- a/src/main/java/plugin/App.java +++ b/src/main/java/plugin/App.java @@ -5,7 +5,6 @@ import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescriptionBuilder; import net.mamoe.mirai.event.GlobalEventChannel; import net.mamoe.mirai.event.events.FriendMessageEvent; import net.mamoe.mirai.event.events.GroupMessageEvent; -import net.mamoe.mirai.utils.MiraiLogger; import plugin.constant.ChatConstant; import plugin.listener.FriendMessageListener; import plugin.listener.GroupMessageListener; @@ -15,12 +14,11 @@ import plugin.utils.ConfigUtil; import java.io.IOException; import java.util.HashMap; +import java.util.List; public final class App extends JavaPlugin { public static final App INSTANCE = new App(); - private String owner, bot; - private static HashMap customCommands; private App() { super(new JvmPluginDescriptionBuilder("com.plugin.chatAI-InGroup-v2", "0.1.0") @@ -32,6 +30,9 @@ public final class App extends JavaPlugin { @Override public void onEnable() { + String owner, bot; + HashMap customCommands; + List blacklist; //加载配置 try { ConfigUtil.load(); @@ -40,7 +41,7 @@ public final class App extends JavaPlugin { owner = config.getOwner().substring(1); bot = config.getBot().substring(1); customCommands = config.getCustomCommands(); - + blacklist = config.getBlacklist(); } catch (IOException | ClassNotFoundException | InterruptedException e) { throw new RuntimeException(e); } @@ -51,16 +52,17 @@ public final class App extends JavaPlugin { GlobalEventChannel.INSTANCE.filterIsInstance(GroupMessageEvent.class) .filter(event -> { String msg = event.getMessage().contentToString(); - return (msg.startsWith(".") && msg.length() != 1) || msg.startsWith("@"+bot) || customCommands.containsKey(msg.split(" ")[0]); + long groupId = event.getGroup().getId(); + return ((msg.startsWith(".") && msg.length() != 1) || msg.startsWith("@" + bot) || customCommands.containsKey(msg.split(" ")[0])) && !blacklist.contains(groupId); }).registerListenerHost(new GroupMessageListener()); //所有者监听 GlobalEventChannel.INSTANCE.filterIsInstance(GroupMessageEvent.class) - .filter(event -> { - String msg = event.getMessage().contentToString(); - String sender = String.valueOf(event.getSender().getId()); - return msg.startsWith(ChatConstant.SET) && sender.equals(owner); - }).registerListenerHost(new OwnerMessageListener()); + .filter(event -> { + String msg = event.getMessage().contentToString(); + String sender = String.valueOf(event.getSender().getId()); + return msg.startsWith(ChatConstant.SET) && sender.equals(owner); + }).registerListenerHost(new OwnerMessageListener()); //私聊监听器 GlobalEventChannel.INSTANCE.filterIsInstance(FriendMessageEvent.class) diff --git a/src/main/java/plugin/constant/AIConstant.java b/src/main/java/plugin/constant/AIConstant.java index ee9aad1..9d9509d 100644 --- a/src/main/java/plugin/constant/AIConstant.java +++ b/src/main/java/plugin/constant/AIConstant.java @@ -14,4 +14,5 @@ public class AIConstant { * 错误结果 */ public static final String ERROR = "ERROR"; + public static final int NORMAL_CODE = 200; } diff --git a/src/main/java/plugin/constant/ChatConstant.java b/src/main/java/plugin/constant/ChatConstant.java index 0eae303..c6e13e5 100644 --- a/src/main/java/plugin/constant/ChatConstant.java +++ b/src/main/java/plugin/constant/ChatConstant.java @@ -30,7 +30,7 @@ public class ChatConstant { */ public static final String BLANK = " "; - public static final String SET = "/set "; + public static final String SET = "$ "; /** * 切换模型 diff --git a/src/main/java/plugin/constant/ConfigConstant.java b/src/main/java/plugin/constant/ConfigConstant.java index de0e7b7..15bb813 100644 --- a/src/main/java/plugin/constant/ConfigConstant.java +++ b/src/main/java/plugin/constant/ConfigConstant.java @@ -10,4 +10,6 @@ public class ConfigConstant { public static final String NULL = "null"; public static final String CUSTOM_SPLIT = "\\|"; + public static final String ADD_CUSTOM = "/[a-zA-Z]+\\|.*\\|.*"; + public static final String MODEL_CHANGE = ".*\\|.*"; } diff --git a/src/main/java/plugin/listener/FriendMessageListener.java b/src/main/java/plugin/listener/FriendMessageListener.java index 80abc71..5540750 100644 --- a/src/main/java/plugin/listener/FriendMessageListener.java +++ b/src/main/java/plugin/listener/FriendMessageListener.java @@ -12,16 +12,18 @@ import plugin.utils.ConfigUtil; import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * @author SLHAF + */ public class FriendMessageListener extends SimpleListenerHost { - private static final Config config = ConfigUtil.getConfig(); - @EventHandler public void friendMessageHandler(FriendMessageEvent event) { - /*String id = String.valueOf(event.getFriend().getId()); + String id = String.valueOf(event.getFriend().getId()); String content = event.getMessage().contentToString(); String miraiCode = event.getMessage().serializeToMiraiCode(); String url = null; + String chatCommand = null; if (miraiCode.matches(ChatConstant.MATCH_MESSAGE)) { String regex = ChatConstant.MATCH_IMAGE; Pattern pattern = Pattern.compile(regex); @@ -37,16 +39,11 @@ public class FriendMessageListener extends SimpleListenerHost { } MethodsConstant method = MethodsConstant.NORMAL; - - if (content.contains(ChatConstant.CHANGE_MODEL) && !id.equals(config.getOwner().substring(1))) { - event.getFriend().sendMessage("没有权限!"); - return; - } - //处理消息头 - if (content.startsWith(ChatConstant.CODE_MESSAGE_START)) { + if (ConfigUtil.getConfig().getCustomCommands().containsKey(content.split(ChatConstant.BLANK)[0])) { content = content.substring(3); method = MethodsConstant.CUSTOM; + chatCommand = content.split(ChatConstant.BLANK)[0]; } else if (content.startsWith(ChatConstant.ONCE_MESSAGE_START)) { content = content.substring(1); method = MethodsConstant.ONCE; @@ -58,6 +55,6 @@ public class FriendMessageListener extends SimpleListenerHost { case NORMAL -> AIUtil.defaultChat(Long.valueOf(id), content, url); default -> "ERROR!"; }; - event.getFriend().sendMessage(response);*/ + event.getFriend().sendMessage(response); } } diff --git a/src/main/java/plugin/listener/GroupMessageListener.java b/src/main/java/plugin/listener/GroupMessageListener.java index 0c48dc7..27be391 100644 --- a/src/main/java/plugin/listener/GroupMessageListener.java +++ b/src/main/java/plugin/listener/GroupMessageListener.java @@ -23,8 +23,6 @@ import static plugin.utils.ConfigUtil.logger; */ public class GroupMessageListener extends SimpleListenerHost { - private static final Config config = ConfigUtil.getConfig(); - @Override public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) { super.handleException(context, exception); @@ -37,6 +35,7 @@ public class GroupMessageListener extends SimpleListenerHost { */ @EventHandler public void groupMessageHandler(GroupMessageEvent event) { + Config config = ConfigUtil.getConfig(); //处理消息 String id = String.valueOf(event.getSender().getId()); String content = event.getMessage().contentToString(); diff --git a/src/main/java/plugin/listener/OwnerMessageListener.java b/src/main/java/plugin/listener/OwnerMessageListener.java index 8c445dc..d4f2d19 100644 --- a/src/main/java/plugin/listener/OwnerMessageListener.java +++ b/src/main/java/plugin/listener/OwnerMessageListener.java @@ -1,6 +1,118 @@ package plugin.listener; +import kotlin.coroutines.CoroutineContext; +import net.mamoe.mirai.event.EventHandler; import net.mamoe.mirai.event.SimpleListenerHost; +import net.mamoe.mirai.event.events.FriendMessageEvent; +import net.mamoe.mirai.event.events.GroupMessageEvent; +import net.mamoe.mirai.message.data.At; +import org.jetbrains.annotations.NotNull; +import plugin.constant.AIConstant; +import plugin.constant.ChatConstant; +import plugin.constant.ConfigConstant; +import plugin.utils.AIUtil; +import plugin.utils.ConfigUtil; +import java.io.IOException; +import java.util.HashMap; + +import static plugin.utils.ConfigUtil.getConfig; +import static plugin.utils.ConfigUtil.logger; + +/** + * @author SLHAF + */ public class OwnerMessageListener extends SimpleListenerHost { + + @Override + public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) { + super.handleException(context, exception); + logger.error(exception); + } + + @EventHandler + public void onGroupMessageEvent(GroupMessageEvent event) { + String msg = event.getMessage().contentToString(); + String primaryContent = msg.split(ChatConstant.BLANK)[1]; + if (!primaryContent.contains(ChatConstant.BLANK)) { + String response; + response = switch (primaryContent) { + case "clearAll" -> AIUtil.clearAll(); + case "shutUp" -> ConfigUtil.shutUp(event.getGroup().getId()); + case "speak" -> ConfigUtil.speak(event.getGroup().getId()); + default -> "无对应操作"; + }; + event.getGroup().sendMessage(response); + return; + } + + String command = primaryContent.split(ChatConstant.BLANK)[0]; + String arguments = primaryContent.split(ChatConstant.BLANK)[1]; + long id = event.getSender().getId(); + String response; + try { + response = handleCommand(command, arguments); + } catch (Exception e) { + logger.error(e.toString()); + response = "操作失败!\r\n" + e.getMessage(); + } + event.getGroup().sendMessage(new At(id).plus(response)); + } + + @EventHandler + public void onFriendMessageEvent(FriendMessageEvent event) throws IOException { + String command; + String arguments; + try { + command = event.getMessage().contentToString().split(ChatConstant.BLANK)[0]; + arguments = event.getMessage().contentToString().split(ChatConstant.BLANK)[1]; + } catch (ArrayIndexOutOfBoundsException e) { + event.getFriend().sendMessage("操作失败,缺少参数"); + return; + } + String response = handleCommand(command, arguments); + event.getFriend().sendMessage(response); + } + + /** + * 对命令及其参数进行处理 + * + * @param command 命令 + * @param arguments 参数 + * @return 处理结果 + */ + private String handleCommand(String command, String arguments) throws IOException { + return switch (command) { + case "添加预设" -> { + if (arguments.matches(ConfigConstant.ADD_CUSTOM)) { + String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; + String customModel = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; + String customContent = arguments.split(ConfigConstant.CUSTOM_SPLIT)[2]; + yield ConfigUtil.addCustom(instruction, customModel, customContent); + } else { + yield "格式不正确! 参数格式如下: \r\n指令|模型名称|预设\r\n例: \r\n/example|glm-4-flash|你是...\r\n注:如果不需要预设,可以将预设写为null"; + } + } + case "切换模型" -> { + if (arguments.matches(ConfigConstant.MODEL_CHANGE)) { + String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; + String modelName = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; + yield ConfigUtil.customModelChange(instruction, modelName); + } else { + yield "格式不正确! 参数格式如下: \r\n指令|指令对应模型"; + } + } + case "更改预设" -> { + if (arguments.matches(ConfigConstant.MODEL_CHANGE)) { + String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; + String customContent = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; + yield ConfigUtil.customContentChange(instruction, customContent); + } else { + yield "格式不正确! 参数格式如下: \r\n指令|指令对应预设"; + } + } + case "删除预设" -> ConfigUtil.removeCustom(arguments); + default -> "该指令不存在!"; + }; + } } diff --git a/src/main/java/plugin/pojo/Config.java b/src/main/java/plugin/pojo/Config.java index 4b5fd3e..5a3c33a 100644 --- a/src/main/java/plugin/pojo/Config.java +++ b/src/main/java/plugin/pojo/Config.java @@ -2,6 +2,7 @@ package plugin.pojo; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; public class Config { /** @@ -23,6 +24,7 @@ public class Config { private String bot; private String timeout; private String timeCheck; + private List blacklist; /** * 自定义预设 @@ -44,6 +46,19 @@ public class Config { this.customCommands = customCommands; } + public Config(String apikey, String accessKeyId, String accessKeySecret, String owner, String defaultModel, String bot, String timeout, String timeCheck, List blacklist, LinkedHashMap customCommands) { + this.apikey = apikey; + this.accessKeyId = accessKeyId; + this.accessKeySecret = accessKeySecret; + this.owner = owner; + this.defaultModel = defaultModel; + this.bot = bot; + this.timeout = timeout; + this.timeCheck = timeCheck; + this.blacklist = blacklist; + this.customCommands = customCommands; + } + /** * 获取 * @return apikey @@ -192,4 +207,20 @@ public class Config { public String toString() { return "Config{apikey = " + apikey + ", accessKeyId = " + accessKeyId + ", accessKeySecret = " + accessKeySecret + ", owner = " + owner + ", modelNormal = " + defaultModel + ", modelCode = " + ", bot = " + bot + ", timeout = " + timeout + ", timeCheck = " + timeCheck + ", customCommands = " + customCommands + "}"; } + + /** + * 获取 + * @return blacklist + */ + public List getBlacklist() { + return blacklist; + } + + /** + * 设置 + * @param blacklist + */ + public void setBlacklist(List blacklist) { + this.blacklist = blacklist; + } } diff --git a/src/main/java/plugin/pojo/UserCustomLatestTime.java b/src/main/java/plugin/pojo/UserCustomLatestTime.java new file mode 100644 index 0000000..90c3dd5 --- /dev/null +++ b/src/main/java/plugin/pojo/UserCustomLatestTime.java @@ -0,0 +1,53 @@ +package plugin.pojo; + +/** + * @author SLHAF + */ +public class UserCustomLatestTime { + private String chatCommand; + private Long latestTime; + + public UserCustomLatestTime() { + } + + public UserCustomLatestTime(String chatCommand, Long latestTime) { + this.chatCommand = chatCommand; + this.latestTime = latestTime; + } + + /** + * 获取 + * @return chatCommand + */ + public String getChatCommand() { + return chatCommand; + } + + /** + * 设置 + * @param chatCommand + */ + public void setChatCommand(String chatCommand) { + this.chatCommand = chatCommand; + } + + /** + * 获取 + * @return latestTime + */ + public Long getLatestTime() { + return latestTime; + } + + /** + * 设置 + * @param latestTime + */ + public void setLatestTime(Long latestTime) { + this.latestTime = latestTime; + } + + public String toString() { + return "UserCustomLatestTime{chatCommand = " + chatCommand + ", latestTime = " + latestTime + "}"; + } +} diff --git a/src/main/java/plugin/utils/AIUtil.java b/src/main/java/plugin/utils/AIUtil.java index 6b88f9a..a3737ae 100644 --- a/src/main/java/plugin/utils/AIUtil.java +++ b/src/main/java/plugin/utils/AIUtil.java @@ -1,5 +1,6 @@ package plugin.utils; +import cn.hutool.core.map.MapUtil; import com.zhipu.oapi.ClientV4; import com.zhipu.oapi.Constants; import com.zhipu.oapi.service.v4.model.ChatCompletionRequest; @@ -9,13 +10,14 @@ import com.zhipu.oapi.service.v4.model.ModelApiResponse; import plugin.constant.AIConstant; import plugin.constant.ChatConstant; import plugin.constant.ConfigConstant; -import plugin.constant.MethodsConstant; import plugin.pojo.Config; +import plugin.pojo.UserCustomLatestTime; import plugin.pojo.UserCustomMessage; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.function.BiConsumer; import static plugin.utils.ConfigUtil.logger; @@ -32,7 +34,7 @@ public class AIUtil { private static String defaultModel; private static final HashMap> userCustomMessages = new HashMap<>(); - private static final HashMap userLatestTimeOfCustom = new HashMap<>(); + private static final HashMap> userLatestTimeOfCustom = new HashMap<>(); /*private static String modelCode;*/ /** * 结构: @@ -59,7 +61,7 @@ public class AIUtil { } if (!userLatestTimeOfDefault.isEmpty()) { - //查看user最近时间,如果超过30min,则清理对应记录 + //查看user最近时间,如果超过TIMEOUT,则清理对应记录 userLatestTimeOfDefault.forEach((id, latestTime) -> { synchronized (userDefaultMessages.get(id)) { Long currentTime = System.currentTimeMillis(); @@ -73,13 +75,21 @@ public class AIUtil { if (!userLatestTimeOfCustom.isEmpty()) { - //查看user最近时间,如果超过30min,则清理对应记录 - userLatestTimeOfCustom.forEach((id, latestTime) -> { + //查看user最近时间,如果超过TIMEOUT,则清理对应记录 + userLatestTimeOfCustom.forEach((id, userCustomLatestTimeList) -> { synchronized (userCustomMessages.get(id)) { + ArrayList indexToRemove = new ArrayList<>(); Long currentTime = System.currentTimeMillis(); - if (currentTime - latestTime > 30 * 60 * 1000 && userCustomMessages.containsKey(id)) { - userCustomMessages.remove(id); - logger.info("custom记录清理:" + id); + for (int i = 0; i < userCustomLatestTimeList.size(); i++) { + if (currentTime - userCustomLatestTimeList.get(i).getLatestTime() > TIMEOUT){ + logger.info("custom记录清理: "+id+" "+userCustomLatestTimeList.get(i).getChatCommand()); + userCustomMessages.get(id).remove(i); + indexToRemove.add(i); + } + } + //移除最近操作时间 + for (int i : indexToRemove) { + userCustomLatestTimeList.remove(i); } } }); @@ -96,14 +106,16 @@ public class AIUtil { public static String customChat(Long id, String content, String url, String chatCommand) { if (ChatConstant.CLEAR.equals(content.replace(ChatConstant.BLANK, ""))) { - userCustomMessages.remove(id); + if (!userCustomMessages.containsKey(id)) { + return "不存在消息记录"; + } + for (UserCustomMessage userCustomMessage : userCustomMessages.get(id)) { + if (userCustomMessage.getCommand().equals(chatCommand)) { + userCustomMessage.getMessages().clear(); + } + } return "消息记录已清空"; - } /*else if (content.replace(ChatConstant.BLANK, "").startsWith(ChatConstant.CHANGE_MODEL)) { - content = content.replace(ChatConstant.BLANK, ""); - modelCode = content.substring(4); - ConfigUtil.modelCodeChange(modelCode); - return "聊天模型切换为: " + modelCode; - } */ else if (AIConstant.CURRENT_MODEL.equals(content.replace(ChatConstant.BLANK, ""))) { + } else if (AIConstant.CURRENT_MODEL.equals(content.replace(ChatConstant.BLANK, ""))) { String modelName = customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[0]; return "当前模型为: " + modelName; } @@ -121,15 +133,18 @@ public class AIUtil { } String modelName = customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[0]; synchronized (userCustomMessages.get(id)) { - return getChatResponse(id, content, url, modelName, userLatestTimeOfCustom, chatCommand); + return getChatResponse(id, content, url, modelName, chatCommand); } } public static String defaultChat(Long id, String content, String url) { if (ChatConstant.CLEAR.equals(content.replace(ChatConstant.BLANK, ""))) { + if (!userDefaultMessages.containsKey(id)) { + return "不存在消息记录"; + } userDefaultMessages.remove(id); return "消息记录已清空"; - }else if (ChatConstant.CURRENT_MODEL.equals(content.replace(ChatConstant.BLANK, ""))) { + } else if (ChatConstant.CURRENT_MODEL.equals(content.replace(ChatConstant.BLANK, ""))) { return "当前模型为: " + defaultModel; } //查看本次id是否有记录存在 @@ -143,7 +158,7 @@ public class AIUtil { userDefaultMessages.put(id, chatMessages); } synchronized (userDefaultMessages.get(id)) { - return getChatResponse(id, content, url, defaultModel, userLatestTimeOfDefault, null); + return getChatResponse(id, content, url, defaultModel, null); } } @@ -167,7 +182,7 @@ public class AIUtil { } } } - String requestId = REQUEST_ID_TEMPLATE + "_once_"+System.currentTimeMillis(); + String requestId = REQUEST_ID_TEMPLATE + "_once_" + System.currentTimeMillis(); List messages = new ArrayList<>(); messages.add(new ChatMessage(ChatMessageRole.USER.value(), content)); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() @@ -179,7 +194,7 @@ public class AIUtil { .build(); ModelApiResponse invokeModelApiResp = CLIENT.invokeModelApi(chatCompletionRequest); int code = invokeModelApiResp.getCode(); - if (code == 200) { + if (code == AIConstant.NORMAL_CODE) { printTokenInfo(invokeModelApiResp); return invokeModelApiResp.getData().getChoices().get(0).getMessage().getContent().toString(); } else { @@ -209,14 +224,11 @@ public class AIUtil { *
qq1 : [{command1,[msg1.msg2,msg3]},{command2,[msg1,msg2,msg3]},{command3,[msg1,msg2,msg3]}] *
qq2 : [{command1,[msg1.msg2,msg3]},{command2,[msg1,msg2,msg3]},{command3,[msg1,msg2,msg3]}] *
- * @param userLatestTime 最近操作时间 - * @param chatCommand + * @param chatCommand 聊天指令 * @return 得到的模型响应内容 */ - private static String getChatResponse(Long id, String content, String url, String model, HashMap userLatestTime, String chatCommand) { - userLatestTime.put(id, System.currentTimeMillis()); - - String requestId = REQUEST_ID_TEMPLATE + "_"+ model + "_" + System.currentTimeMillis(); + private static String getChatResponse(Long id, String content, String url, String model, String chatCommand) { + String requestId = REQUEST_ID_TEMPLATE + "_" + model + "_" + System.currentTimeMillis(); //处理url内容 String result = ""; if (url != null) { @@ -236,10 +248,11 @@ public class AIUtil { } logger.info("final content:" + content); - //根据primaryUserMessages中的内容来定义userMessages + //根据primaryUserMessages中的内容来定义userMessages并更新latestTime List chatMessages = null; if (chatCommand == null) { chatMessages = userDefaultMessages.get(id); + userLatestTimeOfDefault.put(id, System.currentTimeMillis()); } else { List userCustomMessageList = userCustomMessages.get(id); for (UserCustomMessage userCustomMessage : userCustomMessageList) { @@ -249,6 +262,28 @@ public class AIUtil { break; } } + //更新最新操作时间 + boolean found = false; + List userCustomLatestTimeList; + if (userLatestTimeOfCustom.containsKey(id)) { + //如果存在该id对应的任一聊天记录 + userCustomLatestTimeList = userLatestTimeOfCustom.get(id); + for (UserCustomLatestTime userCustomLatestTime : userCustomLatestTimeList) { + if (userCustomLatestTime.getChatCommand().equals(chatCommand)) { + userCustomLatestTime.setLatestTime(System.currentTimeMillis()); + found = true; + break; + } + } + }else { + //如果没有记录存在 + userCustomLatestTimeList = new ArrayList<>(); + userCustomLatestTimeList.add(new UserCustomLatestTime(chatCommand,System.currentTimeMillis())); + userLatestTimeOfCustom.put(id,userCustomLatestTimeList); + } + if (!found) { + userCustomLatestTimeList.add(new UserCustomLatestTime(chatCommand, System.currentTimeMillis())); + } } if (chatMessages == null) { @@ -264,12 +299,11 @@ public class AIUtil { .stream(Boolean.FALSE) .invokeMethod(Constants.invokeMethod) .messages(chatMessages) - .requestId(requestId) - .build(); + .requestId(requestId).build(); ModelApiResponse invokeModelApiResp = CLIENT.invokeModelApi(chatCompletionRequest); int code = invokeModelApiResp.getCode(); - if (code == 200) { + if (code == AIConstant.NORMAL_CODE) { printTokenInfo(invokeModelApiResp); String response = invokeModelApiResp.getData().getChoices().get(0).getMessage().getContent().toString(); chatMessages.add(new ChatMessage(ChatMessageRole.ASSISTANT.value(), response)); @@ -291,4 +325,20 @@ public class AIUtil { logger.info("total_tokens: " + totalTokens); } + /** + * 清空所有聊天记录 + */ + public static String clearAll() { + int size = 0; + size += userDefaultMessages.size(); + userDefaultMessages.clear(); + userLatestTimeOfDefault.clear(); + + for (Long id : userCustomMessages.keySet()) { + size += userCustomMessages.get(id).size(); + } + userCustomMessages.clear(); + userLatestTimeOfCustom.clear(); + return "本次清空" + size + "条会话"; + } } diff --git a/src/main/java/plugin/utils/ConfigUtil.java b/src/main/java/plugin/utils/ConfigUtil.java index 8687dea..d214525 100644 --- a/src/main/java/plugin/utils/ConfigUtil.java +++ b/src/main/java/plugin/utils/ConfigUtil.java @@ -6,10 +6,13 @@ import net.mamoe.mirai.utils.LoggerAdapters; import net.mamoe.mirai.utils.MiraiLogger; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; +import plugin.constant.ChatConstant; import plugin.constant.ConfigConstant; import plugin.pojo.Config; import java.io.*; +import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; @@ -53,8 +56,12 @@ public class ConfigUtil { config.setBot("your_bot_qq_number(e.g. Q1145141919810)"); config.setTimeout("M3600000"); config.setTimeCheck("M60000"); + ArrayList blacklist = new ArrayList<>(); + blacklist.add(123456789L); + blacklist.add(987654321L); + config.setBlacklist(blacklist); LinkedHashMap commands = new LinkedHashMap<>(); - commands.put("default","glm-4-flash|null"); + commands.put("default", "null"); commands.put("/c ", "glm-4-flash|你是一位智能编程助手,你会为用户回答关于编程、代码、计算机方面的任何问题,并提供格式规范、可以执行、准确安全的代码,并在必要时提供详细的解释。 请用中文回答。"); commands.put("/example ", "模型名称|预设内容"); config.setCustomCommands(commands); @@ -77,31 +84,89 @@ public class ConfigUtil { return config; } - /** - * 配置改变(模型) - * - * @param modelName 模型名称 - */ - public static void defaultModelChange(String modelName) { - try { - config.setDefaultModel(modelName); - dump(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - public static void customModelChange(String command,String modelName) { - try { - String customContent = config.getCustomCommands().get(command).split(ConfigConstant.CUSTOM_SPLIT)[1]; - config.getCustomCommands().put(command,modelName+ConfigConstant.CUSTOM_SPLIT+customContent); - dump(); - } catch (IOException e) { - throw new RuntimeException(e); + public static String customModelChange(String instruction, String customModel) throws IOException { + HashMap customCommands = config.getCustomCommands(); + if (!customCommands.containsKey(instruction)) { + return "该指令不存在!"; } + String customContent = customCommands.get(instruction).split(ConfigConstant.CUSTOM_SPLIT)[1]; + customCommands.put(instruction, customModel + "|" + customContent); + dump(); + return "模型切换成功: [" + instruction + "->" + customCommands.get(instruction) + "]"; } private static void dump() throws IOException { - yaml.dump(BeanUtil.beanToMap(config), new FileWriter(CONFIG_PATH)); + FileWriter writer = new FileWriter(CONFIG_PATH); + yaml.dump(BeanUtil.beanToMap(config), writer); + } + + /** + * 关闭当前群聊发言 + * + * @param id 群聊id + */ + public static String shutUp(long id) { + config.getBlacklist().add(id); + return "ChatAI-InGroup 已关闭"; + } + + /** + * 开启当前群聊发言 + * + * @param id 群聊id + */ + public static String speak(long id) { + config.getBlacklist().remove(id); + return "ChatAI-InGroup 已开启"; + } + + /** + * 添加预设 + * + * @param instruction 指令 + * @param customModel 预设模型 + * @param customContent 预设内容 + * @return 运行结果 + * @throws IOException 配置保存出错 + */ + public static String addCustom(String instruction, String customModel, String customContent) throws IOException { + HashMap customCommands = config.getCustomCommands(); + if (customCommands.containsKey(instruction)) { + return "已存在当前指令! \r\n[" + instruction + "->" + customCommands.get(instruction) + "]"; + } + String content = customModel + "|" + customContent; + customCommands.put(instruction, content); + dump(); + return "预设添加完毕! \r\n[" + instruction + "->" + content + "]"; + } + + /** + * 改变指令对应预设 + * + * @param instruction 指令 + * @param customContent 预设内容 + * @return 运行结果 + */ + public static String customContentChange(String instruction, String customContent) throws IOException { + HashMap customCommands = config.getCustomCommands(); + if (!customCommands.containsKey(instruction)) { + return "该指令不存在!"; + } + String modelName = customCommands.get(instruction).split(ConfigConstant.CUSTOM_SPLIT)[0]; + customCommands.put(instruction, modelName + "|" + customContent); + dump(); + return "预设更改成功! \r\n[" + instruction + "->" + customCommands.get(instruction) + "]"; + } + + public static String removeCustom(String arguments) throws IOException { + HashMap customCommands = getConfig().getCustomCommands(); + if (!customCommands.containsKey(arguments + ChatConstant.BLANK)) { + return "该预设不存在"; + } + String content = customCommands.get(arguments + ChatConstant.BLANK); + customCommands.remove(arguments + ChatConstant.BLANK); + dump(); + return "删除预设[" + arguments + "->" + content + "]成功"; } } diff --git a/src/test/java/MyTest.java b/src/test/java/MyTest.java index f274c8b..2b69613 100644 --- a/src/test/java/MyTest.java +++ b/src/test/java/MyTest.java @@ -10,7 +10,9 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.junit.Test; -import plugin.App; +import plugin.constant.ChatConstant; +import plugin.constant.ConfigConstant; +import plugin.listener.OwnerMessageListener; import plugin.utils.AIUtil; import plugin.utils.ConfigUtil; @@ -20,6 +22,8 @@ import java.lang.reflect.Method; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static kotlin.io.ConsoleKt.readln; + public class MyTest { public static void www(String[] args) { String miraiCode = "看下这个题目[mirai:image:https://multimedia.nt.qq.com.cn/download?appid=1407&fileid=CgoyOTk4ODEzODgyEhQW4G7W3v2lT-NKItOqORRIbuK6rxiZzgcg_woo4u2zytCqiANQgL2jAQ&spec=0&rkey=CAMSKMa3OFokB_Tlf6uVSrtr8zFEBtyDtGIdmuztQCnfO9gIDN19LUsLquI]"; @@ -139,13 +143,44 @@ public class MyTest { } @Test - public void mainTest() throws ClassNotFoundException, IOException { + public void ownerTest() throws ClassNotFoundException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { ConfigUtil.load(); - Long id = 2998813882L; - String content = "hello"; + Class clazz = OwnerMessageListener.class; + Method handleCommand = clazz.getDeclaredMethod("handleCommand", String.class, String.class); + handleCommand.setAccessible(true); + while (true){ + String input = readln(); + String command = input.split(ChatConstant.BLANK)[0]; + String arguments = input.split(ChatConstant.BLANK)[1]; + + Object invoke = handleCommand.invoke(clazz.getDeclaredConstructor().newInstance(), command, arguments); + System.out.println(invoke); + } + + } + + @Test + public void chatTest() throws IOException, ClassNotFoundException { + ConfigUtil.load(); + + Long id = 1L; + String content = "你好"; String chatCommand = "/c "; - String s = AIUtil.customChat(id, content, null, chatCommand); - System.out.println(s); + + String customChat = AIUtil.customChat(id, content, null, chatCommand); + System.out.println(customChat); + + String defaultChat = AIUtil.defaultChat(id, content, null); + System.out.println(defaultChat); + + String chatOnce = AIUtil.chatOnce(content, null); + System.out.println(chatOnce); + } + + @Test + public void regexTest(){ + String str = "/c glm"; + System.out.println(str.matches(ConfigConstant.MODEL_CHANGE)); } }