[Change] 将各MessageEvent的消息发送部分分离成单独的MessageSender, 将MessageEvent依赖于对应的MessageSender;

This commit is contained in:
2020-04-19 12:23:02 +08:00
parent 11005b0f6c
commit 084be3970a
4 changed files with 205 additions and 183 deletions

View File

@ -0,0 +1,158 @@
package net.lamgc.cgj.bot.message;
import com.google.common.base.Strings;
import net.lamgc.cgj.bot.BotCode;
import net.lamgc.cgj.bot.MessageSender;
import net.lamgc.cgj.bot.cache.CacheStore;
import net.lamgc.cgj.bot.cache.HotDataCacheStore;
import net.lamgc.cgj.bot.cache.LocalHashCacheStore;
import net.lamgc.cgj.bot.cache.StringRedisCacheStore;
import net.lamgc.cgj.bot.event.BotEventHandler;
import net.mamoe.mirai.contact.Contact;
import net.mamoe.mirai.message.data.CombinedMessage;
import net.mamoe.mirai.message.data.Image;
import net.mamoe.mirai.message.data.Message;
import net.mamoe.mirai.message.data.MessageUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MiraiMessageSender implements MessageSender {
private final Contact member;
private final MessageSource source;
private final static Logger log = LoggerFactory.getLogger("MiraiMessageSender");
private final static CacheStore<String> imageIdCache = new HotDataCacheStore<>(
new StringRedisCacheStore(BotEventHandler.redisServer, "mirai.imageId"),
new LocalHashCacheStore<>(),
5400000, 1800000);
public MiraiMessageSender(Contact member, MessageSource source) {
this.member = member;
this.source = source;
}
@Override
public int sendMessage(final String message) {
log.debug("处理前的消息内容:\n{}", message);
Message msgBody = processMessage(Objects.requireNonNull(message));
log.debug("处理后的消息内容(可能出现乱序的情况, 但实际上顺序是没问题的):\n{}", msgBody);
member.sendMessage(msgBody);
return 0;
}
private final static Pattern cqCodePattern = BotCode.getCodePattern();
private Message processMessage(final String message) {
Matcher matcher = cqCodePattern.matcher(message);
ArrayList<String> cqCode = new ArrayList<>();
while (matcher.find()) {
cqCode.add(matcher.group());
}
String[] texts = message
.replaceAll("&", "&38")
.replaceAll("\\{", "&" + Character.getNumericValue('{'))
.replaceAll(cqCodePattern.pattern(), "|{BotCode}|")
.replaceAll("&" + Character.getNumericValue('{'), "{")
.replaceAll("&38", "&")
.split("\\|");
CombinedMessage chain = MessageUtils.newChain().plus("");
int codeIndex = 0;
for(String text : texts) {
if(text.equals("{BotCode}")) {
BotCode code;
try {
code = BotCode.parse(cqCode.get(codeIndex++));
} catch(IllegalArgumentException e) {
log.warn("解析待发送消息内的BotCode时发生异常, 请检查错误格式BotCode的来源并尽快排错!", e);
continue;
}
chain = chain.plus(processBotCode(code));
} else {
chain = chain.plus(text);
}
}
return chain;
}
private Message processBotCode(BotCode code) {
switch(code.getFunctionName().toLowerCase()) {
case "image":
if(code.containsParameter("id")) {
return MessageUtils.newImage(code.getParameter("id"));
} else if(code.containsParameter("absolutePath")) {
return uploadImage(code);
} else {
return MessageUtils.newChain("(参数不存在)");
}
default:
log.warn("解析到不支持的BotCode: {}", code);
return MessageUtils.newChain("(不支持的BotCode)");
}
}
/**
* 存在缓存的上传图片.
* @param code 图片BotCode
* @return Image对象
*/
public Image uploadImage(BotCode code) {
log.debug("传入BotCode信息:\n{}", code);
String absolutePath = code.getParameter("absolutePath");
if(Strings.isNullOrEmpty(absolutePath)) {
throw new IllegalArgumentException("BotCode does not contain the absolutePath parameter");
}
String imageName = code.getParameter("imageName");
if(!Strings.isNullOrEmpty(imageName)) {
Image image = null;
imageName = (source + "." + imageName).intern();
if(!imageIdCache.exists(imageName) ||
Strings.nullToEmpty(code.getParameter("updateCache")).equalsIgnoreCase("true")) {
synchronized (imageName) {
if(!imageIdCache.exists(imageName) ||
Strings.nullToEmpty(code.getParameter("updateCache")) .equalsIgnoreCase("true")) {
log.debug("imageName [{}] 缓存失效或强制更新, 正在更新缓存...", imageName);
image = uploadImage0(new File(absolutePath));
String cacheExpireAt;
long expireTime = 0;
if(!Strings.isNullOrEmpty(cacheExpireAt = code.getParameter("cacheExpireAt"))) {
try {
expireTime = Integer.parseInt(cacheExpireAt);
} catch (NumberFormatException e) {
log.warn("BotCode中的cacheExpireAt参数无效: {}", cacheExpireAt);
}
}
imageIdCache.update(imageName, image.getImageId(), expireTime);
log.info("imageName [{}] 缓存更新完成.(有效时间: {})", imageName, expireTime);
} else {
log.debug("ImageName: [{}] 缓存命中.", imageName);
}
}
} else {
log.debug("ImageName: [{}] 缓存命中.", imageName);
}
if(image == null) {
image = MessageUtils.newImage(imageIdCache.getCache(imageName));
}
log.debug("ImageName: {}, ImageId: {}", imageName, image.getImageId());
return image;
} else {
log.debug("未设置imageName, 无法使用缓存.");
return uploadImage0(new File(absolutePath));
}
}
private Image uploadImage0(File imageFile) {
return member.uploadImage(imageFile);
}
}

View File

@ -0,0 +1,31 @@
package net.lamgc.cgj.bot.message;
import net.lamgc.cgj.bot.MessageSender;
import net.lz1998.cq.robot.CoolQ;
public class SpringCQMessageSender implements MessageSender {
private CoolQ coolQ;
private MessageSource source;
private long target;
public SpringCQMessageSender(CoolQ coolQ, MessageSource source, long target) {
this.coolQ = coolQ;
this.source = source;
this.target = target;
}
@Override
public int sendMessage(String message) {
switch (source) {
case Private:
return coolQ.sendPrivateMsg(target, message, false).getData().getMessageId();
case Group:
return coolQ.sendGroupMsg(target, message, false).getData().getMessageId();
case Discuss:
return coolQ.sendDiscussMsg(target, message, false).getData().getMessageId();
default:
return -1;
}
}
}