@zhin.js/adapter-icqq 6.0.0 → 6.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +3 -3
- package/{skills/icqq → agent}/PERMITS.md +6 -6
- package/agent/tools/announce.ts +21 -0
- package/agent/tools/essence.ts +22 -0
- package/agent/tools/friend_list.ts +19 -0
- package/agent/tools/group_files.ts +27 -0
- package/agent/tools/group_invite.ts +20 -0
- package/agent/tools/group_list.ts +20 -0
- package/agent/tools/group_sign.ts +19 -0
- package/agent/tools/list_muted.ts +22 -0
- package/agent/tools/poke.ts +20 -0
- package/agent/tools/send_user_like.ts +22 -0
- package/agent/tools/set_anonymous.ts +22 -0
- package/agent/tools/set_title.ts +25 -0
- package/dist/index.js +2 -2
- package/lib/agent/tools/announce.js +21 -0
- package/lib/agent/tools/announce.js.map +1 -0
- package/lib/agent/tools/essence.js +22 -0
- package/lib/agent/tools/essence.js.map +1 -0
- package/lib/agent/tools/friend_list.js +19 -0
- package/lib/agent/tools/friend_list.js.map +1 -0
- package/lib/agent/tools/group_files.js +29 -0
- package/lib/agent/tools/group_files.js.map +1 -0
- package/lib/agent/tools/group_invite.js +20 -0
- package/lib/agent/tools/group_invite.js.map +1 -0
- package/lib/agent/tools/group_list.js +20 -0
- package/lib/agent/tools/group_list.js.map +1 -0
- package/lib/agent/tools/group_sign.js +19 -0
- package/lib/agent/tools/group_sign.js.map +1 -0
- package/lib/agent/tools/list_muted.js +23 -0
- package/lib/agent/tools/list_muted.js.map +1 -0
- package/lib/agent/tools/poke.js +20 -0
- package/lib/agent/tools/poke.js.map +1 -0
- package/lib/agent/tools/send_user_like.js +22 -0
- package/lib/agent/tools/send_user_like.js.map +1 -0
- package/lib/agent/tools/set_anonymous.js +22 -0
- package/lib/agent/tools/set_anonymous.js.map +1 -0
- package/lib/agent/tools/set_title.js +25 -0
- package/lib/agent/tools/set_title.js.map +1 -0
- package/lib/{adapter.js → src/adapter.js} +13 -6
- package/lib/src/adapter.js.map +1 -0
- package/lib/src/agent-prompt.js.map +1 -0
- package/lib/{cq-message.js → src/cq-message.js} +12 -3
- package/lib/src/cq-message.js.map +1 -0
- package/lib/{endpoint.js → src/endpoint.js} +130 -63
- package/lib/src/endpoint.js.map +1 -0
- package/lib/{forward-msg.js → src/forward-msg.js} +4 -1
- package/lib/src/forward-msg.js.map +1 -0
- package/lib/src/get-msg.js.map +1 -0
- package/lib/src/icqq-agent-deps.js +10 -0
- package/lib/src/icqq-agent-deps.js.map +1 -0
- package/lib/src/icqq-guild.js +115 -0
- package/lib/src/icqq-guild.js.map +1 -0
- package/lib/{icqq-inbound.js → src/icqq-inbound.js} +15 -5
- package/lib/src/icqq-inbound.js.map +1 -0
- package/lib/src/icqq-login-assist-bridge.js.map +1 -0
- package/lib/{icqq-side-events.js → src/icqq-side-events.js} +28 -92
- package/lib/src/icqq-side-events.js.map +1 -0
- package/lib/{index.js → src/index.js} +0 -1
- package/lib/src/index.js.map +1 -0
- package/lib/src/ipc-client.js.map +1 -0
- package/lib/src/login-assist-routes.js.map +1 -0
- package/lib/src/login-ipc-contract.js.map +1 -0
- package/lib/src/outbound-media.js.map +1 -0
- package/lib/src/protocol.js.map +1 -0
- package/lib/src/routes.js.map +1 -0
- package/lib/src/segment-mapper.js +2 -0
- package/lib/src/segment-mapper.js.map +1 -0
- package/lib/src/tools/index.js +23 -0
- package/lib/src/tools/index.js.map +1 -0
- package/lib/src/types.js.map +1 -0
- package/package.json +25 -21
- package/src/adapter.ts +13 -6
- package/src/agent-prompt.ts +1 -2
- package/src/cq-message.ts +11 -3
- package/src/endpoint.ts +158 -82
- package/src/forward-msg.ts +2 -2
- package/src/icqq-agent-deps.ts +18 -0
- package/src/icqq-guild.ts +157 -0
- package/src/icqq-inbound.ts +16 -5
- package/src/icqq-side-events.ts +33 -118
- package/src/index.ts +0 -8
- package/src/segment-mapper.ts +1 -0
- package/src/tools/index.ts +16 -397
- package/src/types.ts +0 -45
- package/lib/adapter.d.ts +0 -39
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js.map +0 -1
- package/lib/agent-prompt.d.ts +0 -3
- package/lib/agent-prompt.d.ts.map +0 -1
- package/lib/agent-prompt.js.map +0 -1
- package/lib/cq-message.d.ts +0 -10
- package/lib/cq-message.d.ts.map +0 -1
- package/lib/cq-message.js.map +0 -1
- package/lib/endpoint.d.ts +0 -99
- package/lib/endpoint.d.ts.map +0 -1
- package/lib/endpoint.js.map +0 -1
- package/lib/forward-msg.d.ts +0 -27
- package/lib/forward-msg.d.ts.map +0 -1
- package/lib/forward-msg.js.map +0 -1
- package/lib/get-msg.d.ts +0 -3
- package/lib/get-msg.d.ts.map +0 -1
- package/lib/get-msg.js.map +0 -1
- package/lib/icqq-inbound.d.ts +0 -130
- package/lib/icqq-inbound.d.ts.map +0 -1
- package/lib/icqq-inbound.js.map +0 -1
- package/lib/icqq-login-assist-bridge.d.ts +0 -5
- package/lib/icqq-login-assist-bridge.d.ts.map +0 -1
- package/lib/icqq-login-assist-bridge.js.map +0 -1
- package/lib/icqq-side-events.d.ts +0 -34
- package/lib/icqq-side-events.d.ts.map +0 -1
- package/lib/icqq-side-events.js.map +0 -1
- package/lib/index.d.ts +0 -20
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/ipc-client.d.ts +0 -74
- package/lib/ipc-client.d.ts.map +0 -1
- package/lib/ipc-client.js.map +0 -1
- package/lib/login-assist-routes.d.ts +0 -7
- package/lib/login-assist-routes.d.ts.map +0 -1
- package/lib/login-assist-routes.js.map +0 -1
- package/lib/login-ipc-contract.d.ts +0 -44
- package/lib/login-ipc-contract.d.ts.map +0 -1
- package/lib/login-ipc-contract.js.map +0 -1
- package/lib/outbound-media.d.ts +0 -14
- package/lib/outbound-media.d.ts.map +0 -1
- package/lib/outbound-media.js.map +0 -1
- package/lib/protocol.d.ts +0 -198
- package/lib/protocol.d.ts.map +0 -1
- package/lib/protocol.js.map +0 -1
- package/lib/routes.d.ts +0 -8
- package/lib/routes.d.ts.map +0 -1
- package/lib/routes.js.map +0 -1
- package/lib/tools/index.d.ts +0 -10
- package/lib/tools/index.d.ts.map +0 -1
- package/lib/tools/index.js +0 -341
- package/lib/tools/index.js.map +0 -1
- package/lib/types.d.ts +0 -117
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js.map +0 -1
- package/lib/typing-indicator-example.d.ts +0 -108
- package/lib/typing-indicator-example.d.ts.map +0 -1
- package/lib/typing-indicator-example.js +0 -220
- package/lib/typing-indicator-example.js.map +0 -1
- package/lib/typing-indicator.d.ts +0 -87
- package/lib/typing-indicator.d.ts.map +0 -1
- package/lib/typing-indicator.js +0 -229
- package/lib/typing-indicator.js.map +0 -1
- package/src/typing-indicator-example.ts +0 -269
- package/src/typing-indicator.ts +0 -317
- /package/lib/{agent-prompt.js → src/agent-prompt.js} +0 -0
- /package/lib/{get-msg.js → src/get-msg.js} +0 -0
- /package/lib/{icqq-login-assist-bridge.js → src/icqq-login-assist-bridge.js} +0 -0
- /package/lib/{ipc-client.js → src/ipc-client.js} +0 -0
- /package/lib/{login-assist-routes.js → src/login-assist-routes.js} +0 -0
- /package/lib/{login-ipc-contract.js → src/login-ipc-contract.js} +0 -0
- /package/lib/{outbound-media.js → src/outbound-media.js} +0 -0
- /package/lib/{protocol.js → src/protocol.js} +0 -0
- /package/lib/{routes.js → src/routes.js} +0 -0
- /package/lib/{types.js → src/types.js} +0 -0
package/src/icqq-side-events.ts
CHANGED
|
@@ -1,29 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* icqq IPC 非 message 入站:notice / request / meta(对齐 OneBot 与 @icqqjs/icqq EventMap)
|
|
3
|
-
* @see https://icqq.pages.dev/interfaces/EventMap.html
|
|
4
3
|
*/
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import type { RequestType } from "zhin.js";
|
|
4
|
+
import { mapNoticeParts, mapRequestParts, resolveSideEventDedupeKey, senderFromId, buildNotice, buildRequest, formatCompact, type OneBotLikeRawEvent } from 'zhin.js';
|
|
5
|
+
|
|
8
6
|
import { Actions } from "./protocol.js";
|
|
9
7
|
import type { IpcClient } from "./ipc-client.js";
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
export interface IcqqIpcRawEvent {
|
|
13
|
-
post_type?: string;
|
|
14
|
-
time?: number;
|
|
15
|
-
self_id?: number;
|
|
16
|
-
notice_type?: string;
|
|
17
|
-
request_type?: string;
|
|
18
|
-
sub_type?: string;
|
|
19
|
-
meta_event_type?: string;
|
|
20
|
-
group_id?: number;
|
|
21
|
-
user_id?: number;
|
|
22
|
-
operator_id?: number;
|
|
23
|
-
flag?: string;
|
|
24
|
-
comment?: string;
|
|
25
|
-
[key: string]: unknown;
|
|
26
|
-
}
|
|
9
|
+
export type IcqqIpcRawEvent = OneBotLikeRawEvent;
|
|
27
10
|
|
|
28
11
|
export function resolveIcqqEventPostType(
|
|
29
12
|
data: Record<string, unknown>,
|
|
@@ -54,110 +37,39 @@ export function isIcqqMetaPayload(data: unknown): data is IcqqIpcRawEvent {
|
|
|
54
37
|
return pt === "meta_event" || (typeof pt === "string" && pt.startsWith("system."));
|
|
55
38
|
}
|
|
56
39
|
|
|
57
|
-
/** 去重用:notice / request 无稳定 id 时组合键 */
|
|
58
|
-
export function resolveSideEventDedupeKey(
|
|
59
|
-
data: IcqqIpcRawEvent,
|
|
60
|
-
kind: "notice" | "request" | "meta",
|
|
61
|
-
): string {
|
|
62
|
-
if (data.flag != null && String(data.flag) !== "") {
|
|
63
|
-
return `${kind}:${data.flag}`;
|
|
64
|
-
}
|
|
65
|
-
const time = data.time ?? 0;
|
|
66
|
-
const type =
|
|
67
|
-
data.notice_type ?? data.request_type ?? data.meta_event_type ?? kind;
|
|
68
|
-
const scope = data.group_id ?? data.user_id ?? "";
|
|
69
|
-
const sub = data.sub_type ?? "";
|
|
70
|
-
return `${kind}:${time}_${type}_${scope}_${sub}`;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const NOTICE_TYPE_MAP: Record<string, NoticeType> = {
|
|
74
|
-
group_increase: "group_member_increase",
|
|
75
|
-
group_decrease: "group_member_decrease",
|
|
76
|
-
group_admin: "group_admin_change",
|
|
77
|
-
group_ban: "group_ban",
|
|
78
|
-
group_recall: "group_recall",
|
|
79
|
-
friend_recall: "friend_recall",
|
|
80
|
-
friend_add: "friend_add",
|
|
81
|
-
group_upload: "group_upload",
|
|
82
|
-
group_sign: "group_sign",
|
|
83
|
-
group_transfer: "group_transfer",
|
|
84
|
-
// icqq EventMap 命名 → Zhin NoticeType
|
|
85
|
-
"group.increase": "group_member_increase",
|
|
86
|
-
"group.decrease": "group_member_decrease",
|
|
87
|
-
"group.admin": "group_admin_change",
|
|
88
|
-
"group.ban": "group_ban",
|
|
89
|
-
"group.recall": "group_recall",
|
|
90
|
-
"friend.increase": "friend_add",
|
|
91
|
-
"friend.decrease": "friend_recall",
|
|
92
|
-
"friend.recall": "friend_recall",
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
function resolveNoticeZhinType(event: IcqqIpcRawEvent): NoticeType {
|
|
96
|
-
const raw = event.notice_type ?? "";
|
|
97
|
-
if (NOTICE_TYPE_MAP[raw]) return NOTICE_TYPE_MAP[raw];
|
|
98
|
-
if (raw === "notify") {
|
|
99
|
-
if (event.sub_type === "poke") {
|
|
100
|
-
return event.group_id != null ? "group_poke" : "friend_poke";
|
|
101
|
-
}
|
|
102
|
-
return `notify_${event.sub_type ?? "unknown"}` as NoticeType;
|
|
103
|
-
}
|
|
104
|
-
if (raw.startsWith("notice.")) {
|
|
105
|
-
const suffix = raw.slice("notice.".length).replace(/\./g, "_");
|
|
106
|
-
return (NOTICE_TYPE_MAP[suffix] ?? suffix) as NoticeType;
|
|
107
|
-
}
|
|
108
|
-
return raw as NoticeType;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function senderFromId(id: unknown, name?: string) {
|
|
112
|
-
if (id == null) return undefined;
|
|
113
|
-
const s = String(id);
|
|
114
|
-
return { id: s, name: name ?? s };
|
|
115
|
-
}
|
|
116
|
-
|
|
117
40
|
export function formatIcqqNotice(
|
|
118
41
|
event: IcqqIpcRawEvent,
|
|
119
42
|
endpointName: string,
|
|
120
|
-
)
|
|
121
|
-
const
|
|
43
|
+
) {
|
|
44
|
+
const raw = event.notice_type ?? "";
|
|
122
45
|
const isGroup = event.group_id != null;
|
|
123
|
-
const
|
|
46
|
+
const { scene_type, sub_type } = mapNoticeParts('icqq', raw, { sub_type: event.sub_type, is_group: isGroup });
|
|
47
|
+
const sceneId = String(
|
|
124
48
|
event.group_id ?? event.user_id ?? event.operator_id ?? "",
|
|
125
49
|
);
|
|
126
50
|
const tsSec = event.time ?? Math.floor(Date.now() / 1000);
|
|
127
51
|
|
|
128
|
-
return
|
|
52
|
+
return buildNotice(event, {
|
|
129
53
|
$id: resolveSideEventDedupeKey(event, "notice"),
|
|
130
54
|
$adapter: "icqq",
|
|
131
55
|
$endpoint: endpointName,
|
|
132
|
-
$type,
|
|
133
|
-
$
|
|
134
|
-
$
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
},
|
|
138
|
-
$operator: senderFromId(event.operator_id),
|
|
56
|
+
$type: "notice",
|
|
57
|
+
$scene_id: sceneId,
|
|
58
|
+
$scene_type: scene_type,
|
|
59
|
+
$sub_type: sub_type,
|
|
60
|
+
$actor: senderFromId(event.operator_id),
|
|
139
61
|
$target: senderFromId(event.user_id),
|
|
140
62
|
$timestamp: tsSec * 1000,
|
|
141
63
|
});
|
|
142
64
|
}
|
|
143
65
|
|
|
144
|
-
function resolveRequestZhinType(event: IcqqIpcRawEvent): RequestType {
|
|
145
|
-
const rt = event.request_type ?? "";
|
|
146
|
-
if (rt === "friend" || rt.startsWith("friend")) return "friend_add";
|
|
147
|
-
if (rt === "group" || rt.startsWith("group")) {
|
|
148
|
-
return event.sub_type === "invite" ? "group_invite" : "group_add";
|
|
149
|
-
}
|
|
150
|
-
return rt as RequestType;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
66
|
export function formatIcqqRequest(
|
|
154
67
|
event: IcqqIpcRawEvent,
|
|
155
68
|
endpointName: string,
|
|
156
69
|
ipc: IpcClient,
|
|
157
|
-
)
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const channelId = String(event.group_id ?? event.user_id ?? "");
|
|
70
|
+
) {
|
|
71
|
+
const { scene_type, sub_type } = mapRequestParts('icqq', event.request_type ?? '', event.sub_type);
|
|
72
|
+
const sceneId = String(event.group_id ?? event.user_id ?? "");
|
|
161
73
|
const tsSec = event.time ?? Math.floor(Date.now() / 1000);
|
|
162
74
|
const flag = event.flag ?? resolveSideEventDedupeKey(event, "request");
|
|
163
75
|
|
|
@@ -166,18 +78,16 @@ export function formatIcqqRequest(
|
|
|
166
78
|
(typeof event.request_type === "string" &&
|
|
167
79
|
event.request_type.startsWith("friend"));
|
|
168
80
|
|
|
169
|
-
return
|
|
81
|
+
return buildRequest(event, {
|
|
170
82
|
$id: String(flag),
|
|
171
83
|
$adapter: "icqq",
|
|
172
84
|
$endpoint: endpointName,
|
|
173
|
-
$type,
|
|
174
|
-
$
|
|
175
|
-
$
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
$sender: senderFromId(event.user_id) ?? { id: "", name: "" },
|
|
180
|
-
$comment: event.comment,
|
|
85
|
+
$type: "request",
|
|
86
|
+
$scene_id: sceneId,
|
|
87
|
+
$scene_type: scene_type,
|
|
88
|
+
$sub_type: sub_type,
|
|
89
|
+
$actor: senderFromId(event.user_id) ?? { id: "", name: "" },
|
|
90
|
+
$comment: typeof event.comment === "string" ? event.comment : undefined,
|
|
181
91
|
$timestamp: tsSec * 1000,
|
|
182
92
|
$approve: async (remark?: string) => {
|
|
183
93
|
const action = isFriend
|
|
@@ -208,21 +118,26 @@ export function formatIcqqRequest(
|
|
|
208
118
|
});
|
|
209
119
|
}
|
|
210
120
|
|
|
211
|
-
/** meta_event / system.*:返回是否建议在上线后刷新好友/群列表 */
|
|
212
121
|
export function shouldRefreshListsOnMeta(event: IcqqIpcRawEvent): boolean {
|
|
213
122
|
if (event.meta_event_type === "lifecycle") {
|
|
214
123
|
const sub = event.sub_type;
|
|
215
124
|
return sub === "connect" || sub === "enable";
|
|
216
125
|
}
|
|
217
|
-
const pt = event.post_type ?? "";
|
|
126
|
+
const pt = String(event.post_type ?? "");
|
|
218
127
|
if (pt === "system.online" || pt.endsWith(".online")) return true;
|
|
219
128
|
return false;
|
|
220
129
|
}
|
|
221
130
|
|
|
222
131
|
export function formatIcqqMetaLog(event: IcqqIpcRawEvent): string {
|
|
132
|
+
const meta =
|
|
133
|
+
(typeof event.meta_event_type === "string" && event.meta_event_type) ||
|
|
134
|
+
(typeof event.post_type === "string" && event.post_type) ||
|
|
135
|
+
"meta";
|
|
136
|
+
const subType = typeof event.sub_type === "string" ? event.sub_type : undefined;
|
|
137
|
+
const time = typeof event.time === "number" ? event.time : undefined;
|
|
223
138
|
return formatCompact({
|
|
224
|
-
meta
|
|
225
|
-
sub_type:
|
|
226
|
-
time
|
|
139
|
+
meta,
|
|
140
|
+
sub_type: subType,
|
|
141
|
+
time,
|
|
227
142
|
});
|
|
228
143
|
}
|
package/src/index.ts
CHANGED
|
@@ -31,14 +31,6 @@ declare module "zhin.js" {
|
|
|
31
31
|
export * from "./types.js";
|
|
32
32
|
export { IcqqEndpoint } from "./endpoint.js";
|
|
33
33
|
export { IcqqAdapter } from "./adapter.js";
|
|
34
|
-
export {
|
|
35
|
-
ICQQTypingIndicatorManager,
|
|
36
|
-
createICQQTypingIndicatorManager,
|
|
37
|
-
startICQQTypingIndicator,
|
|
38
|
-
enableTypingIndicator,
|
|
39
|
-
type ICQQTypingIndicatorConfig,
|
|
40
|
-
} from "./typing-indicator.js";
|
|
41
|
-
export type { TypingIndicatorConfig } from "./types.js";
|
|
42
34
|
|
|
43
35
|
const plugin = usePlugin();
|
|
44
36
|
const { provide, useContext, addCommand, root } = plugin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { toCanonicalSegments, fromCanonicalSegments } from 'zhin.js';
|
package/src/tools/index.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ICQQ
|
|
2
|
+
* ICQQ 场景管理工具注册
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 本模块注册 ICQQ 独有的扩展工具。
|
|
4
|
+
* 平台特有工具已迁移至 agent/tools/;本模块仅注册通用群管工具。
|
|
6
5
|
*/
|
|
7
|
-
import type
|
|
8
|
-
|
|
6
|
+
import { createSceneManagementTools, type ToolFeature } from 'zhin.js';
|
|
7
|
+
|
|
9
8
|
import type { IcqqAdapter } from "../adapter.js";
|
|
10
|
-
import {
|
|
9
|
+
import { setIcqqAgentDeps } from "../icqq-agent-deps.js";
|
|
11
10
|
|
|
12
11
|
export function registerTools(
|
|
13
12
|
toolService: ToolFeature,
|
|
@@ -16,397 +15,17 @@ export function registerTools(
|
|
|
16
15
|
): () => void {
|
|
17
16
|
const disposers: (() => void)[] = [];
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
type: "object",
|
|
31
|
-
properties: {
|
|
32
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
33
|
-
group_id: { type: "number", description: "目标群号" },
|
|
34
|
-
user_id: { type: "number", description: "目标成员 QQ号" },
|
|
35
|
-
title: { type: "string", description: "头衔文字" },
|
|
36
|
-
duration: { type: "number", description: "持续时间(秒),-1永久" },
|
|
37
|
-
},
|
|
38
|
-
required: ["endpoint_id", "group_id", "user_id", "title"],
|
|
39
|
-
},
|
|
40
|
-
platforms: ["icqq"],
|
|
41
|
-
tags: ["icqq"],
|
|
42
|
-
permissions: ["platform(icqq,group_owner)"],
|
|
43
|
-
execute: async (args: Record<string, any>) => {
|
|
44
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
45
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
46
|
-
const resp = await endpoint.ipc.request(Actions.SET_GROUP_TITLE, {
|
|
47
|
-
group_id: args.group_id,
|
|
48
|
-
user_id: args.user_id,
|
|
49
|
-
title: args.title,
|
|
50
|
-
duration: args.duration ?? -1,
|
|
51
|
-
});
|
|
52
|
-
return { success: resp.ok, message: resp.ok ? `已将 ${args.user_id} 的头衔设为 "${args.title}"` : (resp.error ?? "设置失败") };
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
pluginName,
|
|
56
|
-
),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
// ── 发送群公告 ─────────────────────────────────────────────────────
|
|
60
|
-
disposers.push(
|
|
61
|
-
toolService.addTool(
|
|
62
|
-
{
|
|
63
|
-
name: "icqq_announce",
|
|
64
|
-
description: "发送 QQ 群公告(需要管理员权限)",
|
|
65
|
-
parameters: {
|
|
66
|
-
type: "object",
|
|
67
|
-
properties: {
|
|
68
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
69
|
-
group_id: { type: "number", description: "目标群号" },
|
|
70
|
-
content: { type: "string", description: "公告内容" },
|
|
71
|
-
},
|
|
72
|
-
required: ["endpoint_id", "group_id", "content"],
|
|
73
|
-
},
|
|
74
|
-
platforms: ["icqq"],
|
|
75
|
-
tags: ["icqq"],
|
|
76
|
-
permissions: ["platform(icqq,group_admin)"],
|
|
77
|
-
execute: async (args: Record<string, any>) => {
|
|
78
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
79
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
80
|
-
const resp = await endpoint.ipc.request(Actions.GROUP_ANNOUNCE, {
|
|
81
|
-
group_id: args.group_id,
|
|
82
|
-
content: args.content,
|
|
83
|
-
});
|
|
84
|
-
return { success: resp.ok, message: resp.ok ? "群公告已发送" : (resp.error ?? "发送失败") };
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
pluginName,
|
|
88
|
-
),
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
// ── 戳一戳 ─────────────────────────────────────────────────────────
|
|
92
|
-
disposers.push(
|
|
93
|
-
toolService.addTool(
|
|
94
|
-
{
|
|
95
|
-
name: "icqq_poke",
|
|
96
|
-
description: "在 QQ 群中对某个成员执行戳一戳互动操作",
|
|
97
|
-
parameters: {
|
|
98
|
-
type: "object",
|
|
99
|
-
properties: {
|
|
100
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
101
|
-
group_id: { type: "number", description: "目标群号" },
|
|
102
|
-
user_id: { type: "number", description: "要戳的目标成员 QQ号" },
|
|
103
|
-
},
|
|
104
|
-
required: ["endpoint_id", "group_id", "user_id"],
|
|
105
|
-
},
|
|
106
|
-
platforms: ["icqq"],
|
|
107
|
-
tags: ["icqq"],
|
|
108
|
-
execute: async (args: Record<string, any>) => {
|
|
109
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
110
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
111
|
-
const resp = await endpoint.ipc.request(Actions.GROUP_POKE, {
|
|
112
|
-
group_id: args.group_id,
|
|
113
|
-
user_id: args.user_id,
|
|
114
|
-
});
|
|
115
|
-
return { success: resp.ok, message: resp.ok ? `已戳了戳 ${args.user_id}` : (resp.error ?? "戳一戳失败") };
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
pluginName,
|
|
119
|
-
),
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// ── 获取被禁言列表 ─────────────────────────────────────────────────
|
|
123
|
-
disposers.push(
|
|
124
|
-
toolService.addTool(
|
|
125
|
-
{
|
|
126
|
-
name: "icqq_list_muted",
|
|
127
|
-
description: "查询 QQ 群中当前被禁言的成员列表",
|
|
128
|
-
parameters: {
|
|
129
|
-
type: "object",
|
|
130
|
-
properties: {
|
|
131
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
132
|
-
group_id: { type: "number", description: "目标群号" },
|
|
133
|
-
},
|
|
134
|
-
required: ["endpoint_id", "group_id"],
|
|
135
|
-
},
|
|
136
|
-
platforms: ["icqq"],
|
|
137
|
-
tags: ["icqq"],
|
|
138
|
-
permissions: ["platform(icqq,group_admin)"],
|
|
139
|
-
execute: async (args: Record<string, any>) => {
|
|
140
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
141
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
142
|
-
const resp = await endpoint.ipc.request(Actions.GROUP_MUTED_LIST, {
|
|
143
|
-
group_id: args.group_id,
|
|
144
|
-
});
|
|
145
|
-
if (!resp.ok) throw new Error(resp.error ?? "获取禁言列表失败");
|
|
146
|
-
const list = Array.isArray(resp.data) ? resp.data : [];
|
|
147
|
-
return { muted_members: list, count: list.length };
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
pluginName,
|
|
151
|
-
),
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
// ── 给用户点赞 ─────────────────────────────────────────────────────
|
|
155
|
-
disposers.push(
|
|
156
|
-
toolService.addTool(
|
|
157
|
-
{
|
|
158
|
-
name: "icqq_send_user_like",
|
|
159
|
-
description: "给用户点赞(竖大拇指),每人每天最多 20 次",
|
|
160
|
-
parameters: {
|
|
161
|
-
type: "object",
|
|
162
|
-
properties: {
|
|
163
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
164
|
-
user_id: { type: "number", description: "要点赞的目标用户 QQ号" },
|
|
165
|
-
times: { type: "number", description: "点赞次数(1-20),默认 1" },
|
|
166
|
-
},
|
|
167
|
-
required: ["endpoint_id", "user_id"],
|
|
168
|
-
},
|
|
169
|
-
platforms: ["icqq"],
|
|
170
|
-
tags: ["icqq"],
|
|
171
|
-
execute: async (args: Record<string, any>) => {
|
|
172
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
173
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
174
|
-
const resp = await endpoint.ipc.request(Actions.FRIEND_LIKE, {
|
|
175
|
-
user_id: args.user_id,
|
|
176
|
-
times: Math.min(args.times ?? 1, 20),
|
|
177
|
-
});
|
|
178
|
-
return { success: resp.ok, message: resp.ok ? `已给 ${args.user_id} 点赞` : (resp.error ?? "点赞失败") };
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
pluginName,
|
|
182
|
-
),
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
// ── 设置匿名聊天 ───────────────────────────────────────────────────
|
|
186
|
-
disposers.push(
|
|
187
|
-
toolService.addTool(
|
|
188
|
-
{
|
|
189
|
-
name: "icqq_set_anonymous",
|
|
190
|
-
description: "开启或关闭 QQ 群的匿名聊天功能",
|
|
191
|
-
parameters: {
|
|
192
|
-
type: "object",
|
|
193
|
-
properties: {
|
|
194
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
195
|
-
group_id: { type: "number", description: "目标群号" },
|
|
196
|
-
enable: { type: "boolean", description: "true=开启,false=关闭,默认 true" },
|
|
197
|
-
},
|
|
198
|
-
required: ["endpoint_id", "group_id"],
|
|
199
|
-
},
|
|
200
|
-
platforms: ["icqq"],
|
|
201
|
-
tags: ["icqq"],
|
|
202
|
-
permissions: ["platform(icqq,group_owner)"],
|
|
203
|
-
execute: async (args: Record<string, any>) => {
|
|
204
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
205
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
206
|
-
const enable = args.enable ?? true;
|
|
207
|
-
const resp = await endpoint.ipc.request(Actions.GROUP_ALLOW_ANONY, {
|
|
208
|
-
group_id: args.group_id,
|
|
209
|
-
enable,
|
|
210
|
-
});
|
|
211
|
-
return { success: resp.ok, message: resp.ok ? (enable ? "已开启匿名聊天" : "已关闭匿名聊天") : (resp.error ?? "操作失败") };
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
pluginName,
|
|
215
|
-
),
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
// ── 群文件列表 ─────────────────────────────────────────────────────
|
|
219
|
-
disposers.push(
|
|
220
|
-
toolService.addTool(
|
|
221
|
-
{
|
|
222
|
-
name: "icqq_group_files",
|
|
223
|
-
description: "获取 QQ 群的群文件列表",
|
|
224
|
-
parameters: {
|
|
225
|
-
type: "object",
|
|
226
|
-
properties: {
|
|
227
|
-
endpoint_id: { type: "string", description: "Endpoint 名称", contextKey: 'endpointId' },
|
|
228
|
-
group_id: { type: "number", description: "群号" },
|
|
229
|
-
},
|
|
230
|
-
required: ["endpoint_id", "group_id"],
|
|
231
|
-
},
|
|
232
|
-
platforms: ["icqq"],
|
|
233
|
-
tags: ["icqq"],
|
|
234
|
-
execute: async (args: Record<string, any>) => {
|
|
235
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
236
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
237
|
-
const resp = await endpoint.ipc.request(Actions.GFS_LIST, {
|
|
238
|
-
group_id: args.group_id,
|
|
239
|
-
});
|
|
240
|
-
if (!resp.ok) throw new Error(resp.error ?? "获取群文件失败");
|
|
241
|
-
const files = Array.isArray(resp.data) ? resp.data : [];
|
|
242
|
-
if (!files.length) return { files: [], message: "群文件为空" };
|
|
243
|
-
return {
|
|
244
|
-
files: files.slice(0, 30).map((f: any) => ({
|
|
245
|
-
name: f.name,
|
|
246
|
-
size: f.size,
|
|
247
|
-
uploader: f.uploader_uin,
|
|
248
|
-
upload_time: f.upload_time,
|
|
249
|
-
})),
|
|
250
|
-
count: files.length,
|
|
251
|
-
};
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
pluginName,
|
|
255
|
-
),
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
// ── 好友列表 ───────────────────────────────────────────────────────
|
|
259
|
-
disposers.push(
|
|
260
|
-
toolService.addTool(
|
|
261
|
-
{
|
|
262
|
-
name: "icqq_friend_list",
|
|
263
|
-
description: "获取 QQ 好友列表",
|
|
264
|
-
parameters: {
|
|
265
|
-
type: "object",
|
|
266
|
-
properties: {
|
|
267
|
-
endpoint_id: { type: "string", description: "Endpoint 名称", contextKey: 'endpointId' },
|
|
268
|
-
},
|
|
269
|
-
required: ["endpoint_id"],
|
|
270
|
-
},
|
|
271
|
-
platforms: ["icqq"],
|
|
272
|
-
tags: ["icqq"],
|
|
273
|
-
execute: async (args: Record<string, any>) => {
|
|
274
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
275
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
276
|
-
const friends = Array.from(endpoint.friends.values()).map((f) => ({
|
|
277
|
-
user_id: f.user_id,
|
|
278
|
-
nickname: f.nickname,
|
|
279
|
-
remark: f.remark,
|
|
280
|
-
}));
|
|
281
|
-
return { friends: friends.slice(0, 50), count: endpoint.friends.size };
|
|
282
|
-
},
|
|
283
|
-
},
|
|
284
|
-
pluginName,
|
|
285
|
-
),
|
|
286
|
-
);
|
|
287
|
-
|
|
288
|
-
// ── 群列表 ─────────────────────────────────────────────────────────
|
|
289
|
-
disposers.push(
|
|
290
|
-
toolService.addTool(
|
|
291
|
-
{
|
|
292
|
-
name: "icqq_group_list",
|
|
293
|
-
description: "获取 Endpoint 的 QQ 群列表",
|
|
294
|
-
parameters: {
|
|
295
|
-
type: "object",
|
|
296
|
-
properties: {
|
|
297
|
-
endpoint_id: { type: "string", description: "Endpoint 名称", contextKey: 'endpointId' },
|
|
298
|
-
},
|
|
299
|
-
required: ["endpoint_id"],
|
|
300
|
-
},
|
|
301
|
-
platforms: ["icqq"],
|
|
302
|
-
tags: ["icqq"],
|
|
303
|
-
execute: async (args: Record<string, any>) => {
|
|
304
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
305
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
306
|
-
const groups = Array.from(endpoint.groups.values()).map((g) => ({
|
|
307
|
-
group_id: g.group_id,
|
|
308
|
-
group_name: g.group_name,
|
|
309
|
-
member_count: g.member_count,
|
|
310
|
-
max_member_count: g.max_member_count,
|
|
311
|
-
}));
|
|
312
|
-
return { groups: groups.slice(0, 50), count: endpoint.groups.size };
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
pluginName,
|
|
316
|
-
),
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
// ── 群签到 ─────────────────────────────────────────────────────────
|
|
320
|
-
disposers.push(
|
|
321
|
-
toolService.addTool(
|
|
322
|
-
{
|
|
323
|
-
name: "icqq_group_sign",
|
|
324
|
-
description: "QQ 群签到打卡",
|
|
325
|
-
parameters: {
|
|
326
|
-
type: "object",
|
|
327
|
-
properties: {
|
|
328
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
329
|
-
group_id: { type: "number", description: "目标群号" },
|
|
330
|
-
},
|
|
331
|
-
required: ["endpoint_id", "group_id"],
|
|
332
|
-
},
|
|
333
|
-
platforms: ["icqq"],
|
|
334
|
-
tags: ["icqq"],
|
|
335
|
-
execute: async (args: Record<string, any>) => {
|
|
336
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
337
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
338
|
-
const resp = await endpoint.ipc.request(Actions.GROUP_SIGN, {
|
|
339
|
-
group_id: args.group_id,
|
|
340
|
-
});
|
|
341
|
-
return { success: resp.ok, message: resp.ok ? "群签到成功" : (resp.error ?? "签到失败") };
|
|
342
|
-
},
|
|
343
|
-
},
|
|
344
|
-
pluginName,
|
|
345
|
-
),
|
|
346
|
-
);
|
|
347
|
-
|
|
348
|
-
// ── 邀请入群 ───────────────────────────────────────────────────────
|
|
349
|
-
disposers.push(
|
|
350
|
-
toolService.addTool(
|
|
351
|
-
{
|
|
352
|
-
name: "icqq_group_invite",
|
|
353
|
-
description: "邀请好友加入 QQ 群",
|
|
354
|
-
parameters: {
|
|
355
|
-
type: "object",
|
|
356
|
-
properties: {
|
|
357
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
358
|
-
group_id: { type: "number", description: "目标群号" },
|
|
359
|
-
user_id: { type: "number", description: "要邀请的 QQ号" },
|
|
360
|
-
},
|
|
361
|
-
required: ["endpoint_id", "group_id", "user_id"],
|
|
362
|
-
},
|
|
363
|
-
platforms: ["icqq"],
|
|
364
|
-
tags: ["icqq"],
|
|
365
|
-
execute: async (args: Record<string, any>) => {
|
|
366
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
367
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
368
|
-
const resp = await endpoint.ipc.request(Actions.GROUP_INVITE, {
|
|
369
|
-
group_id: args.group_id,
|
|
370
|
-
user_id: args.user_id,
|
|
371
|
-
});
|
|
372
|
-
return { success: resp.ok, message: resp.ok ? `已邀请 ${args.user_id} 加入群` : (resp.error ?? "邀请失败") };
|
|
373
|
-
},
|
|
374
|
-
},
|
|
375
|
-
pluginName,
|
|
376
|
-
),
|
|
377
|
-
);
|
|
378
|
-
|
|
379
|
-
// ── 设为/移除精华消息 ──────────────────────────────────────────────
|
|
380
|
-
disposers.push(
|
|
381
|
-
toolService.addTool(
|
|
382
|
-
{
|
|
383
|
-
name: "icqq_essence",
|
|
384
|
-
description: "设置或移除 QQ 群精华消息",
|
|
385
|
-
parameters: {
|
|
386
|
-
type: "object",
|
|
387
|
-
properties: {
|
|
388
|
-
endpoint_id: { type: "string", description: "Endpoint QQ号", contextKey: 'endpointId' },
|
|
389
|
-
message_id: { type: "string", description: "消息 ID" },
|
|
390
|
-
action: { type: "string", description: "add=设为精华, remove=移除精华" },
|
|
391
|
-
},
|
|
392
|
-
required: ["endpoint_id", "message_id", "action"],
|
|
393
|
-
},
|
|
394
|
-
platforms: ["icqq"],
|
|
395
|
-
tags: ["icqq"],
|
|
396
|
-
permissions: ["platform(icqq,group_admin)"],
|
|
397
|
-
execute: async (args: Record<string, any>) => {
|
|
398
|
-
const endpoint = icqq.endpoints.get(args.endpoint_id);
|
|
399
|
-
if (!endpoint) throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
|
|
400
|
-
const action = args.action === "add" ? Actions.GROUP_ESSENCE_ADD : Actions.GROUP_ESSENCE_REMOVE;
|
|
401
|
-
const resp = await endpoint.ipc.request(action, {
|
|
402
|
-
message_id: args.message_id,
|
|
403
|
-
});
|
|
404
|
-
return { success: resp.ok, message: resp.ok ? (args.action === "add" ? "已设为精华" : "已移除精华") : (resp.error ?? "操作失败") };
|
|
405
|
-
},
|
|
406
|
-
},
|
|
407
|
-
pluginName,
|
|
408
|
-
),
|
|
409
|
-
);
|
|
18
|
+
setIcqqAgentDeps({
|
|
19
|
+
getEndpoint: (endpointId) => {
|
|
20
|
+
const endpoint = icqq.endpoints.get(endpointId);
|
|
21
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
22
|
+
return endpoint;
|
|
23
|
+
},
|
|
24
|
+
getAdapter: () => icqq,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const sceneTools = createSceneManagementTools(icqq, "icqq");
|
|
28
|
+
disposers.push(...sceneTools.map((t) => toolService.addTool(t, pluginName)));
|
|
410
29
|
|
|
411
30
|
return () => disposers.forEach((d) => d());
|
|
412
31
|
}
|