feat: adding dto class and add json handle system

This commit is contained in:
wzp 2024-08-04 02:23:40 +08:00
parent be18927b3c
commit 4ba6db2777
43 changed files with 1194 additions and 55 deletions

View File

@ -1 +1 @@
0.0.2-dev
0.0.3-dev

11
.idea/misc.xml generated
View File

@ -1,10 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ASMSmaliIdeaPluginConfiguration">
<asm skipDebug="true" skipFrames="true" skipCode="false" expandFrames="false" />
<groovy codeStyle="LEGACY" />
</component>
<component name="EntryPointsManager">
<list size="1">
<item index="0" class="java.lang.String" itemvalue="com.alibaba.fastjson2.annotation.JSONField" />
</list>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -4,7 +4,7 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCach
val projectName = rootProject.name
val groupName by extra("cn.wzpmc")
val projectArtifactId by extra("my-bot")
val projectVersion by extra("0.0.2-dev")
val projectVersion by extra("0.0.3-dev")
plugins {
id("java")

View File

@ -6,6 +6,7 @@ import cn.wzpmc.console.MyBotConsole;
import cn.wzpmc.entities.user.bot.MyBot;
import cn.wzpmc.network.WebSocketConnectionHandler;
import cn.wzpmc.plugins.CommandManager;
import cn.wzpmc.utils.JsonUtils;
import cn.wzpmc.utils.TemplateFileUtils;
import cn.wzpmc.utils.YamlUtils;
import io.netty.channel.ChannelFuture;
@ -23,6 +24,8 @@ public class Main {
public static void main(String[] args) {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
System.setProperty("terminal.jline", "true");
JsonUtils.initReader();
JsonUtils.initWriter();
log.info("启动MyBot...");
File configurationFile = new File("config.yaml");
if (TemplateFileUtils.saveDefaultConfig(Main.class.getClassLoader(), DEFAULT_CONFIGURATION_FILE_PATH, configurationFile)) {

View File

@ -1,5 +1,10 @@
package cn.wzpmc.api.events;
import cn.wzpmc.api.events.message.MessageEvent;
import cn.wzpmc.api.events.meta.MetaEvent;
import cn.wzpmc.api.events.notice.NoticeEvent;
import cn.wzpmc.api.events.request.RequestEvent;
/**
* 事件类型
* @author wzp
@ -11,20 +16,24 @@ public enum EventPostType {
* 消息事件
* @since 2024/8/1 下午5:48 v0.0.2-dev
*/
MESSAGE,
MESSAGE(MessageEvent.class),
/**
* 通知事件
* @since 2024/8/1 下午5:47 v0.0.2-dev
*/
NOTICE,
NOTICE(NoticeEvent.class),
/**
* 请求事件
* @since 2024/8/1 下午5:47 v0.0.2-dev
*/
REQUEST,
REQUEST(RequestEvent.class),
/**
* 元事件
* @since 2024/8/1 下午5:47 v0.0.2-dev
*/
META_EVENT,
META_EVENT(MetaEvent.class);
public final Class<? extends Event> clazz;
EventPostType(Class<? extends Event> clazz){
this.clazz = clazz;
}
}

View File

@ -1,7 +1,8 @@
package cn.wzpmc.api.events.message;
import cn.wzpmc.api.events.Event;
import cn.wzpmc.api.message.MessageComponent;
import cn.wzpmc.api.message.StringMessage;
import cn.wzpmc.api.message.json.JsonMessage;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -47,13 +48,13 @@ public class MessageEvent<E, U> extends Event {
* 消息详细内容
* @since 2024/8/1 下午11:11 v0.0.2-dev
*/
private MessageComponent message;
private JsonMessage message;
/**
* 文本格式消息
* @since 2024/8/1 下午11:11 v0.0.2-dev
*/
@JSONField(name = "raw_message")
private String rawMessage;
private StringMessage rawMessage;
/**
* 消息使用字体
* @since 2024/8/1 下午11:11 v0.0.2-dev

View File

@ -1,6 +1,12 @@
package cn.wzpmc.api.message;
import lombok.RequiredArgsConstructor;
import cn.wzpmc.api.message.json.JsonMessagePart;
import cn.wzpmc.api.message.json.parts.PartType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 纯文本消息
@ -8,9 +14,12 @@ import lombok.RequiredArgsConstructor;
* @version 0.0.1-dev
* @since 2024/7/31 上午2:34
*/
@RequiredArgsConstructor
public class StringMessage implements MessageComponent{
private final String message;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StringMessage implements MessageComponent, JsonMessagePart {
@JSONField(name = "text")
private String message;
@Override
public String toMessageString() {
return this.message;
@ -26,4 +35,24 @@ public class StringMessage implements MessageComponent{
public static StringMessage text(String message){
return new StringMessage(message);
}
@Override
public PartType getPartType() {
return PartType.TEXT;
}
@Override
public JSONObject getData() {
return JSONObject.of("text", this.message);
}
@Override
public String getTextDisplay() {
return this.message;
}
@Override
public String getCQCode() {
return this.message;
}
}

View File

@ -2,6 +2,7 @@ package cn.wzpmc.api.message.json;
import cn.wzpmc.api.message.MessageComponent;
import com.alibaba.fastjson2.JSON;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@ -13,6 +14,7 @@ import java.util.stream.Collectors;
* @version 0.0.1-dev
* @since 2024/7/31 上午2:34
*/
@Data
public class JsonMessage implements MessageComponent {
private final List<JsonMessagePart> messageParts = new ArrayList<>();
@Override
@ -22,4 +24,16 @@ public class JsonMessage implements MessageComponent {
public String toTextDisplay() {
return this.messageParts.stream().map(JsonMessagePart::getTextDisplay).collect(Collectors.joining(""));
}
/**
* 将JSON消息转换为CQ文本消息
* @author wzp
* @since 2024/8/2 下午9:36 v0.0.3-dev
* @return 文本消息
*/
public String toCqString(){
StringBuilder stringBuilder = new StringBuilder();
this.messageParts.stream().map(JsonMessagePart::getCQCode).forEach(stringBuilder::append);
return stringBuilder.toString();
}
}

View File

@ -1,6 +1,9 @@
package cn.wzpmc.api.message.json;
import java.util.Map;
import cn.wzpmc.api.message.json.parts.PartType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
/**
* JSON消息段
@ -8,14 +11,19 @@ import java.util.Map;
* @version 0.0.1-dev
* @since 2024/7/31 上午2:36
*/
@JSONType(includes = {"type", "data"})
public interface JsonMessagePart {
/**
* 获取消息的类型
* @author wzp
* @since 2024/7/31 上午2:40 v0.0.1-dev
* @return 消息类型字符串
* @return 消息类型
*/
String getType();
PartType getPartType();
@JSONField(name = "type")
default String getStringPartType(){
return this.getPartType().toString().toLowerCase();
}
/**
* 获取消息附带的数据
@ -23,7 +31,7 @@ public interface JsonMessagePart {
* @since 2024/7/31 上午2:40 v0.0.1-dev
* @return 数据
*/
Map<String, String> getData();
JSONObject getData();
/**
* 获取当纯文本界面的代替文本
@ -33,14 +41,31 @@ public interface JsonMessagePart {
*/
default String getTextDisplay(){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(this.getType())
stringBuilder.append(this.getPartType())
.append('(')
.append('\n');
Map<String, String> data = this.getData();
JSONObject data = this.getData();
data.forEach((key, value) -> stringBuilder.append('\t').append(key).append('=').append(value).append(',').append('\n'));
int length = stringBuilder.length();
stringBuilder.delete(length - 2, length - 1);
stringBuilder.append(')');
return stringBuilder.toString();
}
/**
* 获取消息段的CQ码
* @author wzp
* @since 2024/8/2 下午9:32 v0.0.3-dev
* @return CQ码
*/
default String getCQCode(){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[CQ:").append(this.getPartType().toString().toLowerCase()).append(',');
JSONObject data = getData();
data.forEach((key, value) -> stringBuilder.append(key).append('=').append(value).append(','));
int lastSplit = stringBuilder.length() - 1;
stringBuilder.deleteCharAt(lastSplit);
stringBuilder.append(']');
return stringBuilder.toString();
}
}

View File

@ -0,0 +1,31 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 匿名发消息
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:19
*/
@Data
@NoArgsConstructor
public class Anonymous implements JsonMessagePart {
/**
* 可选表示无法匿名时是否继续发送
* @since 2024/8/3 下午5:55 v0.0.3-dev
*/
private boolean ignore = false;
@Override
public PartType getPartType() {
return PartType.ANONYMOUS;
}
@Override
public JSONObject getData() {
return JSONObject.of("ignore", this.ignore);
}
}

View File

@ -0,0 +1,31 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* JSON 消息
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:43
*/
@Data
@NoArgsConstructor
public class CustomJSONMessage implements JsonMessagePart {
/**
* JSON 内容
* @since 2024/8/3 下午6:11 v0.0.3-dev
*/
private JSONObject data;
@Override
public PartType getPartType() {
return PartType.JSON;
}
@Override
public JSONObject getData() {
return JSONObject.of("data", this.data);
}
}

View File

@ -0,0 +1,32 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* QQ表情
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:00
*/
@Data
@NoArgsConstructor
public class Face implements JsonMessagePart {
/**
* <a href="https://github.com/richardchien/coolq-http-api/wiki/%E8%A1%A8%E6%83%85-CQ-%E7%A0%81-ID-%E8%A1%A8">qq表情ID</a>
* @since 2024/8/2 下午11:46 v0.0.3-dev
*/
private Short id;
@Override
public PartType getPartType() {
return PartType.FACE;
}
@Override
public JSONObject getData() {
return JSONObject.of("face", id);
}
}

View File

@ -0,0 +1,31 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 合并转发
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:38
*/
@Data
@NoArgsConstructor
public class Forward implements JsonMessagePart {
/**
* 合并转发 ID需通过 get_forward_msg API 获取具体内容
* @since 2024/8/3 下午6:10 v0.0.3-dev
*/
private Long id;
@Override
public PartType getPartType() {
return PartType.FORWARD;
}
@Override
public JSONObject getData() {
return JSONObject.of("id", this.id);
}
}

View File

@ -0,0 +1,50 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 位置
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:22
*/
@Data
@NoArgsConstructor
public class Location implements JsonMessagePart {
/**
* 纬度
* @since 2024/8/3 下午6:06 v0.0.3-dev
*/
private Double lat;
/**
* 经度
* @since 2024/8/3 下午6:07 v0.0.3-dev
*/
private Double lon;
/**
* 发送时可选标题
* @since 2024/8/3 下午6:07 v0.0.3-dev
*/
private String title = "";
/**
* 发送时可选内容描述
* @since 2024/8/3 下午6:07 v0.0.3-dev
*/
private String content = "";
@Override
public PartType getPartType() {
return PartType.LOCATION;
}
@Override
public JSONObject getData() {
return new JSONObject()
.fluentPut("lat", this.lat)
.fluentPut("lon", this.lon)
.fluentPut("title", this.title)
.fluentPut("content", this.content);
}
}

View File

@ -0,0 +1,40 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.StringMessage;
import cn.wzpmc.api.message.json.JsonMessagePart;
import cn.wzpmc.api.message.json.parts.contact.Contact;
import cn.wzpmc.api.message.json.parts.music.Music;
import cn.wzpmc.api.message.json.parts.node.Node;
import cn.wzpmc.api.message.json.parts.poke.Poke;
/**
* 消息段类型
* @author wzp
* @since 2024/8/3 下午6:18
* @version 0.0.3-dev */
public enum PartType {
TEXT(StringMessage.class),
FACE(Face.class),
IMAGE(Image.class),
RECORD(Record.class),
VIDEO(Video.class),
AT(At.class),
RPS(cn.wzpmc.api.message.json.parts.RPS.class),
DICE(Dice.class),
SHAKE(Shake.class),
POKE(Poke.class),
ANONYMOUS(Anonymous.class),
SHARE(Share.class),
CONTACT(Contact.class),
LOCATION(Location.class),
MUSIC(Music.class),
REPLY(Reply.class),
FORWARD(Forward.class),
NODE(Node.class),
XML(XMLMessage.class),
JSON(CustomJSONMessage.class);
public final Class<? extends JsonMessagePart> clazz;
PartType(Class<? extends JsonMessagePart> clazz){
this.clazz = clazz;
}
}

View File

@ -0,0 +1,26 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 拳魔法表情
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:17
*/
@Data
@NoArgsConstructor
public class RPS implements JsonMessagePart {
@Override
public PartType getPartType() {
return PartType.RPS;
}
@Override
public JSONObject getData() {
return JSONObject.of();
}
}

View File

@ -0,0 +1,31 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 回复
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:33
*/
@Data
@NoArgsConstructor
public class Reply implements JsonMessagePart {
/**
* 回复时引用的消息 ID
* @since 2024/8/3 下午6:08 v0.0.3-dev
*/
private Long id;
@Override
public PartType getPartType() {
return PartType.REPLY;
}
@Override
public JSONObject getData() {
return JSONObject.of("id", id);
}
}

View File

@ -0,0 +1,27 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 窗口抖动戳一戳
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:18
*/
@Data
@NoArgsConstructor
public class Shake implements JsonMessagePart {
@Override
public PartType getPartType() {
return PartType.SHAKE;
}
@Override
public JSONObject getData() {
return JSONObject.of();
}
}

View File

@ -0,0 +1,53 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.net.URL;
/**
* 短视频
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:16
*/
@Data
@NoArgsConstructor
public class Video implements JsonMessagePart {
/**
* 视频文件名
* @since 2024/8/2 下午11:49 v0.0.3-dev
*/
private String file;
/**
* 视频 URL
* @since 2024/8/2 下午11:49 v0.0.3-dev
*/
private URL url;
/**
* 只在通过网络 URL 发送时有效表示是否使用已缓存的文件默认 true
* @since 2024/8/2 下午11:49 v0.0.3-dev
*/
private Boolean cache = true;
/**
* 只在通过网络 URL 发送时有效表示是否通过代理下载文件需通过环境变量或配置文件配置代理默认 true
* @since 2024/8/2 下午11:49 v0.0.3-dev
*/
private Boolean proxy = true;
/**
* 只在通过网络 URL 发送时有效单位秒表示下载网络文件的超时时间 默认不超时
* @since 2024/8/2 下午11:49 v0.0.3-dev
*/
private Float timeout = null;
@Override
public PartType getPartType() {
return PartType.VIDEO;
}
@Override
public JSONObject getData() {
return null;
}
}

View File

@ -0,0 +1,32 @@
package cn.wzpmc.api.message.json.parts;
import cn.wzpmc.api.message.json.JsonMessagePart;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* XML消息
* @author MoYiJiangNan
* @version 0.0.3-dev
* @since 2024/8/2 下午11:40
*/
@Data
@NoArgsConstructor
public class XMLMessage implements JsonMessagePart {
/**
* XML 内容
* @since 2024/8/3 下午6:11 v0.0.3-dev
*/
private String data;
@Override
public PartType getPartType() {
return PartType.XML;
}
public JSONObject getData() {
return new JSONObject()
.fluentPut("data", data);
}
}

View File

@ -0,0 +1,37 @@
package cn.wzpmc.api.message.json.parts.contact;
import cn.wzpmc.api.message.json.JsonMessagePart;
import cn.wzpmc.api.message.json.parts.PartType;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 推荐好友/
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:21
*/
@Data
@NoArgsConstructor
public class Contact implements JsonMessagePart {
/**
* 推荐类型
* @since 2024/8/3 下午5:57 v0.0.3-dev
*/
private ContactType type;
/**
* 被推荐人的 QQ
* @since 2024/8/3 下午5:57 v0.0.3-dev
*/
private Long id;
@Override
public PartType getPartType() {
return PartType.CONTACT;
}
@Override
public JSONObject getData() {
return JSONObject.of("type", this.type.name().toLowerCase(), "id", this.id);
}
}

View File

@ -0,0 +1,20 @@
package cn.wzpmc.api.message.json.parts.contact;
/**
* 推荐类型
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:34
*/
public enum ContactType {
/**
* 推荐qq
* @since 2024/8/2 下午11:36 v0.0.3-dev
*/
QQ,
/**
* 推荐群
* @since 2024/8/2 下午11:36 v0.0.3-dev
*/
GROUP;
}

View File

@ -0,0 +1,32 @@
package cn.wzpmc.api.message.json.parts.music;
import cn.wzpmc.api.message.json.JsonMessagePart;
import cn.wzpmc.api.message.json.parts.PartType;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 音乐分享
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:24
*/
@Data
@NoArgsConstructor
public abstract class Music implements JsonMessagePart {
/**
* 音乐类型
* @since 2024/8/3 下午6:07 v0.0.3-dev
*/
protected MusicType musicType;
@Override
public PartType getPartType() {
return PartType.MUSIC;
}
@Override
public JSONObject getData() {
return JSONObject.of("type", this.musicType.name);
}
}

View File

@ -0,0 +1,27 @@
package cn.wzpmc.api.message.json.parts.music;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 音乐App分享
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:28
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class MusicAppShare extends Music {
/**
* 歌曲 ID
* @since 2024/8/3 下午6:08 v0.0.3-dev
*/
private Long id;
@Override
public JSONObject getData() {
return super.getData().fluentPut("id", this.id);
}
}

View File

@ -0,0 +1,52 @@
package cn.wzpmc.api.message.json.parts.music;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 音乐自定义分享
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:30
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class MusicCustomShare extends Music {
/**
* 点击后跳转目标 URL
* @since 2024/8/3 下午6:08 v0.0.3-dev
*/
private String url;
/**
* 音乐 URL
* @since 2024/8/3 下午6:08 v0.0.3-dev
*/
private String audio;
/**
* 标题
* @since 2024/8/3 下午6:08 v0.0.3-dev
*/
private String title;
/**
* 发送时可选内容描述
* @since 2024/8/3 下午6:08 v0.0.3-dev
*/
private String content = "";
/**
* 发送时可选图片 URL
* @since 2024/8/3 下午6:08 v0.0.3-dev
*/
private String image = "";
@Override
public JSONObject getData() {
return super.getData()
.fluentPut("url", this.url)
.fluentPut("audio", this.audio)
.fluentPut("title", this.title)
.fluentPut("content", this.content)
.fluentPut("image", this.image);
}
}

View File

@ -0,0 +1,36 @@
package cn.wzpmc.api.message.json.parts.music;
/**
* 音乐类型
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:25
*/
public enum MusicType {
/**
* qq音乐
* @since 2024/8/2 下午11:25 v0.0.3-dev
*/
QQ("qq", MusicAppShare.class),
/**
* 网易云音乐
* @since 2024/8/2 下午11:26 v0.0.3-dev
*/
NETEASE("163", MusicAppShare.class),
/**
* 虾米音乐
* @since 2024/8/2 下午11:27 v0.0.3-dev
*/
XM("xm", MusicAppShare.class),
/**
* 自定义
* @since 2024/8/2 下午11:30 v0.0.3-dev
*/
CUSTOM("custom", MusicCustomShare.class);
public final String name;
public final Class<? extends Music> clazz;
MusicType(String name, Class<? extends Music> clazz){
this.name = name;
this.clazz = clazz;
}
}

View File

@ -0,0 +1,40 @@
package cn.wzpmc.api.message.json.parts.node;
import cn.wzpmc.api.message.MessageComponent;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 合并转发自定义节点
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:42
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class CustomNode extends Node {
/**
* 发送者 QQ
* @since 2024/8/3 下午6:10 v0.0.3-dev
*/
@JSONField(name = "user_id")
private Long userId;
/**
* 发送者昵称
* @since 2024/8/3 下午6:11 v0.0.3-dev
*/
private String nickname;
/**
* 消息内容
* @since 2024/8/3 下午6:11 v0.0.3-dev
*/
private MessageComponent content;
@Override
public JSONObject getData() {
return JSONObject.of("user_id", userId, "nickname", nickname, "content", content);
}
}

View File

@ -0,0 +1,19 @@
package cn.wzpmc.api.message.json.parts.node;
import cn.wzpmc.api.message.json.JsonMessagePart;
import cn.wzpmc.api.message.json.parts.PartType;
import lombok.NoArgsConstructor;
/**
* 合并转发节点
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:39
*/
@NoArgsConstructor
public abstract class Node implements JsonMessagePart {
@Override
public PartType getPartType() {
return PartType.NODE;
}
}

View File

@ -0,0 +1,27 @@
package cn.wzpmc.api.message.json.parts.node;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 合并转发节点
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:41
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class SingleNode extends Node{
/**
* 转发的消息 ID
* @since 2024/8/3 下午6:10 v0.0.3-dev
*/
private Long id;
@Override
public JSONObject getData() {
return JSONObject.of("id", this.id);
}
}

View File

@ -0,0 +1,33 @@
package cn.wzpmc.api.message.json.parts.poke;
import cn.wzpmc.api.message.json.JsonMessagePart;
import cn.wzpmc.api.message.json.parts.PartType;
import com.alibaba.fastjson2.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 戳一戳
* @author MoYiJiangNan
* @version 0.0.3-dev
* @since 2024/8/2 下午11:28
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Poke implements JsonMessagePart {
private PokeType pokeType;
@Override
public PartType getPartType() {
return PartType.POKE;
}
public JSONObject getData() {
return new JSONObject()
.fluentPut("type", this.pokeType.type)
.fluentPut("id", this.pokeType.id)
.fluentPut("name", this.pokeType.name);
}
}

View File

@ -0,0 +1,46 @@
package cn.wzpmc.api.message.json.parts.poke;
/**
* 戳一戳类型
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午11:51
*/
public enum PokeType {
CHUO_YI_CHUO("戳一戳", 1, -1),
SHOW_LOVE("比心", 2, -1),
LIKE("点赞", 2, -1),
HEART_BROKEN("心碎", 4, -1),
SIX_SIX_SIX("666", 5, -1),
FANG_DA_ZHAO("放大招", 6, -1),
BAO_BEI_QOI("宝贝球", 126, 2011),
MEI_GUI_HUA("玫瑰花", 126, 2007),
ZHAO_HUAN_SHU("召唤术", 126, 2006),
RANG_NI_PI("让你皮", 126, 2009),
JIE_YIN("结印", 126, 2005),
SHOU_LEI("手雷", 126, 2004),
GOU_YIN("勾引", 126, 2003),
ZHUA_YI_XIA("抓一下", 126, 2001),
SUI_PIN("碎屏", 126, 2002),
QIAO_MEN("敲门", 126, 2002);
/**
* 戳一戳名称
* @since 2024/8/3 下午6:18 v0.0.3-dev
*/
public final String name;
/**
* 戳一戳类型
* @since 2024/8/3 下午6:18 v0.0.3-dev
*/
public final Integer type;
/**
* 戳一戳ID
* @since 2024/8/3 下午6:18 v0.0.3-dev
*/
public final Integer id;
PokeType(String name, Integer type, Integer id){
this.name = name;
this.type = type;
this.id = id;
}
}

View File

@ -1,13 +1,6 @@
package cn.wzpmc.network;
import cn.wzpmc.api.events.Event;
import cn.wzpmc.api.events.message.MessageEvent;
import cn.wzpmc.api.events.meta.MetaEvent;
import cn.wzpmc.api.events.notice.NoticeEvent;
import cn.wzpmc.api.events.notice.NoticeType;
import cn.wzpmc.api.events.notice.notify.NotifyEvent;
import cn.wzpmc.api.events.request.RequestEvent;
import cn.wzpmc.api.events.request.RequestEventType;
import com.alibaba.fastjson2.JSON;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@ -32,31 +25,6 @@ public class PacketHandler extends SimpleChannelInboundHandler<TextWebSocketFram
}
System.out.println(text);
Event event = JSON.parseObject(text, Event.class);
Class<? extends Event> eventClass = switch (event.getPostType()) {
case NOTICE -> {
NoticeEvent noticeEvent = JSON.parseObject(text, NoticeEvent.class);
NoticeType noticeType = noticeEvent.getNoticeType();
if (NoticeType.NOTIFY.equals(noticeType)) {
NotifyEvent notifyEvent = JSON.parseObject(text, NotifyEvent.class);
yield notifyEvent.getSubType().clazz;
}
yield noticeType.clazz;
}
case MESSAGE -> {
MessageEvent<?, ?> messageEvent = JSON.parseObject(text, MessageEvent.class);
yield messageEvent.getMessageType().clazz;
}
case REQUEST -> {
RequestEvent requestEvent = JSON.parseObject(text, RequestEvent.class);
RequestEventType requestType = requestEvent.getRequestType();
yield requestType.clazz;
}
case META_EVENT -> {
MetaEvent metaEvent = JSON.parseObject(text, MetaEvent.class);
yield metaEvent.getMetaEventType().clazz;
}
};
Event event1 = JSON.parseObject(text, eventClass);
System.out.println(event1);
System.out.println(event);
}
}

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* 指令管理器实现类
@ -116,7 +117,7 @@ public class CommandManager implements ICommandManager, Completer, Highlighter {
}
}
Suggestions suggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(rawCommandLine, sender), cursor).get();
result.addAll(suggestions.getList().stream().map(Suggestion::getText).toList());
result.addAll(suggestions.getList().stream().map(Suggestion::getText).collect(Collectors.toList()));
return result;
}
@ -124,7 +125,7 @@ public class CommandManager implements ICommandManager, Completer, Highlighter {
public void complete(LineReader lineReader, ParsedLine parsedLine, List<Candidate> list) {
String line = parsedLine.line();
int cursor = parsedLine.cursor();
list.addAll(this.tabComplete(this.bot, line, cursor).stream().map(Candidate::new).toList());
list.addAll(this.tabComplete(this.bot, line, cursor).stream().map(Candidate::new).collect(Collectors.toList()));
}
@Override

View File

@ -0,0 +1,38 @@
package cn.wzpmc.utils;
import cn.wzpmc.api.events.Event;
import cn.wzpmc.api.events.message.MessageEvent;
import cn.wzpmc.api.events.meta.MetaEvent;
import cn.wzpmc.api.events.notice.NoticeEvent;
import cn.wzpmc.api.events.notice.notify.NotifyEvent;
import cn.wzpmc.api.events.request.RequestEvent;
import cn.wzpmc.api.message.StringMessage;
import cn.wzpmc.api.message.json.JsonMessage;
import cn.wzpmc.utils.json.event.*;
import cn.wzpmc.utils.json.message.JsonMessageReader;
import cn.wzpmc.utils.json.message.JsonMessageWriter;
import cn.wzpmc.utils.json.message.StringMessageReader;
import com.alibaba.fastjson2.JSON;
/**
* JSON相关工具类
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午2:04
*/
public class JsonUtils {
public static void initWriter() {
JSON.register(JsonMessage.class, new JsonMessageWriter());
}
public static void initReader() {
JSON.register(MessageEvent.class, new MessageEventReader());
JSON.register(MetaEvent.class, new MetaEventReader());
JSON.register(NotifyEvent.class, new NotifyNoticeEventReader());
JSON.register(NoticeEvent.class, new NoticeEventReader());
JSON.register(RequestEvent.class, new RequestEventReader());
JSON.register(Event.class, new EventReader());
JSON.register(JsonMessage.class, new JsonMessageReader());
JSON.register(StringMessage.class, new StringMessageReader());
}
}

View File

@ -0,0 +1,28 @@
package cn.wzpmc.utils.json.event;
import cn.wzpmc.api.events.Event;
import cn.wzpmc.api.events.EventPostType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
/**
* event类型JSON反序列化
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午2:07
*/
public class EventReader implements ObjectReader<Event> {
@Override
public Event readObject(JSONReader jsonReader, Type type, Object o, long l) {
JSONReader.SavePoint mark = jsonReader.mark();
JSONObject jsonObject = jsonReader.readJSONObject();
EventPostType postType = EventPostType.valueOf(jsonObject.getString("post_type").toUpperCase());
jsonReader.reset(mark);
Event event = jsonReader.read(postType.clazz);
jsonReader.close();
return event;
}
}

View File

@ -0,0 +1,26 @@
package cn.wzpmc.utils.json.event;
import cn.wzpmc.api.events.message.MessageEvent;
import cn.wzpmc.api.events.message.MessageType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
/**
* 消息事件反序列化
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午8:56
*/
public class MessageEventReader implements ObjectReader<MessageEvent<?, ?>> {
@Override
public MessageEvent<?, ?> readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
JSONReader.SavePoint mark = jsonReader.mark();
JSONObject jsonObject = jsonReader.readJSONObject();
MessageType messageType = MessageType.valueOf(jsonObject.getString("message_type").toUpperCase());
jsonReader.reset(mark);
return jsonReader.read(messageType.clazz);
}
}

View File

@ -0,0 +1,26 @@
package cn.wzpmc.utils.json.event;
import cn.wzpmc.api.events.meta.MetaEvent;
import cn.wzpmc.api.events.meta.MetaEventType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
/**
* 元事件反序列化
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午8:56
*/
public class MetaEventReader implements ObjectReader<MetaEvent> {
@Override
public MetaEvent readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
JSONReader.SavePoint mark = jsonReader.mark();
JSONObject jsonObject = jsonReader.readJSONObject();
MetaEventType metaEventType = MetaEventType.valueOf(jsonObject.getString("meta_event_type").toUpperCase());
jsonReader.reset(mark);
return jsonReader.read(metaEventType.clazz);
}
}

View File

@ -0,0 +1,26 @@
package cn.wzpmc.utils.json.event;
import cn.wzpmc.api.events.notice.NoticeEvent;
import cn.wzpmc.api.events.notice.NoticeType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
/**
* 提醒类型事件反序列化
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午8:48
*/
public class NoticeEventReader implements ObjectReader<NoticeEvent> {
@Override
public NoticeEvent readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
JSONReader.SavePoint mark = jsonReader.mark();
JSONObject jsonObject = jsonReader.readJSONObject();
NoticeType noticeType = NoticeType.valueOf(jsonObject.getString("notice_type").toUpperCase());
jsonReader.reset(mark);
return jsonReader.read(noticeType.clazz);
}
}

View File

@ -0,0 +1,26 @@
package cn.wzpmc.utils.json.event;
import cn.wzpmc.api.events.notice.notify.NotifyEvent;
import cn.wzpmc.api.events.notice.notify.NotifySubType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
/**
* 群提醒事件反序列化
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午8:53
*/
public class NotifyNoticeEventReader implements ObjectReader<NotifyEvent> {
@Override
public NotifyEvent readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
JSONReader.SavePoint mark = jsonReader.mark();
JSONObject jsonObject = jsonReader.readJSONObject();
NotifySubType subType = NotifySubType.valueOf(jsonObject.getString("sub_type").toUpperCase());
jsonReader.reset(mark);
return jsonReader.read(subType.clazz);
}
}

