@zhin.js/adapter-napcat 7.0.0 → 7.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 +30 -0
- package/README.md +18 -3
- package/adapters/napcat.js +1 -8
- package/adapters/napcat.ts +1 -8
- package/agent/tools/ai_tts.ts +4 -6
- package/agent/tools/del_group_notice.ts +4 -6
- package/agent/tools/delete_essence_msg.ts +4 -6
- package/agent/tools/delete_friend.ts +4 -6
- package/agent/tools/download_file.ts +4 -6
- package/agent/tools/forward_single_msg.ts +4 -8
- package/agent/tools/get_ai_characters.ts +4 -6
- package/agent/tools/get_essence_list.ts +4 -6
- package/agent/tools/get_friend_msg_history.ts +4 -6
- package/agent/tools/get_group_file_url.ts +4 -6
- package/agent/tools/get_group_info_ex.ts +4 -6
- package/agent/tools/get_group_msg_history.ts +4 -6
- package/agent/tools/get_group_notice.ts +4 -6
- package/agent/tools/get_group_root_files.ts +4 -6
- package/agent/tools/get_group_shut_list.ts +4 -6
- package/agent/tools/get_mini_app_ark.ts +4 -6
- package/agent/tools/get_user_status.ts +4 -6
- package/agent/tools/group_sign.ts +4 -6
- package/agent/tools/mark_msg_as_read.ts +4 -6
- package/agent/tools/ocr_image.ts +4 -6
- package/agent/tools/send_forward_msg.ts +4 -8
- package/agent/tools/send_group_notice.ts +4 -6
- package/agent/tools/send_like.ts +4 -6
- package/agent/tools/send_poke.ts +4 -6
- package/agent/tools/set_avatar.ts +4 -6
- package/agent/tools/set_emoji_reaction.ts +4 -6
- package/agent/tools/set_essence_msg.ts +4 -6
- package/agent/tools/set_group_portrait.ts +4 -6
- package/agent/tools/set_online_status.ts +4 -6
- package/agent/tools/set_profile.ts +4 -6
- package/agent/tools/set_signature.ts +4 -6
- package/agent/tools/set_title.ts +4 -6
- package/agent/tools/translate.ts +4 -6
- package/agent/tools/upload_group_file.ts +4 -6
- package/lib/{napcat-agent-deps.d.ts → client.d.ts} +15 -14
- package/lib/client.js +62 -0
- package/lib/http-endpoint.d.ts +5 -6
- package/lib/http-endpoint.js +22 -12
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/napcat-endpoint-commands.d.ts +1 -1
- package/lib/side-event-dispatch.d.ts +2 -2
- package/lib/side-event-dispatch.js +3 -3
- package/lib/ws-endpoint.d.ts +5 -41
- package/lib/ws-endpoint.js +24 -156
- package/lib/wss-endpoint.d.ts +5 -6
- package/lib/wss-endpoint.js +23 -13
- package/package.json +15 -14
- package/src/client.ts +79 -0
- package/src/http-endpoint.ts +24 -20
- package/src/index.ts +4 -7
- package/src/side-event-dispatch.ts +4 -4
- package/src/ws-endpoint.ts +26 -202
- package/src/wss-endpoint.ts +25 -21
- package/lib/napcat-agent-deps.js +0 -33
- package/src/napcat-agent-deps.ts +0 -95
package/lib/http-endpoint.js
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
1
2
|
import { createRecallEndpointControl, } from 'zhin.js/adapter';
|
|
2
3
|
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
3
4
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
4
|
-
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
5
5
|
import { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
|
|
6
6
|
import { buildSendAction, callNapCatHttpAction, formatInboundContent, formatOutboundSegments, isMessageEvent, napcatInboundConversation, napcatOutboundTarget, senderNickname, senderUserId, } from './protocol.js';
|
|
7
7
|
import { receiveNapCatSideEvent } from './side-event-dispatch.js';
|
|
8
8
|
import { createNapCatContentPort } from './onebot-get-msg.js';
|
|
9
|
+
import { NapcatClient } from './client.js';
|
|
9
10
|
import { readRequestBody } from './webhook.js';
|
|
10
11
|
import { verifyNapCatAccessToken } from './wss-auth.js';
|
|
11
|
-
export class NapCatHttpEndpoint {
|
|
12
|
+
export class NapCatHttpEndpoint extends Endpoint {
|
|
13
|
+
client = new NapcatClient((action, params) => this.#callApi(action, params));
|
|
12
14
|
#logger;
|
|
13
15
|
#options;
|
|
14
16
|
#inboundDeduper = new InboundMessageDeduper();
|
|
15
|
-
management = createNapCatEndpointManagement(this);
|
|
17
|
+
management = createNapCatEndpointManagement(this.client);
|
|
16
18
|
control = createRecallEndpointControl((id) => this.recallMessage(id));
|
|
17
|
-
content = createNapCatContentPort((action, params) => this.callApi(action, params));
|
|
19
|
+
content = createNapCatContentPort((action, params) => this.client.callApi(action, params));
|
|
18
20
|
#callHttpAction;
|
|
19
21
|
#routeReleases = [];
|
|
20
22
|
#open = false;
|
|
21
23
|
#started = false;
|
|
22
|
-
#unregisterAgent;
|
|
23
24
|
constructor(options) {
|
|
25
|
+
super();
|
|
24
26
|
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
25
27
|
this.#options = options;
|
|
26
28
|
this.#callHttpAction = options.callHttpAction ?? callNapCatHttpAction;
|
|
@@ -29,7 +31,6 @@ export class NapCatHttpEndpoint {
|
|
|
29
31
|
if (this.#started)
|
|
30
32
|
return;
|
|
31
33
|
this.#started = true;
|
|
32
|
-
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.id, this);
|
|
33
34
|
this.#setupRoutes();
|
|
34
35
|
this.#logger.info(formatCompact({
|
|
35
36
|
op: 'listen',
|
|
@@ -48,8 +49,6 @@ export class NapCatHttpEndpoint {
|
|
|
48
49
|
this.#open = false;
|
|
49
50
|
for (const release of this.#routeReleases.splice(0))
|
|
50
51
|
release();
|
|
51
|
-
this.#unregisterAgent?.();
|
|
52
|
-
this.#unregisterAgent = undefined;
|
|
53
52
|
this.#inboundDeduper.clear();
|
|
54
53
|
this.#started = false;
|
|
55
54
|
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
@@ -74,9 +73,9 @@ export class NapCatHttpEndpoint {
|
|
|
74
73
|
async recallMessage(messageId) {
|
|
75
74
|
if (!messageId)
|
|
76
75
|
return;
|
|
77
|
-
await this.callApi('delete_msg', { message_id: Number(messageId) });
|
|
76
|
+
await this.client.callApi('delete_msg', { message_id: Number(messageId) });
|
|
78
77
|
}
|
|
79
|
-
callApi(action, params = {}) {
|
|
78
|
+
#callApi(action, params = {}) {
|
|
80
79
|
return this.#callHttpAction({
|
|
81
80
|
http_url: this.#options.config.http_url,
|
|
82
81
|
access_token: this.#options.config.access_token,
|
|
@@ -85,8 +84,14 @@ export class NapCatHttpEndpoint {
|
|
|
85
84
|
admit(ev) {
|
|
86
85
|
if (!this.#open)
|
|
87
86
|
return;
|
|
87
|
+
void this.emitPlatform(napCatPlatformEventName(ev), ev).catch((error) => {
|
|
88
|
+
this.#logger.warn(formatCompact({
|
|
89
|
+
op: 'napcat_platform_event_failed',
|
|
90
|
+
error: error instanceof Error ? error.message : String(error),
|
|
91
|
+
}));
|
|
92
|
+
});
|
|
88
93
|
if (!isMessageEvent(ev)) {
|
|
89
|
-
receiveNapCatSideEvent(this
|
|
94
|
+
receiveNapCatSideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, this.client, ev, this.#logger);
|
|
90
95
|
return;
|
|
91
96
|
}
|
|
92
97
|
if (isSelfMessage(ev))
|
|
@@ -100,7 +105,7 @@ export class NapCatHttpEndpoint {
|
|
|
100
105
|
const conversation = napcatInboundConversation(String(this.#options.id), ev);
|
|
101
106
|
const nickname = senderNickname(ev);
|
|
102
107
|
const mentioned = isNapCatBotMentioned(ev);
|
|
103
|
-
void this
|
|
108
|
+
void this.emit('message.receive', {
|
|
104
109
|
conversation,
|
|
105
110
|
message: { conversation, id: msgId },
|
|
106
111
|
content: formatInboundContent(ev),
|
|
@@ -165,3 +170,8 @@ export class NapCatHttpEndpoint {
|
|
|
165
170
|
}
|
|
166
171
|
}
|
|
167
172
|
}
|
|
173
|
+
function napCatPlatformEventName(ev) {
|
|
174
|
+
return [ev.post_type, ev.message_type ?? ev.notice_type ?? ev.request_type, ev.sub_type]
|
|
175
|
+
.filter(Boolean)
|
|
176
|
+
.join('.');
|
|
177
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatOutboundSegments, getChannelId, isMessageEvent, mediaRefToOneBotFile, napcatInboundConversation, napcatOutboundTarget, resolveNapCatConfig, senderNickname, senderUserId, type MessageSegment, type NapCatActionRequest, type NapCatActionResponse, type NapCatAdapterConfig, type NapCatConfigBase, type NapCatEndpointConfig, type NapCatEvent, type NapCatHttpConfig, type NapCatMessageEvent, type NapCatSender, type NapCatWireSegment, type NapCatWsConfig, type NapCatWssConfig, type ParsedSendTarget, type ResolvedNapCatConfig, } from './protocol.js';
|
|
2
2
|
export { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
|
|
3
|
-
export {
|
|
3
|
+
export { napcatClient, type NapcatClient, type NapcatClientEventMap, } from './client.js';
|
|
4
4
|
export { parseOneBotGetMsgResponse } from './onebot-get-msg.js';
|
|
5
5
|
export { NapCatWsEndpoint, type NapCatWsEndpointOptions, } from './ws-endpoint.js';
|
|
6
6
|
export { NapCatWssEndpoint, type NapCatWssEndpointOptions, } from './wss-endpoint.js';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatOutboundSegments, getChannelId, isMessageEvent, mediaRefToOneBotFile, napcatInboundConversation, napcatOutboundTarget, resolveNapCatConfig, senderNickname, senderUserId, } from './protocol.js';
|
|
2
2
|
export { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
|
|
3
|
-
export {
|
|
3
|
+
export { napcatClient, } from './client.js';
|
|
4
4
|
export { parseOneBotGetMsgResponse } from './onebot-get-msg.js';
|
|
5
5
|
export { NapCatWsEndpoint, } from './ws-endpoint.js';
|
|
6
6
|
export { NapCatWssEndpoint, } from './wss-endpoint.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const napcatEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage>>>;
|
|
1
|
+
export declare const napcatEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EndpointEventEmitter } from 'zhin.js/adapter';
|
|
2
2
|
import { type getAdapterLogger } from '@zhin.js/logger';
|
|
3
3
|
import type { NapCatEvent } from './protocol.js';
|
|
4
4
|
export interface NapCatSideEventCaller {
|
|
5
5
|
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
6
6
|
}
|
|
7
|
-
export declare function receiveNapCatSideEvent(
|
|
7
|
+
export declare function receiveNapCatSideEvent(emit: EndpointEventEmitter, endpointKey: string, caller: NapCatSideEventCaller, raw: NapCatEvent, logger: ReturnType<typeof getAdapterLogger>): void;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { receiveOneBotLikeSideEvent } from '@zhin.js/core';
|
|
2
2
|
import { formatCompact } from '@zhin.js/logger';
|
|
3
|
-
export function receiveNapCatSideEvent(
|
|
4
|
-
if (!
|
|
3
|
+
export function receiveNapCatSideEvent(emit, endpointKey, caller, raw, logger) {
|
|
4
|
+
if (!emit)
|
|
5
5
|
return;
|
|
6
6
|
const record = raw;
|
|
7
7
|
const postType = String(record.post_type ?? '');
|
|
8
8
|
const requestType = String(record.request_type ?? '');
|
|
9
9
|
const isRequest = postType === 'request' || postType.startsWith('request.');
|
|
10
10
|
const isFriend = requestType === 'friend' || postType.includes('friend');
|
|
11
|
-
void receiveOneBotLikeSideEvent(
|
|
11
|
+
void receiveOneBotLikeSideEvent(emit, {
|
|
12
12
|
adapter: 'napcat',
|
|
13
13
|
endpointKey,
|
|
14
14
|
platform: 'napcat',
|
package/lib/ws-endpoint.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
2
|
+
import { type EndpointControl, type EndpointManagement, type EndpointSendRequest } from 'zhin.js/adapter';
|
|
3
3
|
import type { CapabilityId } from 'zhin.js';
|
|
4
4
|
import { type NapCatEvent, type NapCatWsConfig } from './protocol.js';
|
|
5
5
|
import { type NapCatWsCreateOptions, type NapCatWsSocket } from './ws-types.js';
|
|
6
|
+
import { NapcatClient } from './client.js';
|
|
6
7
|
export interface NapCatWsEndpointOptions {
|
|
7
8
|
readonly id: CapabilityId;
|
|
8
|
-
readonly gateway: MessageGateway;
|
|
9
|
-
readonly sideEvents?: SideEventGateway;
|
|
10
9
|
readonly config: NapCatWsConfig;
|
|
11
10
|
readonly createWebSocket?: (url: string, options: NapCatWsCreateOptions) => NapCatWsSocket;
|
|
12
11
|
}
|
|
13
|
-
export declare class NapCatWsEndpoint
|
|
12
|
+
export declare class NapCatWsEndpoint extends Endpoint<NapcatClient> {
|
|
14
13
|
#private;
|
|
14
|
+
readonly client: NapcatClient;
|
|
15
15
|
readonly management: EndpointManagement;
|
|
16
16
|
readonly control: EndpointControl;
|
|
17
17
|
readonly content: import("@zhin.js/adapter").EndpointContentPort;
|
|
@@ -22,42 +22,6 @@ export declare class NapCatWsEndpoint implements EndpointInstance {
|
|
|
22
22
|
stop(): Promise<void>;
|
|
23
23
|
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
24
24
|
recallMessage(messageId: string): Promise<void>;
|
|
25
|
-
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
26
|
-
setTitle(groupId: number, userId: number, title: string, duration?: number): Promise<boolean>;
|
|
27
|
-
sendLike(userId: number, times?: number): Promise<unknown>;
|
|
28
|
-
deleteFriend(userId: number): Promise<unknown>;
|
|
29
|
-
markMsgAsRead(messageId: number): Promise<unknown>;
|
|
30
|
-
ocrImage(image: string): Promise<unknown>;
|
|
31
|
-
setQQProfile(nickname: string, company?: string, email?: string, college?: string, personalNote?: string): Promise<unknown>;
|
|
32
|
-
setGroupPortrait(groupId: number, file: string): Promise<unknown>;
|
|
33
|
-
setEssenceMsg(messageId: number): Promise<unknown>;
|
|
34
|
-
deleteEssenceMsg(messageId: number): Promise<unknown>;
|
|
35
|
-
getEssenceMsgList(groupId: number): Promise<unknown>;
|
|
36
|
-
sendGroupSign(groupId: number): Promise<unknown>;
|
|
37
|
-
sendGroupNotice(groupId: number, content: string, image?: string): Promise<unknown>;
|
|
38
|
-
getGroupNotice(groupId: number): Promise<unknown>;
|
|
39
|
-
deleteGroupNotice(groupId: number, noticeId: string): Promise<unknown>;
|
|
40
|
-
uploadGroupFile(groupId: number, file: string, name: string, folder?: string): Promise<unknown>;
|
|
41
|
-
getGroupRootFiles(groupId: number): Promise<unknown>;
|
|
42
|
-
getGroupFileUrl(groupId: number, fileId: string, busid: number): Promise<unknown>;
|
|
43
|
-
downloadFile(url: string, threadCount?: number, headers?: string[]): Promise<unknown>;
|
|
44
|
-
setOnlineStatus(status: number, extStatus: number): Promise<unknown>;
|
|
45
|
-
setQQAvatar(file: string): Promise<unknown>;
|
|
46
|
-
forwardFriendSingleMsg(userId: number, messageId: number): Promise<unknown>;
|
|
47
|
-
forwardGroupSingleMsg(groupId: number, messageId: number): Promise<unknown>;
|
|
48
|
-
translateEn2Zh(sourceText: string): Promise<unknown>;
|
|
49
|
-
setMsgEmojiLike(messageId: number, emojiId: string): Promise<unknown>;
|
|
50
|
-
sendForwardMsg(messageType: 'private' | 'group', id: number, messages: unknown[]): Promise<unknown>;
|
|
51
|
-
getFriendMsgHistory(userId: number, messageSeq?: number, count?: number): Promise<unknown>;
|
|
52
|
-
getGroupMsgHistory(groupId: number, messageSeq?: number, count?: number): Promise<unknown>;
|
|
53
|
-
setSelfLongnick(longnick: string): Promise<unknown>;
|
|
54
|
-
getGroupInfoEx(groupId: number): Promise<unknown>;
|
|
55
|
-
sendPoke(userId: number, groupId?: number): Promise<unknown>;
|
|
56
|
-
ncGetUserStatus(userId: number): Promise<unknown>;
|
|
57
|
-
getGroupShutList(groupId: number): Promise<unknown>;
|
|
58
|
-
getMiniAppArk(type: string, title: string, desc: string, picUrl: string, jumpUrl: string): Promise<unknown>;
|
|
59
|
-
getAiCharacters(groupId: number): Promise<unknown>;
|
|
60
|
-
sendGroupAiRecord(groupId: number, characterId: string, text: string): Promise<unknown>;
|
|
61
25
|
/** Test / internal: admit a parsed event when the endpoint is open. */
|
|
62
26
|
admit(ev: NapCatEvent): void;
|
|
63
27
|
}
|
package/lib/ws-endpoint.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
1
2
|
/**
|
|
2
3
|
* NapCat WS client endpoint — outbound connect to NapCat.
|
|
3
4
|
*/
|
|
@@ -5,26 +6,27 @@ import WebSocket from 'ws';
|
|
|
5
6
|
import { createRecallEndpointControl, createEndpointLifecycle, } from 'zhin.js/adapter';
|
|
6
7
|
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
7
8
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
8
|
-
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
9
9
|
import { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
|
|
10
10
|
import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatOutboundSegments, isMessageEvent, napcatInboundConversation, napcatOutboundTarget, senderNickname, senderUserId, } from './protocol.js';
|
|
11
11
|
import { receiveNapCatSideEvent } from './side-event-dispatch.js';
|
|
12
12
|
import { callNapCatWsAction, handleNapCatWsMessage, rejectAllPending, } from './ws-transport.js';
|
|
13
13
|
import { createNapCatContentPort } from './onebot-get-msg.js';
|
|
14
|
-
|
|
14
|
+
import { NapcatClient } from './client.js';
|
|
15
|
+
export class NapCatWsEndpoint extends Endpoint {
|
|
16
|
+
client = new NapcatClient((action, params) => this.#callApi(action, params));
|
|
15
17
|
#logger;
|
|
16
18
|
#options;
|
|
17
19
|
#inboundDeduper = new InboundMessageDeduper();
|
|
18
|
-
management = createNapCatEndpointManagement(this);
|
|
20
|
+
management = createNapCatEndpointManagement(this.client);
|
|
19
21
|
control = createRecallEndpointControl((id) => this.recallMessage(id));
|
|
20
|
-
content = createNapCatContentPort((action, params) => this.callApi(action, params));
|
|
22
|
+
content = createNapCatContentPort((action, params) => this.client.callApi(action, params));
|
|
21
23
|
#lifecycle;
|
|
22
24
|
#ws;
|
|
23
25
|
#requestId = { value: 0 };
|
|
24
26
|
#pending = new Map();
|
|
25
27
|
#open = false;
|
|
26
|
-
#unregisterAgent;
|
|
27
28
|
constructor(options) {
|
|
29
|
+
super();
|
|
28
30
|
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
29
31
|
this.#options = options;
|
|
30
32
|
this.#lifecycle = createEndpointLifecycle({
|
|
@@ -41,16 +43,7 @@ export class NapCatWsEndpoint {
|
|
|
41
43
|
async start() {
|
|
42
44
|
if (this.#lifecycle.started)
|
|
43
45
|
return;
|
|
44
|
-
this.#
|
|
45
|
-
try {
|
|
46
|
-
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
47
|
-
}
|
|
48
|
-
catch (err) {
|
|
49
|
-
// start 失败复位由基座保证;agent 注册/反注册是适配器专有依赖,留在适配器侧
|
|
50
|
-
this.#unregisterAgent?.();
|
|
51
|
-
this.#unregisterAgent = undefined;
|
|
52
|
-
throw err;
|
|
53
|
-
}
|
|
46
|
+
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
54
47
|
}
|
|
55
48
|
open() {
|
|
56
49
|
this.#open = true;
|
|
@@ -61,8 +54,6 @@ export class NapCatWsEndpoint {
|
|
|
61
54
|
async stop() {
|
|
62
55
|
this.#open = false;
|
|
63
56
|
await this.#lifecycle.stop();
|
|
64
|
-
this.#unregisterAgent?.();
|
|
65
|
-
this.#unregisterAgent = undefined;
|
|
66
57
|
rejectAllPending(this.#pending);
|
|
67
58
|
this.#inboundDeduper.clear();
|
|
68
59
|
if (this.#ws) {
|
|
@@ -78,7 +69,7 @@ export class NapCatWsEndpoint {
|
|
|
78
69
|
async send({ conversation, payload }) {
|
|
79
70
|
const message = formatOutboundSegments(payload);
|
|
80
71
|
const { action, params } = buildSendAction(napcatOutboundTarget(conversation), message);
|
|
81
|
-
const data = await this.callApi(action, params);
|
|
72
|
+
const data = await this.client.callApi(action, params);
|
|
82
73
|
const messageId = data?.message_id != null ? String(data.message_id) : '';
|
|
83
74
|
this.#logger.debug(formatCompact({
|
|
84
75
|
op: 'napcat_send',
|
|
@@ -91,151 +82,23 @@ export class NapCatWsEndpoint {
|
|
|
91
82
|
async recallMessage(messageId) {
|
|
92
83
|
if (!messageId)
|
|
93
84
|
return;
|
|
94
|
-
await this.callApi('delete_msg', { message_id: Number(messageId) });
|
|
85
|
+
await this.client.callApi('delete_msg', { message_id: Number(messageId) });
|
|
95
86
|
}
|
|
96
|
-
callApi(action, params = {}) {
|
|
87
|
+
#callApi(action, params = {}) {
|
|
97
88
|
return callNapCatWsAction(this.#ws, this.#pending, this.#requestId, action, params);
|
|
98
89
|
}
|
|
99
|
-
// ── Agent-facing API wrappers ─────────────────────────────────────
|
|
100
|
-
async setTitle(groupId, userId, title, duration = -1) {
|
|
101
|
-
await this.callApi('set_group_special_title', {
|
|
102
|
-
group_id: groupId,
|
|
103
|
-
user_id: userId,
|
|
104
|
-
special_title: title,
|
|
105
|
-
duration,
|
|
106
|
-
});
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
109
|
-
sendLike(userId, times = 1) {
|
|
110
|
-
return this.callApi('send_like', { user_id: userId, times });
|
|
111
|
-
}
|
|
112
|
-
deleteFriend(userId) {
|
|
113
|
-
return this.callApi('delete_friend', { user_id: userId });
|
|
114
|
-
}
|
|
115
|
-
markMsgAsRead(messageId) {
|
|
116
|
-
return this.callApi('mark_msg_as_read', { message_id: messageId });
|
|
117
|
-
}
|
|
118
|
-
ocrImage(image) {
|
|
119
|
-
return this.callApi('ocr_image', { image });
|
|
120
|
-
}
|
|
121
|
-
setQQProfile(nickname, company, email, college, personalNote) {
|
|
122
|
-
return this.callApi('set_qq_profile', {
|
|
123
|
-
nickname,
|
|
124
|
-
company,
|
|
125
|
-
email,
|
|
126
|
-
college,
|
|
127
|
-
personal_note: personalNote,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
setGroupPortrait(groupId, file) {
|
|
131
|
-
return this.callApi('set_group_portrait', { group_id: groupId, file });
|
|
132
|
-
}
|
|
133
|
-
setEssenceMsg(messageId) {
|
|
134
|
-
return this.callApi('set_essence_msg', { message_id: messageId });
|
|
135
|
-
}
|
|
136
|
-
deleteEssenceMsg(messageId) {
|
|
137
|
-
return this.callApi('delete_essence_msg', { message_id: messageId });
|
|
138
|
-
}
|
|
139
|
-
getEssenceMsgList(groupId) {
|
|
140
|
-
return this.callApi('get_essence_msg_list', { group_id: groupId });
|
|
141
|
-
}
|
|
142
|
-
sendGroupSign(groupId) {
|
|
143
|
-
return this.callApi('send_group_sign', { group_id: groupId });
|
|
144
|
-
}
|
|
145
|
-
sendGroupNotice(groupId, content, image) {
|
|
146
|
-
return this.callApi('_send_group_notice', { group_id: groupId, content, image });
|
|
147
|
-
}
|
|
148
|
-
getGroupNotice(groupId) {
|
|
149
|
-
return this.callApi('_get_group_notice', { group_id: groupId });
|
|
150
|
-
}
|
|
151
|
-
deleteGroupNotice(groupId, noticeId) {
|
|
152
|
-
return this.callApi('_del_group_notice', { group_id: groupId, notice_id: noticeId });
|
|
153
|
-
}
|
|
154
|
-
uploadGroupFile(groupId, file, name, folder) {
|
|
155
|
-
return this.callApi('upload_group_file', { group_id: groupId, file, name, folder });
|
|
156
|
-
}
|
|
157
|
-
getGroupRootFiles(groupId) {
|
|
158
|
-
return this.callApi('get_group_root_files', { group_id: groupId });
|
|
159
|
-
}
|
|
160
|
-
getGroupFileUrl(groupId, fileId, busid) {
|
|
161
|
-
return this.callApi('get_group_file_url', { group_id: groupId, file_id: fileId, busid });
|
|
162
|
-
}
|
|
163
|
-
downloadFile(url, threadCount = 1, headers) {
|
|
164
|
-
return this.callApi('download_file', { url, thread_count: threadCount, headers });
|
|
165
|
-
}
|
|
166
|
-
setOnlineStatus(status, extStatus) {
|
|
167
|
-
return this.callApi('set_online_status', { status, ext_status: extStatus });
|
|
168
|
-
}
|
|
169
|
-
setQQAvatar(file) {
|
|
170
|
-
return this.callApi('set_qq_avatar', { file });
|
|
171
|
-
}
|
|
172
|
-
forwardFriendSingleMsg(userId, messageId) {
|
|
173
|
-
return this.callApi('forward_friend_single_msg', { user_id: userId, message_id: messageId });
|
|
174
|
-
}
|
|
175
|
-
forwardGroupSingleMsg(groupId, messageId) {
|
|
176
|
-
return this.callApi('forward_group_single_msg', { group_id: groupId, message_id: messageId });
|
|
177
|
-
}
|
|
178
|
-
translateEn2Zh(sourceText) {
|
|
179
|
-
return this.callApi('translate_en2zh', { source_text: sourceText });
|
|
180
|
-
}
|
|
181
|
-
setMsgEmojiLike(messageId, emojiId) {
|
|
182
|
-
return this.callApi('set_msg_emoji_like', { message_id: messageId, emoji_id: emojiId });
|
|
183
|
-
}
|
|
184
|
-
sendForwardMsg(messageType, id, messages) {
|
|
185
|
-
return this.callApi('send_forward_msg', {
|
|
186
|
-
message_type: messageType,
|
|
187
|
-
[messageType === 'group' ? 'group_id' : 'user_id']: id,
|
|
188
|
-
messages,
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
getFriendMsgHistory(userId, messageSeq, count) {
|
|
192
|
-
return this.callApi('get_friend_msg_history', {
|
|
193
|
-
user_id: userId,
|
|
194
|
-
message_seq: messageSeq,
|
|
195
|
-
count,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
getGroupMsgHistory(groupId, messageSeq, count) {
|
|
199
|
-
return this.callApi('get_group_msg_history', {
|
|
200
|
-
group_id: groupId,
|
|
201
|
-
message_seq: messageSeq,
|
|
202
|
-
count,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
setSelfLongnick(longnick) {
|
|
206
|
-
return this.callApi('set_self_longnick', { longNick: longnick });
|
|
207
|
-
}
|
|
208
|
-
getGroupInfoEx(groupId) {
|
|
209
|
-
return this.callApi('get_group_info_ex', { group_id: groupId });
|
|
210
|
-
}
|
|
211
|
-
sendPoke(userId, groupId) {
|
|
212
|
-
return this.callApi('send_poke', { user_id: userId, group_id: groupId });
|
|
213
|
-
}
|
|
214
|
-
ncGetUserStatus(userId) {
|
|
215
|
-
return this.callApi('nc_get_user_status', { user_id: userId });
|
|
216
|
-
}
|
|
217
|
-
getGroupShutList(groupId) {
|
|
218
|
-
return this.callApi('get_group_shut_list', { group_id: groupId });
|
|
219
|
-
}
|
|
220
|
-
getMiniAppArk(type, title, desc, picUrl, jumpUrl) {
|
|
221
|
-
return this.callApi('get_mini_app_ark', { type, title, desc, picUrl, jumpUrl });
|
|
222
|
-
}
|
|
223
|
-
getAiCharacters(groupId) {
|
|
224
|
-
return this.callApi('get_ai_characters', { group_id: groupId });
|
|
225
|
-
}
|
|
226
|
-
sendGroupAiRecord(groupId, characterId, text) {
|
|
227
|
-
return this.callApi('send_group_ai_record', {
|
|
228
|
-
group_id: groupId,
|
|
229
|
-
character: characterId,
|
|
230
|
-
text,
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
90
|
/** Test / internal: admit a parsed event when the endpoint is open. */
|
|
234
91
|
admit(ev) {
|
|
235
92
|
if (!this.#open)
|
|
236
93
|
return;
|
|
94
|
+
void this.emitPlatform(napCatPlatformEventName(ev), ev).catch((error) => {
|
|
95
|
+
this.#logger.warn(formatCompact({
|
|
96
|
+
op: 'napcat_platform_event_failed',
|
|
97
|
+
error: error instanceof Error ? error.message : String(error),
|
|
98
|
+
}));
|
|
99
|
+
});
|
|
237
100
|
if (!isMessageEvent(ev)) {
|
|
238
|
-
receiveNapCatSideEvent(this
|
|
101
|
+
receiveNapCatSideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, this.client, ev, this.#logger);
|
|
239
102
|
return;
|
|
240
103
|
}
|
|
241
104
|
if (isSelfMessage(ev))
|
|
@@ -250,7 +113,7 @@ export class NapCatWsEndpoint {
|
|
|
250
113
|
const content = formatInboundContent(ev);
|
|
251
114
|
const nickname = senderNickname(ev);
|
|
252
115
|
const mentioned = isNapCatBotMentioned(ev);
|
|
253
|
-
void this
|
|
116
|
+
void this.emit('message.receive', {
|
|
254
117
|
conversation,
|
|
255
118
|
message: { conversation, id: msgId },
|
|
256
119
|
content,
|
|
@@ -371,3 +234,8 @@ export class NapCatWsEndpoint {
|
|
|
371
234
|
});
|
|
372
235
|
}
|
|
373
236
|
}
|
|
237
|
+
function napCatPlatformEventName(ev) {
|
|
238
|
+
return [ev.post_type, ev.message_type ?? ev.notice_type ?? ev.request_type, ev.sub_type]
|
|
239
|
+
.filter(Boolean)
|
|
240
|
+
.join('.');
|
|
241
|
+
}
|
package/lib/wss-endpoint.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
2
|
+
import { type EndpointControl, type EndpointManagement, type EndpointSendRequest } from 'zhin.js/adapter';
|
|
3
3
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
4
4
|
import type { CapabilityId } from 'zhin.js';
|
|
5
5
|
import { type NapCatEvent, type NapCatWssConfig } from './protocol.js';
|
|
6
|
+
import { NapcatClient } from './client.js';
|
|
6
7
|
export interface NapCatWssEndpointOptions {
|
|
7
8
|
readonly id: CapabilityId;
|
|
8
|
-
readonly gateway: MessageGateway;
|
|
9
|
-
readonly sideEvents?: SideEventGateway;
|
|
10
9
|
readonly http: HttpHost;
|
|
11
10
|
readonly config: NapCatWssConfig;
|
|
12
11
|
}
|
|
13
|
-
export declare class NapCatWssEndpoint
|
|
12
|
+
export declare class NapCatWssEndpoint extends Endpoint<NapcatClient> {
|
|
14
13
|
#private;
|
|
14
|
+
readonly client: NapcatClient;
|
|
15
15
|
readonly management: EndpointManagement;
|
|
16
16
|
readonly control: EndpointControl;
|
|
17
17
|
readonly content: import("@zhin.js/adapter").EndpointContentPort;
|
|
@@ -22,6 +22,5 @@ export declare class NapCatWssEndpoint implements EndpointInstance {
|
|
|
22
22
|
stop(): Promise<void>;
|
|
23
23
|
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
24
24
|
recallMessage(messageId: string): Promise<void>;
|
|
25
|
-
callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
26
25
|
admit(ev: NapCatEvent): void;
|
|
27
26
|
}
|
package/lib/wss-endpoint.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Endpoint } from 'zhin.js/adapter';
|
|
1
2
|
/**
|
|
2
3
|
* NapCat reverse WSS endpoint — accepts inbound WebSocket from NapCat.
|
|
3
4
|
*/
|
|
@@ -5,20 +6,21 @@ import { clearInterval } from 'node:timers';
|
|
|
5
6
|
import { createRecallEndpointControl, } from 'zhin.js/adapter';
|
|
6
7
|
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
7
8
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
8
|
-
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
9
9
|
import { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
|
|
10
10
|
import { buildSendAction, formatInboundContent, formatOutboundSegments, isMessageEvent, napcatInboundConversation, napcatOutboundTarget, senderNickname, senderUserId, } from './protocol.js';
|
|
11
11
|
import { receiveNapCatSideEvent } from './side-event-dispatch.js';
|
|
12
12
|
import { createNapCatContentPort } from './onebot-get-msg.js';
|
|
13
|
+
import { NapcatClient } from './client.js';
|
|
13
14
|
import { callNapCatWsAction, handleNapCatWsMessage, rejectAllPending, startNapCatHeartbeat, } from './ws-transport.js';
|
|
14
15
|
import { verifyNapCatAccessToken } from './wss-auth.js';
|
|
15
|
-
export class NapCatWssEndpoint {
|
|
16
|
+
export class NapCatWssEndpoint extends Endpoint {
|
|
17
|
+
client = new NapcatClient((action, params) => this.#callApi(action, params));
|
|
16
18
|
#logger;
|
|
17
19
|
#options;
|
|
18
20
|
#inboundDeduper = new InboundMessageDeduper();
|
|
19
|
-
management = createNapCatEndpointManagement(this);
|
|
21
|
+
management = createNapCatEndpointManagement(this.client);
|
|
20
22
|
control = createRecallEndpointControl((id) => this.recallMessage(id));
|
|
21
|
-
content = createNapCatContentPort((action, params) => this.callApi(action, params));
|
|
23
|
+
content = createNapCatContentPort((action, params) => this.client.callApi(action, params));
|
|
22
24
|
#ws;
|
|
23
25
|
#wsRelease;
|
|
24
26
|
#heartbeatTimer;
|
|
@@ -26,8 +28,8 @@ export class NapCatWssEndpoint {
|
|
|
26
28
|
#pending = new Map();
|
|
27
29
|
#open = false;
|
|
28
30
|
#started = false;
|
|
29
|
-
#unregisterAgent;
|
|
30
31
|
constructor(options) {
|
|
32
|
+
super();
|
|
31
33
|
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
32
34
|
this.#options = options;
|
|
33
35
|
}
|
|
@@ -35,7 +37,6 @@ export class NapCatWssEndpoint {
|
|
|
35
37
|
if (this.#started)
|
|
36
38
|
return;
|
|
37
39
|
this.#started = true;
|
|
38
|
-
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.id, this);
|
|
39
40
|
const handle = this.#options.http.ws(this.#options.config.path);
|
|
40
41
|
this.#wsRelease = handle.onConnection((connection) => {
|
|
41
42
|
this.#acceptConnection(connection);
|
|
@@ -55,8 +56,6 @@ export class NapCatWssEndpoint {
|
|
|
55
56
|
}
|
|
56
57
|
async stop() {
|
|
57
58
|
this.#open = false;
|
|
58
|
-
this.#unregisterAgent?.();
|
|
59
|
-
this.#unregisterAgent = undefined;
|
|
60
59
|
this.#wsRelease?.();
|
|
61
60
|
this.#wsRelease = undefined;
|
|
62
61
|
if (this.#heartbeatTimer) {
|
|
@@ -79,22 +78,28 @@ export class NapCatWssEndpoint {
|
|
|
79
78
|
async send({ conversation, payload }) {
|
|
80
79
|
const message = formatOutboundSegments(payload);
|
|
81
80
|
const { action, params } = buildSendAction(napcatOutboundTarget(conversation), message);
|
|
82
|
-
const data = await this.callApi(action, params);
|
|
81
|
+
const data = await this.client.callApi(action, params);
|
|
83
82
|
return data?.message_id != null ? String(data.message_id) : '';
|
|
84
83
|
}
|
|
85
84
|
async recallMessage(messageId) {
|
|
86
85
|
if (!messageId)
|
|
87
86
|
return;
|
|
88
|
-
await this.callApi('delete_msg', { message_id: Number(messageId) });
|
|
87
|
+
await this.client.callApi('delete_msg', { message_id: Number(messageId) });
|
|
89
88
|
}
|
|
90
|
-
callApi(action, params = {}) {
|
|
89
|
+
#callApi(action, params = {}) {
|
|
91
90
|
return callNapCatWsAction(this.#ws, this.#pending, this.#requestId, action, params);
|
|
92
91
|
}
|
|
93
92
|
admit(ev) {
|
|
94
93
|
if (!this.#open)
|
|
95
94
|
return;
|
|
95
|
+
void this.emitPlatform(napCatPlatformEventName(ev), ev).catch((error) => {
|
|
96
|
+
this.#logger.warn(formatCompact({
|
|
97
|
+
op: 'napcat_platform_event_failed',
|
|
98
|
+
error: error instanceof Error ? error.message : String(error),
|
|
99
|
+
}));
|
|
100
|
+
});
|
|
96
101
|
if (!isMessageEvent(ev)) {
|
|
97
|
-
receiveNapCatSideEvent(this
|
|
102
|
+
receiveNapCatSideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, this.client, ev, this.#logger);
|
|
98
103
|
return;
|
|
99
104
|
}
|
|
100
105
|
if (isSelfMessage(ev))
|
|
@@ -108,7 +113,7 @@ export class NapCatWssEndpoint {
|
|
|
108
113
|
const conversation = napcatInboundConversation(String(this.#options.id), ev);
|
|
109
114
|
const nickname = senderNickname(ev);
|
|
110
115
|
const mentioned = isNapCatBotMentioned(ev);
|
|
111
|
-
void this
|
|
116
|
+
void this.emit('message.receive', {
|
|
112
117
|
conversation,
|
|
113
118
|
message: { conversation, id: msgId },
|
|
114
119
|
content: formatInboundContent(ev),
|
|
@@ -175,3 +180,8 @@ export class NapCatWssEndpoint {
|
|
|
175
180
|
}));
|
|
176
181
|
}
|
|
177
182
|
}
|
|
183
|
+
function napCatPlatformEventName(ev) {
|
|
184
|
+
return [ev.post_type, ev.message_type ?? ev.notice_type ?? ev.request_type, ev.sub_type]
|
|
185
|
+
.filter(Boolean)
|
|
186
|
+
.join('.');
|
|
187
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-napcat",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.2",
|
|
4
4
|
"description": "Zhin.js NapCat adapter for Plugin Runtime (WebSocket client, OneBot11 + NapCat extensions)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -43,12 +43,13 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"ws": "^8.21.1",
|
|
46
|
-
"@zhin.js/adapter": "1.2.
|
|
47
|
-
"@zhin.js/core": "1.5.
|
|
48
|
-
"@zhin.js/
|
|
46
|
+
"@zhin.js/adapter": "1.2.1",
|
|
47
|
+
"@zhin.js/core": "1.5.14",
|
|
48
|
+
"@zhin.js/feature-kit": "1.0.13",
|
|
49
|
+
"@zhin.js/host-http": "1.0.13",
|
|
49
50
|
"@zhin.js/im-contract": "1.0.4",
|
|
50
|
-
"@zhin.js/logger": "1.0.
|
|
51
|
-
"@zhin.js/permission": "1.0.
|
|
51
|
+
"@zhin.js/logger": "1.0.77",
|
|
52
|
+
"@zhin.js/permission": "1.0.4"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"@types/node": "^26.1.2",
|
|
@@ -56,17 +57,17 @@
|
|
|
56
57
|
"typescript": "^6.0.3",
|
|
57
58
|
"vitest": "^4.1.10",
|
|
58
59
|
"zod": "^4.4.3",
|
|
59
|
-
"@zhin.js/agent": "1.1.
|
|
60
|
-
"@zhin.js/host-http": "1.0.
|
|
61
|
-
"zhin.js": "6.0.
|
|
60
|
+
"@zhin.js/agent": "1.1.17",
|
|
61
|
+
"@zhin.js/host-http": "1.0.13",
|
|
62
|
+
"zhin.js": "6.0.14"
|
|
62
63
|
},
|
|
63
64
|
"peerDependencies": {
|
|
64
65
|
"zod": "^4.0.0",
|
|
65
|
-
"@zhin.js/adapter": "1.2.
|
|
66
|
-
"@zhin.js/agent": "1.1.
|
|
67
|
-
"@zhin.js/command": "1.0.
|
|
68
|
-
"@zhin.js/core": "1.5.
|
|
69
|
-
"zhin.js": "6.0.
|
|
66
|
+
"@zhin.js/adapter": "1.2.1",
|
|
67
|
+
"@zhin.js/agent": "1.1.17",
|
|
68
|
+
"@zhin.js/command": "1.0.16",
|
|
69
|
+
"@zhin.js/core": "1.5.14",
|
|
70
|
+
"zhin.js": "6.0.14"
|
|
70
71
|
},
|
|
71
72
|
"peerDependenciesMeta": {
|
|
72
73
|
"@zhin.js/agent": {
|