Skip to content

Commit

Permalink
[qqrobot] version:2.10.4_0_0
Browse files Browse the repository at this point in the history
1. 添加并完成新功能 “MD5工具”
2. 添加并完成新功能 “URL/URI转码/解码”
3. 添加并完成新功能 “Unicode转码/解码”
4. 添加Mirai转义字符反斜杠([  ]  :  , \),修改了 去转义 方法以适应反斜杠的正则匹配Matcher.quoteReplacement("\\")
  • Loading branch information
Ultronxr committed Mar 6, 2022
1 parent 5f82922 commit b732d9e
Show file tree
Hide file tree
Showing 11 changed files with 460 additions and 21 deletions.
2 changes: 1 addition & 1 deletion qqrobot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>cn.ultronxr</groupId>
<artifactId>qqrobot</artifactId>
<version>2.10.3_0_0</version>
<version>2.10.4_0_0</version>
<name>qqrobot</name>
<description>A QQ Robot based on Mirai framework.</description>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ public class BotMenuConfig {
@Autowired
private MsgQRCodeHandler msgQRCodeHandler;

@Autowired
private MsgCodeToolkitHandler msgCodeToolkitHandler;


/**
* 初始化BOT命令菜单BotMenu
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cn.ultronxr.qqrobot.eventHandler;

import cn.ultronxr.qqrobot.bean.BotCmd;
import net.mamoe.mirai.event.events.GroupMessageEvent;
import org.apache.commons.cli.CommandLine;

/**
* @author Ultronxr
* @date 2022/02/18 13:33
*
* 消息事件 - 有关各种代码小工具的Handler,包括MD5、SHA-1、等等
*/
public interface MsgCodeToolkitHandler {

/**
* 套用BotCmd/BotMenu框架
* 群聊中的 MD5 命令处理器
*
* @param botCmd 匹配成功的命令BotCmd对象
* @param cmdLine 解析完成的CommandLine对象
* @param groupMsgEvent 群消息事件
* @param msgPlain 纯消息主体文本内容(MiraiUtils自定义消息类型三)
* {@link cn.ultronxr.qqrobot.util.MiraiUtils#getMsgPlain(net.mamoe.mirai.event.events.MessageEvent)}
*/
void groupMD5Handler(BotCmd botCmd, CommandLine cmdLine, GroupMessageEvent groupMsgEvent, String msgPlain);

/**
* 套用BotCmd/BotMenu框架
* 群聊中的 URL转码/解码 命令处理器
*
* @param botCmd 匹配成功的命令BotCmd对象
* @param cmdLine 解析完成的CommandLine对象
* @param groupMsgEvent 群消息事件
* @param msgPlain 纯消息主体文本内容(MiraiUtils自定义消息类型三)
* {@link cn.ultronxr.qqrobot.util.MiraiUtils#getMsgPlain(net.mamoe.mirai.event.events.MessageEvent)}
*/
void groupURLHandler(BotCmd botCmd, CommandLine cmdLine, GroupMessageEvent groupMsgEvent, String msgPlain);

/**
* 套用BotCmd/BotMenu框架
* 群聊中的 Unicode转码/解码 命令处理器
*
* @param botCmd 匹配成功的命令BotCmd对象
* @param cmdLine 解析完成的CommandLine对象
* @param groupMsgEvent 群消息事件
* @param msgPlain 纯消息主体文本内容(MiraiUtils自定义消息类型三)
* {@link cn.ultronxr.qqrobot.util.MiraiUtils#getMsgPlain(net.mamoe.mirai.event.events.MessageEvent)}
*/
void groupUnicodeHandler(BotCmd botCmd, CommandLine cmdLine, GroupMessageEvent groupMsgEvent, String msgPlain);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package cn.ultronxr.qqrobot.eventHandler.eventHandlerImpl;

import cn.ultronxr.qqrobot.bean.BotCmd;
import cn.ultronxr.qqrobot.eventHandler.MsgCodeToolkitHandler;
import cn.ultronxr.qqrobot.util.CommonCliUtils;
import cn.ultronxr.qqrobot.util.MD5Utils;
import lombok.extern.slf4j.Slf4j;
import net.mamoe.mirai.event.events.GroupMessageEvent;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriUtils;

import java.util.Locale;

/**
* @author Ultronxr
* @date 2022/02/18 13:34
*/
@Component
@Slf4j
public class MsgCodeToolkitHandlerImpl implements MsgCodeToolkitHandler {


@Override
public void groupMD5Handler(BotCmd botCmd, CommandLine cmdLine, GroupMessageEvent groupMsgEvent, String msgPlain) {
if(cmdLine.hasOption("help")) {
// 优先判断 --help 选项
CommonCliUtils.defaultOptionHelper(groupMsgEvent, botCmd);
return;
}

String plainText = null, salt = null, msgRes = null;
if(cmdLine.getOptions().length == 0 && cmdLine.getArgList().size() == 2) {
// 无任何选项,但有参数,直接取arg1作为-p选项参数 (如:“>md5 123abc” )
plainText = cmdLine.getArgList().get(1);
msgRes = MD5Utils.md5(plainText);
} else if(cmdLine.hasOption("p")) {
// 有plainText选项
plainText = cmdLine.getOptionValue("p");
if(cmdLine.hasOption("s")) {
// 且有salt选项
salt = cmdLine.getOptionValue("s");
msgRes = MD5Utils.md5WithSalt(plainText, salt);
} else {
msgRes = MD5Utils.md5(plainText);
}
}
if(StringUtils.isEmpty(msgRes)) {
// msgRes还是empty,说明不符合任何情况
CommonCliUtils.defaultOptionExceptionHandler(groupMsgEvent);
return;
}
if(cmdLine.hasOption("U")) {
// 转化为大写
msgRes = msgRes.toUpperCase(Locale.ENGLISH);
}
log.info("[Function] 文本:{}\n盐值:{}\nMD5结果:{}", plainText, salt, msgRes);

groupMsgEvent.getSubject().sendMessage(msgRes);
log.info("[Msg-Send] {}", msgRes);
}

@Override
public void groupURLHandler(BotCmd botCmd, CommandLine cmdLine, GroupMessageEvent groupMsgEvent, String msgPlain) {
if(cmdLine.hasOption("help")) {
// 优先判断 --help 选项
CommonCliUtils.defaultOptionHelper(groupMsgEvent, botCmd);
return;
}

String msgRes = null, url = null;
if(cmdLine.hasOption("e")) {
// 转码参数 -e
if(cmdLine.hasOption("d")) {
//且出现了解码参数 -d ,直接报错
CommonCliUtils.defaultOptionHelper(groupMsgEvent, botCmd);
return;
}
url = cmdLine.getOptionValue("e");
if(cmdLine.hasOption("c")) {
msgRes = UriUtils.encode(url, "UTF-8");
} else {
msgRes = UriUtils.encodeQuery(url, "UTF-8");
}
} else if(cmdLine.hasOption("d")) {
// 解码参数 -d
url = cmdLine.getOptionValue("d");
msgRes = UriUtils.decode(url, "UTF-8");
} else {
CommonCliUtils.defaultOptionExceptionHandler(groupMsgEvent);
return;
}
log.info("[Function] 文本:{}\nURL转码/解码结果:{}", url, msgRes);

groupMsgEvent.getSubject().sendMessage(msgRes);
log.info("[Msg-Send] {}", msgRes);
}

@Override
public void groupUnicodeHandler(BotCmd botCmd, CommandLine cmdLine, GroupMessageEvent groupMsgEvent, String msgPlain) {
if(cmdLine.hasOption("help")) {
// 优先判断 --help 选项
CommonCliUtils.defaultOptionHelper(groupMsgEvent, botCmd);
return;
}

String plainText = null, msgRes = null;
if(cmdLine.hasOption("e")) {
if(cmdLine.hasOption("d")) {
//且出现了解码参数 -d ,直接报错
CommonCliUtils.defaultOptionHelper(groupMsgEvent, botCmd);
return;
}
plainText = cmdLine.getOptionValue("e");
msgRes = cn.ultronxr.qqrobot.util.StringUtils.native2Unicode(plainText);
} else if(cmdLine.hasOption("d")) {
plainText = cmdLine.getOptionValue("d");
msgRes = cn.ultronxr.qqrobot.util.StringUtils.unicode2Native(plainText);
} else {
CommonCliUtils.defaultOptionExceptionHandler(groupMsgEvent);
return;
}
log.info("[Function] 文本:{}\nUnicode转码/解码结果:{}", plainText, msgRes);

groupMsgEvent.getSubject().sendMessage(msgRes);
log.info("[Msg-Send] {}", msgRes);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void groupQRCodeHandler(BotCmd botCmd, CommandLine cmdLine, GroupMessageE
String msgRes = "";
String content = null;
// 无任何选项时
if(cmdLine.getOptions().length == 0 && cmdLine.getArgList().size() > 1) {
if(cmdLine.getOptions().length == 0 && cmdLine.getArgList().size() == 2) {
// 如果无选项但带了arg1参数,如 ">qr 待转换成二维码的文本内容"
content = cmdLine.getArgList().get(1);
} else if(cmdLine.hasOption("e")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,4 @@ public void groupRobotMenuHandler(BotCmd botCmd, CommandLine cmdLine, GroupMessa
log.info("[Msg-Send] {}", BotMenu.getMenuText());
}

//put(0, new String[]{"功能", "菜单"});
//put(9, new String[]{"群成员入群、退群监控"});
//put(1, new String[]{"ping"});
//put(13, new String[]{">"});
//put(2, new String[]{"天气"});
////put(3, new String[]{"定时", "定时格式", "定时说明"});
//put(4, new String[]{"phub"});
//put(5, new String[]{"舔狗", "彩虹屁"});
//put(6, new String[]{"脏话", "口吐芬芳", "芬芳"});
//put(7, new String[]{"火力全开"});
//put(8, new String[]{"随机数", "random"});
//put(10, new String[]{"磁力", "种子", "车牌", "magnet"});
//put(11, new String[]{"所有群活跃"});
//put(12, new String[]{"群活跃", "水群排行", "水群排名"});

}
64 changes: 64 additions & 0 deletions qqrobot/src/main/java/cn/ultronxr/qqrobot/util/MD5Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package cn.ultronxr.qqrobot.util;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.util.DigestUtils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
* @author Ultronxr
* @date 2022/02/18 12:34
*/
@Slf4j
public class MD5Utils {

/**
* 返回32位的MD5结果
* @param plainText 待加密文本
* @return {@code String} 32位MD5结果
*/
public static String md5(@NotNull String plainText) {
return DigestUtils.md5DigestAsHex(plainText.getBytes());
}

/**
* 返回32位的MD5结果(加盐salt)
* @param plainText 待加密文本
* @param salt 盐值
* @return {@code String} 32位MD5结果
*/
public static String md5WithSalt(@NotNull String plainText, @NotNull String salt) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
log.error("[Function] 无法获取MD5算法实例!");
return "";
}
if(StringUtils.isNotEmpty(salt)) {
md.update(salt.getBytes());
}
md.update(plainText.getBytes());
return encodeHex(md.digest());
}

/**
* 把字节数组转化成16进制字符串
* @param byteData md5的结果字节数组
* @return 16进制字符串
* @see org.springframework.util.DigestUtils#encodeHex(byte[])
*/
private static String encodeHex(byte[] byteData) {
StringBuilder sb = new StringBuilder();
for (byte byteD : byteData) {
sb.append(Integer.toString((byteD & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}

}
18 changes: 14 additions & 4 deletions qqrobot/src/main/java/cn/ultronxr/qqrobot/util/MiraiUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import net.mamoe.mirai.message.data.At;
import org.jetbrains.annotations.NotNull;

import java.util.regex.Matcher;

/**
* @author Ultronxr
* @date 2020/12/31 15:03
Expand All @@ -19,11 +21,12 @@
public class MiraiUtils extends GlobalData {

/**
* Mirai会在消息内容中转义的符号 , : [ ]
* 上面的符号会在msgCode和msgPlain中显示为 \, \: \[ \]
* Mirai会在消息内容中转义的符号 [ ] : , \
* 上面的符号会在msgCode和msgPlain中显示为 \[ \] \: \, \\
* 所以需要把它们去掉反斜杠,转义回来
* @link https://github.com/mamoe/mirai/blob/dev/docs/Messages.md#%E8%BD%AC%E4%B9%89%E8%A7%84%E5%88%99
*/
public static final String MIRAI_PUNCTUATION = "\\\\[,:\\[\\]]";
public static final String MIRAI_PUNCTUATION = "\\\\[\\[\\]:,\\\\]";

/*
* 以下自定义了三种Mirai消息类别:
Expand Down Expand Up @@ -96,7 +99,14 @@ public static String getMsgStr(@NotNull MessageEvent msgEvent){
*/
public static String escapeMiraiPunctuation(String msg){
return ReUtil.replaceAll(msg, MIRAI_PUNCTUATION,
matcher -> matcher.group().replaceFirst("\\\\", ""));
matcher -> matcher.group().replaceFirst("\\\\", Matcher.quoteReplacement("\\")));
// 这里需要使用 Matcher.quoteReplacement("\\") 方法,不能直接用 "" ,如下是对这个问题的解释:
// 当 "\," "\[" 等([]:,)被替换掉反斜杠,留下符号自身 "," "[" 时没有问题,
// 但 "\\" 被替换掉反斜杠,留下符号自身 "\" 时,会被认为是转义符号,从而抛出“character to be escaped is missing”缺少转义内容的异常。
// 官方文档:
// Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string; see Matcher.replaceFirst.
// Use Matcher.quoteReplacement to suppress the special meaning of these characters, if desired.
// Slashes ('\') and dollar signs ('$') will be given no special meaning.
}


Expand Down
39 changes: 39 additions & 0 deletions qqrobot/src/main/java/cn/ultronxr/qqrobot/util/StringUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package cn.ultronxr.qqrobot.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author Ultronxr
* @date 2021/04/30 18:11
Expand All @@ -23,4 +26,40 @@ public static String cutOffStringOverLength(String string, int length) {
return string.substring(0, length);
}


/**
* 把字符串转换为 Unicode编码形式
* 例:汉字abc123.,! -> \u6c49\u5b57\u0061\u0062\u0063\u0031\u0032\u0033\u002e\u002c\u0021
* @param plainText 待转换的文本
* @return Unicode编码形式字符串
*/
public static String native2Unicode(String plainText) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < plainText.length(); i++){
String hexStr = Integer.toString((int)plainText.charAt(i), 16);
sb.append("\\u");
sb.append("0".repeat(Math.max(0, 4 - hexStr.length())));
sb.append(hexStr);
}
return sb.toString();
}

/**
* 把 Unicode编码形式的字符串 转换为 正常可读的文本
* 例:\u6c49\u5b57\u0061\u0062\u0063\u0031\u0032\u0033\u002e\u002c\u0021 -> 汉字abc123.,!
* @param unicode Unicode编码形式的字符串
* @return 正常可读的文本
*/
public static String unicode2Native(String unicode) {
Pattern pattern = Pattern.compile("(\\\\u(\\w{4}))");
Matcher matcher = pattern.matcher(unicode);
while (matcher.find()) {
String unicodeFull = matcher.group(1);
String unicodeNum = matcher.group(2);
char singleChar = (char) Integer.parseInt(unicodeNum, 16);
unicode = unicode.replace(unicodeFull, String.valueOf(singleChar));
}
return unicode;
}

}
Loading

0 comments on commit b732d9e

Please sign in to comment.