View File

@ -0,0 +1,26 @@
package cn.wzpmc.utils.json.event;
import cn.wzpmc.api.events.request.RequestEvent;
import cn.wzpmc.api.events.request.RequestEventType;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
/**
* 请求事件反序列化
* @author wzp
* @version 0.0.3-dev
* @since 2024/8/2 下午8:56
*/
public class RequestEventReader implements ObjectReader<RequestEvent> {
@Override
public RequestEvent readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
JSONReader.SavePoint mark = jsonReader.mark();
JSONObject jsonObject = jsonReader.readJSONObject();
RequestEventType requestType = RequestEventType.valueOf(jsonObject.getString("request_type").toUpperCase());
jsonReader.reset(mark);
return jsonReader.read(requestType.clazz);
}
}

View File

@ -0,0 +1,85 @@
package cn.wzpmc.utils.json.message;
import cn.wzpmc.api.message.json.JsonMessage;
import cn.wzpmc.api.message.json.JsonMessagePart;
import cn.wzpmc.api.message.json.parts.PartType;
import cn.wzpmc.api.message.json.parts.music.MusicType;
import cn.wzpmc.api.message.json.parts.node.CustomNode;
import cn.wzpmc.api.message.json.parts.node.SingleNode;
import cn.wzpmc.api.message.json.parts.poke.Poke;
import cn.wzpmc.api.message.json.parts.poke.PokeType;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.reader.ObjectReader;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Objects;
/**
* json消息解析器
* @author wzp
* @since 2024/8/3 下午6:25
* @version 0.0.3-dev
*/
@Log4j2
public class JsonMessageReader implements ObjectReader<JsonMessage> {
@SneakyThrows
@Override
public JsonMessage readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
JSONArray objects = jsonReader.readJSONArray();
JsonMessage message = new JsonMessage();
List<JsonMessagePart> messageParts = message.getMessageParts();
messageFor: for (int i = 0; i < objects.size(); i++) {
JSONObject jsonObject = objects.getJSONObject(i);
PartType type = jsonObject.getObject("type", PartType.class);
Class<? extends JsonMessagePart> clazz = type.clazz;
JSONObject dataObject = jsonObject.getJSONObject("data");
if (type.equals(PartType.POKE)){
Integer pokeType = dataObject.getInteger("type");
Integer pokeId = dataObject.getInteger("id");
for (PokeType value : PokeType.values()) {
if (value.type.equals(pokeType) && value.id.equals(pokeId)){
messageParts.add(new Poke(value));
continue messageFor;
}
}
log.warn("无法识别的戳一戳类型type: {}, id: {}", pokeType, pokeId);
messageParts.add(new Poke());
}
if (type.equals(PartType.NODE)){
if (jsonObject.containsKey("content")){
clazz = CustomNode.class;
}else{
clazz = SingleNode.class;
}
}
if (type.equals(PartType.MUSIC)){
MusicType musicType = dataObject.getObject("type", MusicType.class);
dataObject.put("musicType", musicType);
clazz = musicType.clazz;
}
Constructor<? extends JsonMessagePart> declaredConstructor = clazz.getDeclaredConstructor();
JsonMessagePart resultPart = declaredConstructor.newInstance();
for (Field declaredField : clazz.getDeclaredFields()) {
JSONField annotation = declaredField.getAnnotation(JSONField.class);
String name = Objects.isNull(annotation) ? declaredField.getName() : annotation.name();
if (!dataObject.containsKey(name)) {
continue;
}
declaredField.setAccessible(true);
Class<?> thisFieldClass = declaredField.getType();
Object value = dataObject.getObject(name, thisFieldClass);
declaredField.set(resultPart, value);
}
messageParts.add(resultPart);
}
return message;
}
}

View File

@ -0,0 +1,21 @@
package cn.wzpmc.utils.json.message;
import cn.wzpmc.api.message.json.JsonMessage;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.writer.ObjectWriter;
import java.lang.reflect.Type;
/**
* JSON格式消息反序列化
* @author wzp
* @since 2024/8/3 下午6:28
* @version 0.0.3-dev */
public class JsonMessageWriter implements ObjectWriter<JsonMessage> {
@Override
public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
if (object instanceof JsonMessage) {
jsonWriter.write(((JsonMessage) object).getMessageParts());
}
}
}

View File

@ -0,0 +1,25 @@
package cn.wzpmc.utils.json.message;
import cn.wzpmc.api.message.StringMessage;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
/**
* @author wzp
* @since 2024/8/3 下午8:38
* @version 0.0.3-dev
*/
public class StringMessageReader implements ObjectReader<StringMessage> {
@Override
public StringMessage readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
if (jsonReader.isObject()){
JSONObject jsonObject = jsonReader.readJSONObject();
return new StringMessage(jsonObject.getJSONObject("data").getString("text"));
}
String s = jsonReader.readString();
return new StringMessage(s);
}
}