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