Skip to content

Commit e6b93fe

Browse files
committed
feat: add markdown button template message support
1 parent 6ff4233 commit e6b93fe

File tree

8 files changed

+194
-6
lines changed

8 files changed

+194
-6
lines changed

openqq-for-java/src/main/java/cn/byteforge/openqq/http/OpenAPI.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.google.gson.Gson;
1414
import com.google.gson.GsonBuilder;
1515
import com.google.gson.JsonObject;
16+
import lombok.extern.slf4j.Slf4j;
1617
import org.jetbrains.annotations.Nullable;
1718

1819
import java.util.Map;
@@ -21,6 +22,7 @@
2122
* QQ 机器人 服务端开放的 openapi 接口对接
2223
* */
2324
// TODO 更改url储存位置
25+
@Slf4j
2426
public class OpenAPI {
2527

2628
private static final Gson GSON = new GsonBuilder().create();
@@ -112,14 +114,14 @@ private static <T> T getAuthResponse(String url, @Nullable Map<String, Object> d
112114
* */
113115
private static <T> T getResponse(String url, Map<String, Object> data, Method method, Class<T> clazz, Map<String, String> headers) {
114116
String body = GSON.toJson(data);
117+
log.debug("Send json object to url: {}, json: {}", url, body);
115118
try (HttpResponse response = HttpRequest.of(url)
116119
.method(method)
117120
.timeout(HttpGlobalConfig.getTimeout())
118121
.body(body)
119122
.headerMap(headers, true)
120123
.execute())
121124
{
122-
// {"message":"send msg err","code":22013,"err_code":22013,"trace_id":"eaab6442592c90cffa1ca71ce5f7c670"}
123125
Status.Http httpStatus = Status.Http.parse(response.getStatus());
124126
if (!httpStatus.isSuccess() && response.bodyBytes().length == 0) {
125127
throw new APIInvokeException(httpStatus.getCode(), httpStatus.getMessage(), body);

openqq-for-java/src/main/java/cn/byteforge/openqq/message/MessageBuilder.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import cn.byteforge.openqq.http.entity.entry.KeyValueEntry;
55
import cn.byteforge.openqq.http.entity.entry.LinkedTextEntry;
66
import cn.byteforge.openqq.util.Maps;
7+
import cn.hutool.core.lang.Assert;
78
import com.google.gson.JsonArray;
89
import org.jetbrains.annotations.Nullable;
910

@@ -80,6 +81,20 @@ public MessageBuilder addCustomMarkdown(String content) {
8081
return this;
8182
}
8283

84+
/**
85+
* 从模版发送 Markdown 按钮消息
86+
* @param templateId markdown 按钮模版id,申请按钮模版后获得
87+
* @apiNote 按钮模板消息不能与markdown消息混合使用
88+
* */
89+
public MessageBuilder addTemplateMarkdownButton(String templateId) {
90+
Assert.isNull(data.remove("markdown"), "Button template messages cannot be mixed with markdown messages");
91+
data.put("keyboard", Maps.of(
92+
"id", templateId
93+
));
94+
updateMsgType(MessageType.MARKDOWN);
95+
return this;
96+
}
97+
8398
// ARK 消息
8499

85100
/**

openqq-for-java/src/main/java/cn/byteforge/openqq/ws/entity/Intent.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ public Register withDirectMessage() {
5656
return this;
5757
}
5858

59+
/**
60+
* Markdown 按钮点击回调事件监听
61+
* */
5962
public Register withInteraction() {
6063
intents = intents | (1 << 26);
6164
return this;
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package cn.byteforge.openqq.ws.entity.data;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
import lombok.Data;
5+
import org.jetbrains.annotations.Nullable;
6+
7+
@Data
8+
public class InteractionData {
9+
10+
/**
11+
* 平台方事件 ID,可以用于被动消息发送
12+
* */
13+
private String id;
14+
15+
/**
16+
* 消息按钮: 11,单聊快捷菜单:12
17+
* */
18+
private Integer type;
19+
20+
/**
21+
* 事件发生的场景:c2c、group、guild
22+
* */
23+
private String scene;
24+
25+
/**
26+
* 0 频道场景,1 群聊场景,2 单聊场景
27+
* */
28+
@SerializedName("chat_type")
29+
private Integer chatType;
30+
31+
/**
32+
* 触发时间 RFC 3339 格式
33+
* */
34+
private String timestamp;
35+
36+
/**
37+
* 单聊单聊按钮触发x,的用户 openid,仅在单聊场景提供该字段
38+
* */
39+
@SerializedName("user_openid")
40+
@Nullable
41+
private String userOpenid;
42+
43+
/**
44+
* 群的 openid,仅在群聊场景提供该字段
45+
* */
46+
@SerializedName("group_openid")
47+
@Nullable
48+
private String groupOpenid;
49+
50+
/**
51+
* 按钮触发用户,群聊的群成员 openid,仅在群聊场景提供该字段
52+
* */
53+
@SerializedName("group_member_openid")
54+
@Nullable
55+
private String groupMemberOpenid;
56+
57+
private Data data;
58+
59+
private Integer version;
60+
61+
/**
62+
* 机器人的 appid
63+
* */
64+
@SerializedName("application_id")
65+
private String applicationId;
66+
67+
68+
@lombok.Data
69+
public static final class Data {
70+
71+
private Resolved resolved;
72+
73+
}
74+
75+
@lombok.Data
76+
public static final class Resolved {
77+
78+
/**
79+
* 操作按钮的 data 字段值(在发送消息按钮时设置)
80+
* */
81+
@SerializedName("button_data")
82+
private String buttonData;
83+
84+
/**
85+
* 操作按钮的 id 字段值(在发送消息按钮时设置)
86+
* */
87+
@SerializedName("button_id")
88+
private String buttonId;
89+
90+
/**
91+
* 操作的用户 userid,仅频道场景提供该字段
92+
* */
93+
@Nullable
94+
@SerializedName("user_id")
95+
private String userId;
96+
97+
/**
98+
* 操作按钮的 id 字段值,仅自定义菜单提供该字段(在管理端设置)
99+
* */
100+
@Nullable
101+
@SerializedName("feature_id")
102+
private String featureId;
103+
104+
/**
105+
* 操作的消息id,目前仅频道场景提供该字段
106+
* */
107+
@Nullable
108+
@SerializedName("message_id")
109+
private String messageId;
110+
111+
}
112+
113+
}

openqq-for-java/src/main/java/cn/byteforge/openqq/ws/event/type/MessageEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
public abstract class MessageEvent extends Event {
1717

1818
/**
19-
* 平台方消息ID,可以用于被动消息发送
19+
* 事件ID
2020
* */
2121
private String id;
2222

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package cn.byteforge.openqq.ws.event.type.interact;
2+
3+
import cn.byteforge.openqq.ws.entity.data.InteractionData;
4+
import cn.byteforge.openqq.ws.event.Event;
5+
import com.google.gson.Gson;
6+
import lombok.Data;
7+
import lombok.EqualsAndHashCode;
8+
import lombok.ToString;
9+
10+
/**
11+
* Markdown 按钮交互事件
12+
* */
13+
@EqualsAndHashCode(callSuper = true)
14+
@ToString(callSuper = true)
15+
@Data
16+
public class InteractionEvent extends Event {
17+
18+
/**
19+
* 事件ID
20+
* */
21+
private String id;
22+
23+
/**
24+
* 获取事件字段数据
25+
* */
26+
public InteractionData getData() {
27+
return new Gson().fromJson(getD(), InteractionData.class);
28+
}
29+
30+
31+
}

openqq-for-java/src/main/java/cn/byteforge/openqq/ws/handler/EventParseHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import cn.byteforge.openqq.ws.event.Event;
66
import cn.byteforge.openqq.ws.event.type.friend.*;
77
import cn.byteforge.openqq.ws.event.type.group.*;
8+
import cn.byteforge.openqq.ws.event.type.interact.InteractionEvent;
89
import com.google.gson.Gson;
910
import com.google.gson.GsonBuilder;
1011
import com.google.gson.JsonObject;
@@ -42,6 +43,7 @@ protected Event doHandle(Object object) {
4243

4344
static {
4445
TYPE_EVENT_MAP = new HashMap<>();
46+
TYPE_EVENT_MAP.put("INTERACTION_CREATE", InteractionEvent.class);
4547
TYPE_EVENT_MAP.putAll(Maps.of(
4648
"C2C_MESSAGE_CREATE", C2CMessageEvent.class,
4749
"GROUP_AT_MESSAGE_CREATE", GroupAtMessageEvent.class

openqq-for-java/src/test/java/TestMain.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import cn.byteforge.openqq.http.OpenAPI;
22
import cn.byteforge.openqq.http.entity.AccessToken;
33
import cn.byteforge.openqq.http.entity.RecommendShard;
4+
import cn.byteforge.openqq.message.Message;
5+
import cn.byteforge.openqq.message.MessageBuilder;
46
import cn.byteforge.openqq.model.Certificate;
57
import cn.byteforge.openqq.ws.BotContext;
68
import cn.byteforge.openqq.ws.QQConnection;
79
import cn.byteforge.openqq.ws.WebSocketAPI;
810
import cn.byteforge.openqq.ws.entity.Intent;
11+
import cn.byteforge.openqq.ws.entity.data.GroupAtMessageData;
912
import cn.byteforge.openqq.ws.event.EventListener;
1013
import cn.byteforge.openqq.ws.event.type.group.GroupAtMessageEvent;
14+
import cn.byteforge.openqq.ws.event.type.interact.InteractionEvent;
1115
import cn.byteforge.openqq.ws.handler.ChainHandler;
1216

1317
import java.nio.file.Files;
@@ -18,26 +22,44 @@ public class TestMain {
1822
private static BotContext context;
1923

2024
public static void main(String[] args) throws Exception {
21-
String appId = new String(Files.readAllBytes(Paths.get("../secrets/appId.txt")));
22-
String clientSecret = new String(Files.readAllBytes(Paths.get("../secrets/clientSecret.txt")));
25+
String appId = new String(Files.readAllBytes(Paths.get("secrets/appId.txt")));
26+
String clientSecret = new String(Files.readAllBytes(Paths.get("secrets/clientSecret.txt")));
2327
AccessToken token = OpenAPI.getAppAccessToken(appId, clientSecret);
2428
Certificate certificate = new Certificate(appId, clientSecret, token);
2529
context = BotContext.create(certificate);
2630
RecommendShard shard = OpenAPI.getRecommendShardWssUrls(certificate);
2731
String wssUrl = shard.getUrl();
2832

29-
Intent intent = Intent.register().withAll().done();
33+
Intent intent = Intent.register()
34+
.withCustom(1 << 25)
35+
.withCustom(1 << 26)
36+
.done();
3037
ChainHandler chainHandler = ChainHandler.defaultChainGroup(wssUrl, null,
3138
new EventListener<GroupAtMessageEvent>() {
3239
@Override
3340
public void onEvent(GroupAtMessageEvent event) {
34-
System.out.println(event);
41+
GroupAtMessageData data = event.getData();
42+
Message message = new MessageBuilder()
43+
.addTemplateMarkdownButton("")
44+
.setPassive(data.getId())
45+
.build();
46+
OpenAPI.sendGroupMessage(data.getGroupId(), message, certificate);
3547
}
3648

3749
@Override
3850
public Intent eventIntent() {
3951
return Intent.register().withCustom(1 << 25).done();
4052
}
53+
}, new EventListener<InteractionEvent>() {
54+
@Override
55+
public void onEvent(InteractionEvent event) {
56+
System.out.println("收到:" + event);
57+
}
58+
59+
@Override
60+
public Intent eventIntent() {
61+
return Intent.register().withInteraction().done();
62+
}
4163
});
4264

4365
QQConnection.connect(wssUrl, chainHandler, context,

0 commit comments

Comments
 (0)