@zhin.js/adapter-napcat 6.0.3 → 6.0.5
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 +79 -0
- package/README.md +1 -1
- package/adapters/napcat.js +2 -2
- package/adapters/napcat.ts +2 -2
- package/lib/http-endpoint.js +18 -13
- package/lib/napcat-agent-deps.d.ts +3 -3
- package/lib/napcat-agent-deps.js +9 -9
- package/lib/protocol.d.ts +4 -4
- package/lib/protocol.js +7 -7
- package/lib/ws-endpoint.js +23 -19
- package/lib/ws-transport.d.ts +1 -1
- package/lib/ws-transport.js +1 -1
- package/lib/wss-endpoint.js +17 -12
- package/package.json +16 -15
- package/plugin.js +5 -4
- package/schema.json +41 -5
- package/src/http-endpoint.ts +19 -14
- package/src/napcat-agent-deps.ts +10 -10
- package/src/protocol.ts +10 -10
- package/src/ws-endpoint.ts +24 -20
- package/src/ws-transport.ts +2 -2
- package/src/wss-endpoint.ts +18 -13
- /package/commands/endpoint/add/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/add/{[name].ts → [id].ts} +0 -0
- /package/commands/endpoint/remove/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/remove/{[name].ts → [id].ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,84 @@
|
|
|
1
1
|
# @zhin.js/adapter-napcat
|
|
2
2
|
|
|
3
|
+
## 6.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
|
|
8
|
+
|
|
9
|
+
All adapter platform-permit checkers now accept PermissionSubject
|
|
10
|
+
(duck-typed from Message/CommandSession) instead of Message directly.
|
|
11
|
+
registerPlatformPermitChecker is replaced by host.registerPlatform in
|
|
12
|
+
the adapter plugin setup. activity-feedback service updated for new
|
|
13
|
+
PermissionHost integration.
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [6f9c366]
|
|
16
|
+
- Updated dependencies [373a56b]
|
|
17
|
+
- Updated dependencies [0de46a8]
|
|
18
|
+
- Updated dependencies [c106ecc]
|
|
19
|
+
- Updated dependencies [ca92e03]
|
|
20
|
+
- Updated dependencies [b0f37ae]
|
|
21
|
+
- Updated dependencies [ba08a2f]
|
|
22
|
+
- Updated dependencies [b08f7fe]
|
|
23
|
+
- Updated dependencies [daffd4c]
|
|
24
|
+
- Updated dependencies [36c7400]
|
|
25
|
+
- Updated dependencies [a9fa72e]
|
|
26
|
+
- Updated dependencies [c8de3ef]
|
|
27
|
+
- Updated dependencies [60f0fc8]
|
|
28
|
+
- Updated dependencies [574c990]
|
|
29
|
+
- Updated dependencies [d096f16]
|
|
30
|
+
- Updated dependencies [3f29623]
|
|
31
|
+
- Updated dependencies [2916852]
|
|
32
|
+
- Updated dependencies [d047869]
|
|
33
|
+
- Updated dependencies [162fa34]
|
|
34
|
+
- Updated dependencies [e62561e]
|
|
35
|
+
- Updated dependencies [3eeeb46]
|
|
36
|
+
- Updated dependencies [85d0f82]
|
|
37
|
+
- Updated dependencies [61bfc1c]
|
|
38
|
+
- Updated dependencies [04bad47]
|
|
39
|
+
- Updated dependencies [e40b048]
|
|
40
|
+
- Updated dependencies [5a5b1bb]
|
|
41
|
+
- Updated dependencies [f1708c3]
|
|
42
|
+
- Updated dependencies [d254a81]
|
|
43
|
+
- Updated dependencies [7123c47]
|
|
44
|
+
- Updated dependencies [05befc1]
|
|
45
|
+
- Updated dependencies [0663b6a]
|
|
46
|
+
- Updated dependencies [f28f9b3]
|
|
47
|
+
- Updated dependencies [9f340f7]
|
|
48
|
+
- Updated dependencies [e53444f]
|
|
49
|
+
- Updated dependencies [5eedd26]
|
|
50
|
+
- Updated dependencies [92b0dd7]
|
|
51
|
+
- Updated dependencies [f919b6f]
|
|
52
|
+
- Updated dependencies [098e411]
|
|
53
|
+
- Updated dependencies [e1b7c01]
|
|
54
|
+
- Updated dependencies [9b94f87]
|
|
55
|
+
- Updated dependencies [a7df753]
|
|
56
|
+
- @zhin.js/agent@1.1.5
|
|
57
|
+
- @zhin.js/host-http@1.0.8
|
|
58
|
+
- @zhin.js/permission@1.0.1
|
|
59
|
+
- @zhin.js/im-contract@1.0.3
|
|
60
|
+
- @zhin.js/adapter@1.1.7
|
|
61
|
+
- @zhin.js/plugin-runtime@1.1.5
|
|
62
|
+
- @zhin.js/command@1.0.9
|
|
63
|
+
- @zhin.js/core@1.5.4
|
|
64
|
+
- zhin.js@6.0.4
|
|
65
|
+
|
|
66
|
+
## 6.0.4
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- f8c7a54: fix: im
|
|
71
|
+
- Updated dependencies [f8c7a54]
|
|
72
|
+
- @zhin.js/logger@1.0.76
|
|
73
|
+
- @zhin.js/host-http@1.0.7
|
|
74
|
+
- @zhin.js/adapter@1.1.6
|
|
75
|
+
- @zhin.js/agent@1.1.4
|
|
76
|
+
- @zhin.js/command@1.0.8
|
|
77
|
+
- @zhin.js/core@1.5.3
|
|
78
|
+
- @zhin.js/im-contract@1.0.2
|
|
79
|
+
- @zhin.js/plugin-runtime@1.1.4
|
|
80
|
+
- zhin.js@6.0.3
|
|
81
|
+
|
|
3
82
|
## 6.0.3
|
|
4
83
|
|
|
5
84
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Zhin.js [NapCatQQ](https://github.com/NapNeko/NapCatQQ) 适配器(Plugin Runti
|
|
|
8
8
|
- 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
|
|
9
9
|
- **正向 WebSocket**(`connection: ws`):应用连 NapCat WS
|
|
10
10
|
- `access_token` 鉴权(Bearer + query)
|
|
11
|
-
- 入站经 `messageGatewayToken`(去重 + 自发过滤);出站 `send({
|
|
11
|
+
- 入站经 `messageGatewayToken`(去重 + 自发过滤);出站 `send({ conversation, payload })`
|
|
12
12
|
- 41 个 AI 工具(`agent/tools/`)
|
|
13
13
|
|
|
14
14
|
## 安装
|
package/adapters/napcat.js
CHANGED
|
@@ -25,8 +25,8 @@ export default defineAdapter({
|
|
|
25
25
|
const config = resolveNapCatConfig(context.config);
|
|
26
26
|
const gateway = context.use(messageGatewayToken);
|
|
27
27
|
// 注册到插件运行时状态(napcat.endpoint list 的"运行中"数据源)
|
|
28
|
-
context.use(napcatRuntimeStateToken).endpoints.set(config.
|
|
29
|
-
|
|
28
|
+
context.use(napcatRuntimeStateToken).endpoints.set(config.id, {
|
|
29
|
+
id: config.id,
|
|
30
30
|
mode: config.connection,
|
|
31
31
|
});
|
|
32
32
|
if (config.connection === 'wss') {
|
package/adapters/napcat.ts
CHANGED
|
@@ -36,8 +36,8 @@ export default defineAdapter<NapCatAdapterConfig>({
|
|
|
36
36
|
const config = resolveNapCatConfig(context.config);
|
|
37
37
|
const gateway = context.use(messageGatewayToken);
|
|
38
38
|
// 注册到插件运行时状态(napcat.endpoint list 的"运行中"数据源)
|
|
39
|
-
context.use(napcatRuntimeStateToken).endpoints.set(config.
|
|
40
|
-
|
|
39
|
+
context.use(napcatRuntimeStateToken).endpoints.set(config.id, {
|
|
40
|
+
id: config.id,
|
|
41
41
|
mode: config.connection,
|
|
42
42
|
});
|
|
43
43
|
if (config.connection === 'wss') {
|
package/lib/http-endpoint.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { formatCompact,
|
|
1
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
2
2
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
3
3
|
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
4
4
|
import { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
|
|
5
5
|
import { buildSendAction, callNapCatHttpAction, formatInboundContent, formatOutboundSegments, isMessageEvent, napcatInboundConversation, napcatOutboundTarget, senderNickname, senderUserId, } from './protocol.js';
|
|
6
6
|
import { readRequestBody } from './webhook.js';
|
|
7
7
|
import { verifyNapCatAccessToken } from './wss-auth.js';
|
|
8
|
-
const logger = getLogger('napcat');
|
|
9
8
|
export class NapCatHttpEndpoint {
|
|
9
|
+
#logger;
|
|
10
10
|
#options;
|
|
11
11
|
#inboundDeduper = new InboundMessageDeduper();
|
|
12
12
|
management = createNapCatEndpointManagement(this);
|
|
@@ -16,6 +16,7 @@ export class NapCatHttpEndpoint {
|
|
|
16
16
|
#started = false;
|
|
17
17
|
#unregisterAgent;
|
|
18
18
|
constructor(options) {
|
|
19
|
+
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
19
20
|
this.#options = options;
|
|
20
21
|
this.#callHttpAction = options.callHttpAction ?? callNapCatHttpAction;
|
|
21
22
|
}
|
|
@@ -23,11 +24,11 @@ export class NapCatHttpEndpoint {
|
|
|
23
24
|
if (this.#started)
|
|
24
25
|
return;
|
|
25
26
|
this.#started = true;
|
|
26
|
-
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.
|
|
27
|
+
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.id, this);
|
|
27
28
|
this.#setupRoutes();
|
|
28
|
-
logger.info(formatCompact({
|
|
29
|
+
this.#logger.info(formatCompact({
|
|
29
30
|
op: 'listen',
|
|
30
|
-
endpoint: this.#options.config.
|
|
31
|
+
endpoint: this.#options.config.id,
|
|
31
32
|
mode: 'http',
|
|
32
33
|
path: this.#options.config.post_path,
|
|
33
34
|
}));
|
|
@@ -46,7 +47,7 @@ export class NapCatHttpEndpoint {
|
|
|
46
47
|
this.#unregisterAgent = undefined;
|
|
47
48
|
this.#inboundDeduper.clear();
|
|
48
49
|
this.#started = false;
|
|
49
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
50
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
50
51
|
}
|
|
51
52
|
async send({ conversation, payload }) {
|
|
52
53
|
const message = formatOutboundSegments(payload);
|
|
@@ -57,9 +58,9 @@ export class NapCatHttpEndpoint {
|
|
|
57
58
|
}, action, params);
|
|
58
59
|
const data = resp.data;
|
|
59
60
|
const messageId = data?.message_id != null ? String(data.message_id) : '';
|
|
60
|
-
logger.debug(formatCompact({
|
|
61
|
+
this.#logger.debug(formatCompact({
|
|
61
62
|
op: 'napcat_send',
|
|
62
|
-
endpoint: this.#options.config.
|
|
63
|
+
endpoint: this.#options.config.id,
|
|
63
64
|
target: `${conversation.kind}:${conversation.id}`,
|
|
64
65
|
messageId,
|
|
65
66
|
}));
|
|
@@ -94,20 +95,24 @@ export class NapCatHttpEndpoint {
|
|
|
94
95
|
conversation,
|
|
95
96
|
message: { conversation, id: msgId },
|
|
96
97
|
content: formatInboundContent(ev),
|
|
97
|
-
sender:
|
|
98
|
+
sender: {
|
|
99
|
+
id: senderUserId(ev),
|
|
100
|
+
name: nickname,
|
|
101
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
102
|
+
},
|
|
103
|
+
endpointId: this.#options.config.id,
|
|
104
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
98
105
|
metadata: Object.freeze({
|
|
99
106
|
message_type: ev.message_type,
|
|
100
107
|
user_id: ev.user_id != null ? String(ev.user_id) : undefined,
|
|
101
108
|
group_id: ev.group_id != null ? String(ev.group_id) : undefined,
|
|
102
|
-
endpoint: this.#options.config.name,
|
|
103
109
|
time: ev.time,
|
|
104
110
|
self_id: ev.self_id != null ? String(ev.self_id) : undefined,
|
|
105
111
|
role: ev.sender?.role,
|
|
106
112
|
...(nickname ? { nickname } : {}),
|
|
107
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
108
113
|
}),
|
|
109
114
|
}).catch((err) => {
|
|
110
|
-
logger.warn(formatCompact({
|
|
115
|
+
this.#logger.warn(formatCompact({
|
|
111
116
|
op: 'napcat_gateway_receive_failed',
|
|
112
117
|
target: `${conversation.kind}:${conversation.id}`,
|
|
113
118
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -143,7 +148,7 @@ export class NapCatHttpEndpoint {
|
|
|
143
148
|
response.end(JSON.stringify({ status: 'ok' }));
|
|
144
149
|
}
|
|
145
150
|
catch (error) {
|
|
146
|
-
logger.error('NapCat HTTP webhook error:', error);
|
|
151
|
+
this.#logger.error('NapCat HTTP webhook error:', error);
|
|
147
152
|
if (!response.headersSent) {
|
|
148
153
|
response.writeHead(500, { 'Content-Type': 'application/json' });
|
|
149
154
|
response.end(JSON.stringify({ message: 'Internal Server Error' }));
|
|
@@ -41,11 +41,11 @@ export interface NapcatAgentEndpoint {
|
|
|
41
41
|
sendGroupAiRecord(groupId: number, characterId: string, text: string): Promise<unknown>;
|
|
42
42
|
}
|
|
43
43
|
export interface NapcatAgentDeps {
|
|
44
|
-
getEndpoint: (
|
|
44
|
+
getEndpoint: (endpointKey: string) => NapcatAgentEndpoint;
|
|
45
45
|
}
|
|
46
|
-
export declare function registerNapcatAgentEndpoint(
|
|
46
|
+
export declare function registerNapcatAgentEndpoint(endpointKey: string, endpoint: NapcatAgentEndpoint): () => void;
|
|
47
47
|
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
48
48
|
export declare function setNapcatAgentDeps(deps: NapcatAgentDeps | null): void;
|
|
49
49
|
export declare function getNapcatAgentDeps(): NapcatAgentDeps;
|
|
50
50
|
/** Convenience for agent/tools (unchanged call sites). */
|
|
51
|
-
export declare function getEndpoint(
|
|
51
|
+
export declare function getEndpoint(endpointKey: string): NapcatAgentEndpoint;
|
package/lib/napcat-agent-deps.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const endpoints = new Map();
|
|
6
6
|
let override = null;
|
|
7
|
-
export function registerNapcatAgentEndpoint(
|
|
8
|
-
endpoints.set(
|
|
7
|
+
export function registerNapcatAgentEndpoint(endpointKey, endpoint) {
|
|
8
|
+
endpoints.set(endpointKey, endpoint);
|
|
9
9
|
return () => {
|
|
10
|
-
if (endpoints.get(
|
|
11
|
-
endpoints.delete(
|
|
10
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
11
|
+
endpoints.delete(endpointKey);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -16,10 +16,10 @@ export function registerNapcatAgentEndpoint(endpointId, endpoint) {
|
|
|
16
16
|
export function setNapcatAgentDeps(deps) {
|
|
17
17
|
override = deps;
|
|
18
18
|
}
|
|
19
|
-
function lookup(
|
|
20
|
-
const registered = endpoints.get(
|
|
19
|
+
function lookup(endpointKey) {
|
|
20
|
+
const registered = endpoints.get(endpointKey);
|
|
21
21
|
if (!registered)
|
|
22
|
-
throw new Error(`Endpoint ${
|
|
22
|
+
throw new Error(`Endpoint ${endpointKey} not found`);
|
|
23
23
|
return registered;
|
|
24
24
|
}
|
|
25
25
|
export function getNapcatAgentDeps() {
|
|
@@ -28,6 +28,6 @@ export function getNapcatAgentDeps() {
|
|
|
28
28
|
return { getEndpoint: lookup };
|
|
29
29
|
}
|
|
30
30
|
/** Convenience for agent/tools (unchanged call sites). */
|
|
31
|
-
export function getEndpoint(
|
|
32
|
-
return getNapcatAgentDeps().getEndpoint(
|
|
31
|
+
export function getEndpoint(endpointKey) {
|
|
32
|
+
return getNapcatAgentDeps().getEndpoint(endpointKey);
|
|
33
33
|
}
|
package/lib/protocol.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { ConversationRef } from '@zhin.js/im-contract';
|
|
|
9
9
|
export interface NapCatLegacyEndpointRow {
|
|
10
10
|
readonly context?: string;
|
|
11
11
|
readonly connection?: 'ws' | 'wss' | 'http';
|
|
12
|
-
readonly
|
|
12
|
+
readonly id?: string;
|
|
13
13
|
readonly access_token?: string;
|
|
14
14
|
readonly url?: string;
|
|
15
15
|
readonly path?: string;
|
|
@@ -22,7 +22,7 @@ export interface NapCatLegacyEndpointRow {
|
|
|
22
22
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
23
23
|
export interface NapCatAdapterConfig {
|
|
24
24
|
readonly connection?: 'ws' | 'wss' | 'http';
|
|
25
|
-
readonly
|
|
25
|
+
readonly id?: string;
|
|
26
26
|
readonly access_token?: string;
|
|
27
27
|
readonly url?: string;
|
|
28
28
|
readonly path?: string;
|
|
@@ -36,7 +36,7 @@ export interface NapCatAdapterConfig {
|
|
|
36
36
|
}
|
|
37
37
|
export interface NapCatConfigBase {
|
|
38
38
|
readonly context: 'napcat';
|
|
39
|
-
readonly
|
|
39
|
+
readonly id: string;
|
|
40
40
|
readonly access_token?: string;
|
|
41
41
|
}
|
|
42
42
|
/** 正向 WebSocket:应用连 NapCat WS */
|
|
@@ -121,7 +121,7 @@ export declare function getChannelId(ev: NapCatEvent): string;
|
|
|
121
121
|
* 入站归一化 → ConversationRef:群消息 → kind 'group';私聊临时会话
|
|
122
122
|
* (sub_type 'group')→ kind 'private' + 群容器进 `parent`;其余私聊 → 'private'。
|
|
123
123
|
*/
|
|
124
|
-
export declare function napcatInboundConversation(
|
|
124
|
+
export declare function napcatInboundConversation(endpointKey: string, ev: NapCatEvent): ConversationRef;
|
|
125
125
|
/** 出站:ConversationRef → OneBot 私聊/群聊目标。 */
|
|
126
126
|
export declare function napcatOutboundTarget(conversation: ConversationRef): ParsedSendTarget;
|
|
127
127
|
export declare function formatInboundContent(ev: NapCatEvent): string;
|
package/lib/protocol.js
CHANGED
|
@@ -14,8 +14,8 @@ function normalizeConnection(connection) {
|
|
|
14
14
|
export function resolveNapCatConfig(config = {}) {
|
|
15
15
|
const entry = config.endpoints?.find((item) => item.context === 'napcat');
|
|
16
16
|
const connection = normalizeConnection(config.connection ?? entry?.connection);
|
|
17
|
-
const
|
|
18
|
-
|| (typeof entry?.
|
|
17
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
18
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
19
19
|
|| process.env.NAPCAT_BOT_NAME
|
|
20
20
|
|| 'napcat-bot';
|
|
21
21
|
const access_token = config.access_token ?? entry?.access_token;
|
|
@@ -27,7 +27,7 @@ export function resolveNapCatConfig(config = {}) {
|
|
|
27
27
|
return {
|
|
28
28
|
context: 'napcat',
|
|
29
29
|
connection: 'ws',
|
|
30
|
-
|
|
30
|
+
id,
|
|
31
31
|
access_token,
|
|
32
32
|
url,
|
|
33
33
|
reconnect_interval: config.reconnect_interval ?? entry?.reconnect_interval ?? 5000,
|
|
@@ -41,7 +41,7 @@ export function resolveNapCatConfig(config = {}) {
|
|
|
41
41
|
return {
|
|
42
42
|
context: 'napcat',
|
|
43
43
|
connection: 'wss',
|
|
44
|
-
|
|
44
|
+
id,
|
|
45
45
|
access_token,
|
|
46
46
|
path,
|
|
47
47
|
heartbeat_interval: config.heartbeat_interval ?? entry?.heartbeat_interval ?? 30_000,
|
|
@@ -56,7 +56,7 @@ export function resolveNapCatConfig(config = {}) {
|
|
|
56
56
|
return {
|
|
57
57
|
context: 'napcat',
|
|
58
58
|
connection: 'http',
|
|
59
|
-
|
|
59
|
+
id,
|
|
60
60
|
access_token,
|
|
61
61
|
http_url,
|
|
62
62
|
post_path,
|
|
@@ -82,8 +82,8 @@ export function getChannelId(ev) {
|
|
|
82
82
|
* 入站归一化 → ConversationRef:群消息 → kind 'group';私聊临时会话
|
|
83
83
|
* (sub_type 'group')→ kind 'private' + 群容器进 `parent`;其余私聊 → 'private'。
|
|
84
84
|
*/
|
|
85
|
-
export function napcatInboundConversation(
|
|
86
|
-
const endpoint = { id:
|
|
85
|
+
export function napcatInboundConversation(endpointKey, ev) {
|
|
86
|
+
const endpoint = { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey };
|
|
87
87
|
const isGroup = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private');
|
|
88
88
|
if (isGroup && ev.group_id != null) {
|
|
89
89
|
return { endpoint, kind: 'group', id: String(ev.group_id) };
|
package/lib/ws-endpoint.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import WebSocket from 'ws';
|
|
5
5
|
import { createEndpointLifecycle, } from '@zhin.js/adapter';
|
|
6
|
-
import { formatCompact,
|
|
6
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
7
7
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
8
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 { callNapCatWsAction, handleNapCatWsMessage, rejectAllPending, } from './ws-transport.js';
|
|
12
|
-
const logger = getLogger('napcat');
|
|
13
12
|
export class NapCatWsEndpoint {
|
|
13
|
+
#logger;
|
|
14
14
|
#options;
|
|
15
15
|
#inboundDeduper = new InboundMessageDeduper();
|
|
16
16
|
management = createNapCatEndpointManagement(this);
|
|
@@ -21,9 +21,10 @@ export class NapCatWsEndpoint {
|
|
|
21
21
|
#open = false;
|
|
22
22
|
#unregisterAgent;
|
|
23
23
|
constructor(options) {
|
|
24
|
+
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
24
25
|
this.#options = options;
|
|
25
26
|
this.#lifecycle = createEndpointLifecycle({
|
|
26
|
-
name: options.config.
|
|
27
|
+
name: options.config.id,
|
|
27
28
|
// reconnect_interval 旧语义为固定间隔:multiplier 1 + 无 jitter + 不封顶
|
|
28
29
|
reconnect: {
|
|
29
30
|
initialIntervalMs: options.config.reconnect_interval,
|
|
@@ -36,7 +37,7 @@ export class NapCatWsEndpoint {
|
|
|
36
37
|
async start() {
|
|
37
38
|
if (this.#lifecycle.started)
|
|
38
39
|
return;
|
|
39
|
-
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.
|
|
40
|
+
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.id, this);
|
|
40
41
|
try {
|
|
41
42
|
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
42
43
|
}
|
|
@@ -75,9 +76,9 @@ export class NapCatWsEndpoint {
|
|
|
75
76
|
const { action, params } = buildSendAction(napcatOutboundTarget(conversation), message);
|
|
76
77
|
const data = await this.callApi(action, params);
|
|
77
78
|
const messageId = data?.message_id != null ? String(data.message_id) : '';
|
|
78
|
-
logger.debug(formatCompact({
|
|
79
|
+
this.#logger.debug(formatCompact({
|
|
79
80
|
op: 'napcat_send',
|
|
80
|
-
endpoint: this.#options.config.
|
|
81
|
+
endpoint: this.#options.config.id,
|
|
81
82
|
target: `${conversation.kind}:${conversation.id}`,
|
|
82
83
|
messageId,
|
|
83
84
|
}));
|
|
@@ -245,20 +246,24 @@ export class NapCatWsEndpoint {
|
|
|
245
246
|
conversation,
|
|
246
247
|
message: { conversation, id: msgId },
|
|
247
248
|
content,
|
|
248
|
-
sender:
|
|
249
|
+
sender: {
|
|
250
|
+
id: senderUserId(ev),
|
|
251
|
+
name: nickname,
|
|
252
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
253
|
+
},
|
|
254
|
+
endpointId: this.#options.config.id,
|
|
255
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
249
256
|
metadata: Object.freeze({
|
|
250
257
|
message_type: ev.message_type,
|
|
251
258
|
user_id: ev.user_id != null ? String(ev.user_id) : undefined,
|
|
252
259
|
group_id: ev.group_id != null ? String(ev.group_id) : undefined,
|
|
253
|
-
endpoint: this.#options.config.name,
|
|
254
260
|
time: ev.time,
|
|
255
261
|
self_id: ev.self_id != null ? String(ev.self_id) : undefined,
|
|
256
262
|
role: ev.sender?.role,
|
|
257
263
|
...(nickname ? { nickname } : {}),
|
|
258
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
259
264
|
}),
|
|
260
265
|
}).catch((err) => {
|
|
261
|
-
logger.warn(formatCompact({
|
|
266
|
+
this.#logger.warn(formatCompact({
|
|
262
267
|
op: 'napcat_gateway_receive_failed',
|
|
263
268
|
target: `${conversation.kind}:${conversation.id}`,
|
|
264
269
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -286,14 +291,14 @@ export class NapCatWsEndpoint {
|
|
|
286
291
|
return;
|
|
287
292
|
settled = true;
|
|
288
293
|
if (!this.#options.config.access_token) {
|
|
289
|
-
logger.warn(formatCompact({
|
|
290
|
-
endpoint: this.#options.config.
|
|
294
|
+
this.#logger.warn(formatCompact({
|
|
295
|
+
endpoint: this.#options.config.id,
|
|
291
296
|
ok: false,
|
|
292
297
|
error: 'missing access_token',
|
|
293
298
|
}));
|
|
294
299
|
}
|
|
295
|
-
logger.debug(formatCompact({
|
|
296
|
-
endpoint: this.#options.config.
|
|
300
|
+
this.#logger.debug(formatCompact({
|
|
301
|
+
endpoint: this.#options.config.id,
|
|
297
302
|
mode: 'ws',
|
|
298
303
|
url: safeUrl,
|
|
299
304
|
}));
|
|
@@ -312,7 +317,7 @@ export class NapCatWsEndpoint {
|
|
|
312
317
|
});
|
|
313
318
|
ws.on('message', (data) => {
|
|
314
319
|
handleNapCatWsMessage(data, {
|
|
315
|
-
|
|
320
|
+
endpointId: this.#options.config.id,
|
|
316
321
|
pending: this.#pending,
|
|
317
322
|
admit: (event) => this.admit(event),
|
|
318
323
|
});
|
|
@@ -329,9 +334,8 @@ export class NapCatWsEndpoint {
|
|
|
329
334
|
: codeNum === 1006
|
|
330
335
|
? ' [abnormal]'
|
|
331
336
|
: '';
|
|
332
|
-
logger.warn(formatCompact({
|
|
337
|
+
this.#logger.warn(formatCompact({
|
|
333
338
|
op: 'disconnect',
|
|
334
|
-
endpoint: this.#options.config.name,
|
|
335
339
|
code: codeNum,
|
|
336
340
|
error: `${reasonStr || 'closed'}${codeHint}`,
|
|
337
341
|
reconnect_ms: this.#options.config.reconnect_interval,
|
|
@@ -345,9 +349,9 @@ export class NapCatWsEndpoint {
|
|
|
345
349
|
});
|
|
346
350
|
ws.on('error', (err) => {
|
|
347
351
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
348
|
-
logger.warn(formatCompact({
|
|
352
|
+
this.#logger.warn(formatCompact({
|
|
349
353
|
op: 'ws_error',
|
|
350
|
-
endpoint: this.#options.config.
|
|
354
|
+
endpoint: this.#options.config.id,
|
|
351
355
|
ok: false,
|
|
352
356
|
error: error.message,
|
|
353
357
|
}));
|
package/lib/ws-transport.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type NapCatEvent } from './protocol.js';
|
|
|
2
2
|
import { type NapCatPendingAction, type NapCatWsSocket } from './ws-types.js';
|
|
3
3
|
export declare function decodeWsPayload(data: unknown): string;
|
|
4
4
|
export declare function handleNapCatWsMessage(data: unknown, options: {
|
|
5
|
-
readonly
|
|
5
|
+
readonly endpointId: string;
|
|
6
6
|
readonly pending: Map<string, NapCatPendingAction>;
|
|
7
7
|
readonly admit: (ev: NapCatEvent) => void;
|
|
8
8
|
}): void;
|
package/lib/ws-transport.js
CHANGED
|
@@ -34,7 +34,7 @@ export function handleNapCatWsMessage(data, options) {
|
|
|
34
34
|
catch (error) {
|
|
35
35
|
logger.warn(formatCompact({
|
|
36
36
|
op: 'napcat_parse_failed',
|
|
37
|
-
endpoint: options.
|
|
37
|
+
endpoint: options.endpointId,
|
|
38
38
|
error: error instanceof Error ? error.message : String(error),
|
|
39
39
|
}));
|
|
40
40
|
}
|
package/lib/wss-endpoint.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* NapCat reverse WSS endpoint — accepts inbound WebSocket from NapCat.
|
|
3
3
|
*/
|
|
4
4
|
import { clearInterval } from 'node:timers';
|
|
5
|
-
import { formatCompact,
|
|
5
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
6
6
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
7
7
|
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
8
8
|
import { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
|
|
9
9
|
import { buildSendAction, formatInboundContent, formatOutboundSegments, isMessageEvent, napcatInboundConversation, napcatOutboundTarget, senderNickname, senderUserId, } from './protocol.js';
|
|
10
10
|
import { callNapCatWsAction, handleNapCatWsMessage, rejectAllPending, startNapCatHeartbeat, } from './ws-transport.js';
|
|
11
11
|
import { verifyNapCatAccessToken } from './wss-auth.js';
|
|
12
|
-
const logger = getLogger('napcat');
|
|
13
12
|
export class NapCatWssEndpoint {
|
|
13
|
+
#logger;
|
|
14
14
|
#options;
|
|
15
15
|
#inboundDeduper = new InboundMessageDeduper();
|
|
16
16
|
management = createNapCatEndpointManagement(this);
|
|
@@ -23,20 +23,21 @@ export class NapCatWssEndpoint {
|
|
|
23
23
|
#started = false;
|
|
24
24
|
#unregisterAgent;
|
|
25
25
|
constructor(options) {
|
|
26
|
+
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
26
27
|
this.#options = options;
|
|
27
28
|
}
|
|
28
29
|
async start() {
|
|
29
30
|
if (this.#started)
|
|
30
31
|
return;
|
|
31
32
|
this.#started = true;
|
|
32
|
-
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.
|
|
33
|
+
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.id, this);
|
|
33
34
|
const handle = this.#options.http.ws(this.#options.config.path);
|
|
34
35
|
this.#wsRelease = handle.onConnection((connection) => {
|
|
35
36
|
this.#acceptConnection(connection);
|
|
36
37
|
});
|
|
37
|
-
logger.info(formatCompact({
|
|
38
|
+
this.#logger.info(formatCompact({
|
|
38
39
|
op: 'listen',
|
|
39
|
-
endpoint: this.#options.config.
|
|
40
|
+
endpoint: this.#options.config.id,
|
|
40
41
|
mode: 'wss',
|
|
41
42
|
path: this.#options.config.path,
|
|
42
43
|
}));
|
|
@@ -102,20 +103,24 @@ export class NapCatWssEndpoint {
|
|
|
102
103
|
conversation,
|
|
103
104
|
message: { conversation, id: msgId },
|
|
104
105
|
content: formatInboundContent(ev),
|
|
105
|
-
sender:
|
|
106
|
+
sender: {
|
|
107
|
+
id: senderUserId(ev),
|
|
108
|
+
name: nickname,
|
|
109
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
110
|
+
},
|
|
111
|
+
endpointId: this.#options.config.id,
|
|
112
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
106
113
|
metadata: Object.freeze({
|
|
107
114
|
message_type: ev.message_type,
|
|
108
115
|
user_id: ev.user_id != null ? String(ev.user_id) : undefined,
|
|
109
116
|
group_id: ev.group_id != null ? String(ev.group_id) : undefined,
|
|
110
|
-
endpoint: this.#options.config.name,
|
|
111
117
|
time: ev.time,
|
|
112
118
|
self_id: ev.self_id != null ? String(ev.self_id) : undefined,
|
|
113
119
|
role: ev.sender?.role,
|
|
114
120
|
...(nickname ? { nickname } : {}),
|
|
115
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
116
121
|
}),
|
|
117
122
|
}).catch((err) => {
|
|
118
|
-
logger.warn(formatCompact({
|
|
123
|
+
this.#logger.warn(formatCompact({
|
|
119
124
|
op: 'napcat_gateway_receive_failed',
|
|
120
125
|
target: `${conversation.kind}:${conversation.id}`,
|
|
121
126
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -140,7 +145,7 @@ export class NapCatWssEndpoint {
|
|
|
140
145
|
this.#heartbeatTimer = startNapCatHeartbeat(this.#ws, this.#options.config.heartbeat_interval, this.#heartbeatTimer);
|
|
141
146
|
socket.on('message', (data) => {
|
|
142
147
|
handleNapCatWsMessage(data, {
|
|
143
|
-
|
|
148
|
+
endpointId: this.#options.config.id,
|
|
144
149
|
pending: this.#pending,
|
|
145
150
|
admit: (event) => this.admit(event),
|
|
146
151
|
});
|
|
@@ -154,8 +159,8 @@ export class NapCatWssEndpoint {
|
|
|
154
159
|
}
|
|
155
160
|
}
|
|
156
161
|
});
|
|
157
|
-
logger.debug(formatCompact({
|
|
158
|
-
endpoint: this.#options.config.
|
|
162
|
+
this.#logger.debug(formatCompact({
|
|
163
|
+
endpoint: this.#options.config.id,
|
|
159
164
|
mode: 'wss',
|
|
160
165
|
peer: connection.request.socket.remoteAddress,
|
|
161
166
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-napcat",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.5",
|
|
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,13 +43,14 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"ws": "^8.21.1",
|
|
46
|
-
"@zhin.js/adapter": "1.1.
|
|
47
|
-
"@zhin.js/command": "1.0.
|
|
48
|
-
"@zhin.js/core": "1.5.
|
|
49
|
-
"@zhin.js/host-http": "1.0.
|
|
50
|
-
"@zhin.js/im-contract": "1.0.
|
|
51
|
-
"@zhin.js/logger": "1.0.
|
|
52
|
-
"@zhin.js/
|
|
46
|
+
"@zhin.js/adapter": "1.1.7",
|
|
47
|
+
"@zhin.js/command": "1.0.9",
|
|
48
|
+
"@zhin.js/core": "1.5.4",
|
|
49
|
+
"@zhin.js/host-http": "1.0.8",
|
|
50
|
+
"@zhin.js/im-contract": "1.0.3",
|
|
51
|
+
"@zhin.js/logger": "1.0.76",
|
|
52
|
+
"@zhin.js/permission": "1.0.1",
|
|
53
|
+
"@zhin.js/plugin-runtime": "1.1.5"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@types/node": "^26.1.2",
|
|
@@ -57,16 +58,16 @@
|
|
|
57
58
|
"typescript": "^6.0.3",
|
|
58
59
|
"vitest": "^4.1.10",
|
|
59
60
|
"zod": "^4.4.3",
|
|
60
|
-
"@zhin.js/agent": "1.1.
|
|
61
|
-
"@zhin.js/host-http": "1.0.
|
|
61
|
+
"@zhin.js/agent": "1.1.5",
|
|
62
|
+
"@zhin.js/host-http": "1.0.8"
|
|
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/core": "1.5.
|
|
68
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
69
|
-
"zhin.js": "6.0.
|
|
66
|
+
"@zhin.js/adapter": "1.1.7",
|
|
67
|
+
"@zhin.js/agent": "1.1.5",
|
|
68
|
+
"@zhin.js/core": "1.5.4",
|
|
69
|
+
"@zhin.js/plugin-runtime": "1.1.5",
|
|
70
|
+
"zhin.js": "6.0.4"
|
|
70
71
|
},
|
|
71
72
|
"peerDependenciesMeta": {
|
|
72
73
|
"zhin.js": {
|
package/plugin.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { createEndpointRuntimeState } from '@zhin.js/adapter';
|
|
3
3
|
import { definePlugin } from '@zhin.js/plugin-runtime';
|
|
4
|
-
import {
|
|
4
|
+
import { permissionHostToken, createSceneRolePlatformChecker } from '@zhin.js/permission';
|
|
5
5
|
import { napcatRuntimeStateToken } from "./lib/napcat-runtime-state.js";
|
|
6
6
|
export default definePlugin({
|
|
7
7
|
name: 'napcat',
|
|
@@ -9,9 +9,10 @@ export default definePlugin({
|
|
|
9
9
|
displayName: 'NapCat Adapter',
|
|
10
10
|
},
|
|
11
11
|
setup(context) {
|
|
12
|
-
// 运行中 endpoint 注册表(napcat.endpoint list 的"运行中"数据源)
|
|
13
12
|
context.resources.provide(napcatRuntimeStateToken, createEndpointRuntimeState());
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
if (context.resources.has(permissionHostToken)) {
|
|
14
|
+
const host = context.resources.use(permissionHostToken);
|
|
15
|
+
return host.registerPlatform('napcat', createSceneRolePlatformChecker());
|
|
16
|
+
}
|
|
16
17
|
},
|
|
17
18
|
});
|
package/schema.json
CHANGED
|
@@ -25,16 +25,48 @@
|
|
|
25
25
|
"type": "number",
|
|
26
26
|
"default": 30000
|
|
27
27
|
},
|
|
28
|
+
"master": {
|
|
29
|
+
"type": [
|
|
30
|
+
"string",
|
|
31
|
+
"number"
|
|
32
|
+
],
|
|
33
|
+
"description": "框架 master(QQ uin;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
34
|
+
},
|
|
35
|
+
"trusted": {
|
|
36
|
+
"type": "array",
|
|
37
|
+
"items": {
|
|
38
|
+
"type": [
|
|
39
|
+
"string",
|
|
40
|
+
"number"
|
|
41
|
+
],
|
|
42
|
+
"description": "Trusted QQ uin"
|
|
43
|
+
},
|
|
44
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
45
|
+
},
|
|
28
46
|
"endpoints": {
|
|
29
47
|
"type": "array",
|
|
30
|
-
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(
|
|
48
|
+
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
31
49
|
"items": {
|
|
32
50
|
"type": "object",
|
|
33
51
|
"additionalProperties": true,
|
|
34
52
|
"properties": {
|
|
35
|
-
"
|
|
36
|
-
"type":
|
|
37
|
-
|
|
53
|
+
"master": {
|
|
54
|
+
"type": [
|
|
55
|
+
"string",
|
|
56
|
+
"number"
|
|
57
|
+
],
|
|
58
|
+
"description": "本 endpoint 的框架 master(QQ uin);覆盖顶层 master"
|
|
59
|
+
},
|
|
60
|
+
"trusted": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": {
|
|
63
|
+
"type": [
|
|
64
|
+
"string",
|
|
65
|
+
"number"
|
|
66
|
+
],
|
|
67
|
+
"description": "Trusted QQ uin"
|
|
68
|
+
},
|
|
69
|
+
"description": "本 endpoint 的 trusted 列表"
|
|
38
70
|
},
|
|
39
71
|
"url": {
|
|
40
72
|
"type": "string",
|
|
@@ -55,10 +87,14 @@
|
|
|
55
87
|
"access_token": {
|
|
56
88
|
"type": "string",
|
|
57
89
|
"description": "NapCat access token"
|
|
90
|
+
},
|
|
91
|
+
"id": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"description": "NapCat bot name"
|
|
58
94
|
}
|
|
59
95
|
},
|
|
60
96
|
"required": [
|
|
61
|
-
"
|
|
97
|
+
"id"
|
|
62
98
|
]
|
|
63
99
|
}
|
|
64
100
|
},
|
package/src/http-endpoint.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
5
5
|
import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
|
|
6
6
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
7
7
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
8
|
-
import { formatCompact,
|
|
8
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
9
9
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
10
10
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
11
11
|
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
@@ -32,8 +32,6 @@ import { readRequestBody } from './webhook.js';
|
|
|
32
32
|
import { NapCatWsEndpoint } from './ws-endpoint.js';
|
|
33
33
|
import { verifyNapCatAccessToken } from './wss-auth.js';
|
|
34
34
|
|
|
35
|
-
const logger = getLogger('napcat');
|
|
36
|
-
|
|
37
35
|
export interface NapCatHttpEndpointOptions {
|
|
38
36
|
readonly id: CapabilityId;
|
|
39
37
|
readonly gateway: MessageGateway;
|
|
@@ -43,6 +41,8 @@ export interface NapCatHttpEndpointOptions {
|
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
export class NapCatHttpEndpoint implements EndpointInstance {
|
|
44
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
45
|
+
|
|
46
46
|
readonly #options: NapCatHttpEndpointOptions;
|
|
47
47
|
readonly #inboundDeduper = new InboundMessageDeduper();
|
|
48
48
|
readonly management: EndpointManagement = createNapCatEndpointManagement(this);
|
|
@@ -53,6 +53,7 @@ export class NapCatHttpEndpoint implements EndpointInstance {
|
|
|
53
53
|
#unregisterAgent?: () => void;
|
|
54
54
|
|
|
55
55
|
constructor(options: NapCatHttpEndpointOptions) {
|
|
56
|
+
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
56
57
|
this.#options = options;
|
|
57
58
|
this.#callHttpAction = options.callHttpAction ?? callNapCatHttpAction;
|
|
58
59
|
}
|
|
@@ -61,13 +62,13 @@ export class NapCatHttpEndpoint implements EndpointInstance {
|
|
|
61
62
|
if (this.#started) return;
|
|
62
63
|
this.#started = true;
|
|
63
64
|
this.#unregisterAgent = registerNapcatAgentEndpoint(
|
|
64
|
-
this.#options.config.
|
|
65
|
+
this.#options.config.id,
|
|
65
66
|
this as unknown as NapCatWsEndpoint,
|
|
66
67
|
);
|
|
67
68
|
this.#setupRoutes();
|
|
68
|
-
logger.info(formatCompact({
|
|
69
|
+
this.#logger.info(formatCompact({
|
|
69
70
|
op: 'listen',
|
|
70
|
-
endpoint: this.#options.config.
|
|
71
|
+
endpoint: this.#options.config.id,
|
|
71
72
|
mode: 'http',
|
|
72
73
|
path: this.#options.config.post_path,
|
|
73
74
|
}));
|
|
@@ -88,7 +89,7 @@ export class NapCatHttpEndpoint implements EndpointInstance {
|
|
|
88
89
|
this.#unregisterAgent = undefined;
|
|
89
90
|
this.#inboundDeduper.clear();
|
|
90
91
|
this.#started = false;
|
|
91
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
92
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -104,9 +105,9 @@ export class NapCatHttpEndpoint implements EndpointInstance {
|
|
|
104
105
|
);
|
|
105
106
|
const data = resp.data as { message_id?: number | string } | undefined;
|
|
106
107
|
const messageId = data?.message_id != null ? String(data.message_id) : '';
|
|
107
|
-
logger.debug(formatCompact({
|
|
108
|
+
this.#logger.debug(formatCompact({
|
|
108
109
|
op: 'napcat_send',
|
|
109
|
-
endpoint: this.#options.config.
|
|
110
|
+
endpoint: this.#options.config.id,
|
|
110
111
|
target: `${conversation.kind}:${conversation.id}`,
|
|
111
112
|
messageId,
|
|
112
113
|
}));
|
|
@@ -144,20 +145,24 @@ export class NapCatHttpEndpoint implements EndpointInstance {
|
|
|
144
145
|
conversation,
|
|
145
146
|
message: { conversation, id: msgId },
|
|
146
147
|
content: formatInboundContent(ev),
|
|
147
|
-
sender:
|
|
148
|
+
sender: {
|
|
149
|
+
id: senderUserId(ev),
|
|
150
|
+
name: nickname,
|
|
151
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
152
|
+
},
|
|
153
|
+
endpointId: this.#options.config.id,
|
|
154
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
148
155
|
metadata: Object.freeze({
|
|
149
156
|
message_type: ev.message_type,
|
|
150
157
|
user_id: ev.user_id != null ? String(ev.user_id) : undefined,
|
|
151
158
|
group_id: ev.group_id != null ? String(ev.group_id) : undefined,
|
|
152
|
-
endpoint: this.#options.config.name,
|
|
153
159
|
time: ev.time,
|
|
154
160
|
self_id: ev.self_id != null ? String(ev.self_id) : undefined,
|
|
155
161
|
role: ev.sender?.role,
|
|
156
162
|
...(nickname ? { nickname } : {}),
|
|
157
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
158
163
|
}),
|
|
159
164
|
}).catch((err) => {
|
|
160
|
-
logger.warn(formatCompact({
|
|
165
|
+
this.#logger.warn(formatCompact({
|
|
161
166
|
op: 'napcat_gateway_receive_failed',
|
|
162
167
|
target: `${conversation.kind}:${conversation.id}`,
|
|
163
168
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -194,7 +199,7 @@ export class NapCatHttpEndpoint implements EndpointInstance {
|
|
|
194
199
|
response.writeHead(200, { 'Content-Type': 'application/json' });
|
|
195
200
|
response.end(JSON.stringify({ status: 'ok' }));
|
|
196
201
|
} catch (error) {
|
|
197
|
-
logger.error('NapCat HTTP webhook error:', error);
|
|
202
|
+
this.#logger.error('NapCat HTTP webhook error:', error);
|
|
198
203
|
if (!response.headersSent) {
|
|
199
204
|
response.writeHead(500, { 'Content-Type': 'application/json' });
|
|
200
205
|
response.end(JSON.stringify({ message: 'Internal Server Error' }));
|
package/src/napcat-agent-deps.ts
CHANGED
|
@@ -55,20 +55,20 @@ export interface NapcatAgentEndpoint {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export interface NapcatAgentDeps {
|
|
58
|
-
getEndpoint: (
|
|
58
|
+
getEndpoint: (endpointKey: string) => NapcatAgentEndpoint;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
const endpoints = new Map<string, NapcatAgentEndpoint>();
|
|
62
62
|
let override: NapcatAgentDeps | null = null;
|
|
63
63
|
|
|
64
64
|
export function registerNapcatAgentEndpoint(
|
|
65
|
-
|
|
65
|
+
endpointKey: string,
|
|
66
66
|
endpoint: NapcatAgentEndpoint,
|
|
67
67
|
): () => void {
|
|
68
|
-
endpoints.set(
|
|
68
|
+
endpoints.set(endpointKey, endpoint);
|
|
69
69
|
return () => {
|
|
70
|
-
if (endpoints.get(
|
|
71
|
-
endpoints.delete(
|
|
70
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
71
|
+
endpoints.delete(endpointKey);
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
}
|
|
@@ -78,9 +78,9 @@ export function setNapcatAgentDeps(deps: NapcatAgentDeps | null): void {
|
|
|
78
78
|
override = deps;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
function lookup(
|
|
82
|
-
const registered = endpoints.get(
|
|
83
|
-
if (!registered) throw new Error(`Endpoint ${
|
|
81
|
+
function lookup(endpointKey: string): NapcatAgentEndpoint {
|
|
82
|
+
const registered = endpoints.get(endpointKey);
|
|
83
|
+
if (!registered) throw new Error(`Endpoint ${endpointKey} not found`);
|
|
84
84
|
return registered;
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -90,6 +90,6 @@ export function getNapcatAgentDeps(): NapcatAgentDeps {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/** Convenience for agent/tools (unchanged call sites). */
|
|
93
|
-
export function getEndpoint(
|
|
94
|
-
return getNapcatAgentDeps().getEndpoint(
|
|
93
|
+
export function getEndpoint(endpointKey: string): NapcatAgentEndpoint {
|
|
94
|
+
return getNapcatAgentDeps().getEndpoint(endpointKey);
|
|
95
95
|
}
|
package/src/protocol.ts
CHANGED
|
@@ -13,7 +13,7 @@ const logger = getLogger('napcat');
|
|
|
13
13
|
export interface NapCatLegacyEndpointRow {
|
|
14
14
|
readonly context?: string;
|
|
15
15
|
readonly connection?: 'ws' | 'wss' | 'http';
|
|
16
|
-
readonly
|
|
16
|
+
readonly id?: string;
|
|
17
17
|
readonly access_token?: string;
|
|
18
18
|
readonly url?: string;
|
|
19
19
|
readonly path?: string;
|
|
@@ -27,7 +27,7 @@ export interface NapCatLegacyEndpointRow {
|
|
|
27
27
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
28
28
|
export interface NapCatAdapterConfig {
|
|
29
29
|
readonly connection?: 'ws' | 'wss' | 'http';
|
|
30
|
-
readonly
|
|
30
|
+
readonly id?: string;
|
|
31
31
|
readonly access_token?: string;
|
|
32
32
|
readonly url?: string;
|
|
33
33
|
readonly path?: string;
|
|
@@ -42,7 +42,7 @@ export interface NapCatAdapterConfig {
|
|
|
42
42
|
|
|
43
43
|
export interface NapCatConfigBase {
|
|
44
44
|
readonly context: 'napcat';
|
|
45
|
-
readonly
|
|
45
|
+
readonly id: string;
|
|
46
46
|
readonly access_token?: string;
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -143,8 +143,8 @@ function normalizeConnection(
|
|
|
143
143
|
export function resolveNapCatConfig(config: NapCatAdapterConfig = {}): ResolvedNapCatConfig {
|
|
144
144
|
const entry = config.endpoints?.find((item) => item.context === 'napcat');
|
|
145
145
|
const connection = normalizeConnection(config.connection ?? entry?.connection);
|
|
146
|
-
const
|
|
147
|
-
|| (typeof entry?.
|
|
146
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
147
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
148
148
|
|| process.env.NAPCAT_BOT_NAME
|
|
149
149
|
|| 'napcat-bot';
|
|
150
150
|
const access_token = config.access_token ?? entry?.access_token;
|
|
@@ -159,7 +159,7 @@ export function resolveNapCatConfig(config: NapCatAdapterConfig = {}): ResolvedN
|
|
|
159
159
|
return {
|
|
160
160
|
context: 'napcat',
|
|
161
161
|
connection: 'ws',
|
|
162
|
-
|
|
162
|
+
id,
|
|
163
163
|
access_token,
|
|
164
164
|
url,
|
|
165
165
|
reconnect_interval: config.reconnect_interval ?? entry?.reconnect_interval ?? 5000,
|
|
@@ -173,7 +173,7 @@ export function resolveNapCatConfig(config: NapCatAdapterConfig = {}): ResolvedN
|
|
|
173
173
|
return {
|
|
174
174
|
context: 'napcat',
|
|
175
175
|
connection: 'wss',
|
|
176
|
-
|
|
176
|
+
id,
|
|
177
177
|
access_token,
|
|
178
178
|
path,
|
|
179
179
|
heartbeat_interval: config.heartbeat_interval ?? entry?.heartbeat_interval ?? 30_000,
|
|
@@ -189,7 +189,7 @@ export function resolveNapCatConfig(config: NapCatAdapterConfig = {}): ResolvedN
|
|
|
189
189
|
return {
|
|
190
190
|
context: 'napcat',
|
|
191
191
|
connection: 'http',
|
|
192
|
-
|
|
192
|
+
id,
|
|
193
193
|
access_token,
|
|
194
194
|
http_url,
|
|
195
195
|
post_path,
|
|
@@ -218,8 +218,8 @@ export function getChannelId(ev: NapCatEvent): string {
|
|
|
218
218
|
* 入站归一化 → ConversationRef:群消息 → kind 'group';私聊临时会话
|
|
219
219
|
* (sub_type 'group')→ kind 'private' + 群容器进 `parent`;其余私聊 → 'private'。
|
|
220
220
|
*/
|
|
221
|
-
export function napcatInboundConversation(
|
|
222
|
-
const endpoint = { id:
|
|
221
|
+
export function napcatInboundConversation(endpointKey: string, ev: NapCatEvent): ConversationRef {
|
|
222
|
+
const endpoint = { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey };
|
|
223
223
|
const isGroup = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private');
|
|
224
224
|
if (isGroup && ev.group_id != null) {
|
|
225
225
|
return { endpoint, kind: 'group', id: String(ev.group_id) };
|
package/src/ws-endpoint.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type EndpointSendRequest,
|
|
12
12
|
} from '@zhin.js/adapter';
|
|
13
13
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
14
|
-
import { formatCompact,
|
|
14
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
15
15
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
16
16
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
17
17
|
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
@@ -45,8 +45,6 @@ import {
|
|
|
45
45
|
type NapCatWsSocket,
|
|
46
46
|
} from './ws-types.js';
|
|
47
47
|
|
|
48
|
-
const logger = getLogger('napcat');
|
|
49
|
-
|
|
50
48
|
export interface NapCatWsEndpointOptions {
|
|
51
49
|
readonly id: CapabilityId;
|
|
52
50
|
readonly gateway: MessageGateway;
|
|
@@ -58,6 +56,8 @@ export interface NapCatWsEndpointOptions {
|
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
export class NapCatWsEndpoint implements EndpointInstance {
|
|
59
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
60
|
+
|
|
61
61
|
readonly #options: NapCatWsEndpointOptions;
|
|
62
62
|
readonly #inboundDeduper = new InboundMessageDeduper();
|
|
63
63
|
readonly management: EndpointManagement = createNapCatEndpointManagement(this);
|
|
@@ -69,9 +69,10 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
69
69
|
#unregisterAgent?: () => void;
|
|
70
70
|
|
|
71
71
|
constructor(options: NapCatWsEndpointOptions) {
|
|
72
|
+
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
72
73
|
this.#options = options;
|
|
73
74
|
this.#lifecycle = createEndpointLifecycle({
|
|
74
|
-
name: options.config.
|
|
75
|
+
name: options.config.id,
|
|
75
76
|
// reconnect_interval 旧语义为固定间隔:multiplier 1 + 无 jitter + 不封顶
|
|
76
77
|
reconnect: {
|
|
77
78
|
initialIntervalMs: options.config.reconnect_interval,
|
|
@@ -84,7 +85,7 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
84
85
|
|
|
85
86
|
async start(): Promise<void> {
|
|
86
87
|
if (this.#lifecycle.started) return;
|
|
87
|
-
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.
|
|
88
|
+
this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.id, this);
|
|
88
89
|
try {
|
|
89
90
|
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
90
91
|
} catch (err) {
|
|
@@ -125,9 +126,9 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
125
126
|
const { action, params } = buildSendAction(napcatOutboundTarget(conversation), message);
|
|
126
127
|
const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
|
|
127
128
|
const messageId = data?.message_id != null ? String(data.message_id) : '';
|
|
128
|
-
logger.debug(formatCompact({
|
|
129
|
+
this.#logger.debug(formatCompact({
|
|
129
130
|
op: 'napcat_send',
|
|
130
|
-
endpoint: this.#options.config.
|
|
131
|
+
endpoint: this.#options.config.id,
|
|
131
132
|
target: `${conversation.kind}:${conversation.id}`,
|
|
132
133
|
messageId,
|
|
133
134
|
}));
|
|
@@ -336,20 +337,24 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
336
337
|
conversation,
|
|
337
338
|
message: { conversation, id: msgId },
|
|
338
339
|
content,
|
|
339
|
-
sender:
|
|
340
|
+
sender: {
|
|
341
|
+
id: senderUserId(ev),
|
|
342
|
+
name: nickname,
|
|
343
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
344
|
+
},
|
|
345
|
+
endpointId: this.#options.config.id,
|
|
346
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
340
347
|
metadata: Object.freeze({
|
|
341
348
|
message_type: ev.message_type,
|
|
342
349
|
user_id: ev.user_id != null ? String(ev.user_id) : undefined,
|
|
343
350
|
group_id: ev.group_id != null ? String(ev.group_id) : undefined,
|
|
344
|
-
endpoint: this.#options.config.name,
|
|
345
351
|
time: ev.time,
|
|
346
352
|
self_id: ev.self_id != null ? String(ev.self_id) : undefined,
|
|
347
353
|
role: ev.sender?.role,
|
|
348
354
|
...(nickname ? { nickname } : {}),
|
|
349
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
350
355
|
}),
|
|
351
356
|
}).catch((err) => {
|
|
352
|
-
logger.warn(formatCompact({
|
|
357
|
+
this.#logger.warn(formatCompact({
|
|
353
358
|
op: 'napcat_gateway_receive_failed',
|
|
354
359
|
target: `${conversation.kind}:${conversation.id}`,
|
|
355
360
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -379,14 +384,14 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
379
384
|
if (settled) return;
|
|
380
385
|
settled = true;
|
|
381
386
|
if (!this.#options.config.access_token) {
|
|
382
|
-
logger.warn(formatCompact({
|
|
383
|
-
endpoint: this.#options.config.
|
|
387
|
+
this.#logger.warn(formatCompact({
|
|
388
|
+
endpoint: this.#options.config.id,
|
|
384
389
|
ok: false,
|
|
385
390
|
error: 'missing access_token',
|
|
386
391
|
}));
|
|
387
392
|
}
|
|
388
|
-
logger.debug(formatCompact({
|
|
389
|
-
endpoint: this.#options.config.
|
|
393
|
+
this.#logger.debug(formatCompact({
|
|
394
|
+
endpoint: this.#options.config.id,
|
|
390
395
|
mode: 'ws',
|
|
391
396
|
url: safeUrl,
|
|
392
397
|
}));
|
|
@@ -405,7 +410,7 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
405
410
|
|
|
406
411
|
ws.on('message', (data) => {
|
|
407
412
|
handleNapCatWsMessage(data, {
|
|
408
|
-
|
|
413
|
+
endpointId: this.#options.config.id,
|
|
409
414
|
pending: this.#pending,
|
|
410
415
|
admit: (event) => this.admit(event),
|
|
411
416
|
});
|
|
@@ -423,9 +428,8 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
423
428
|
: codeNum === 1006
|
|
424
429
|
? ' [abnormal]'
|
|
425
430
|
: '';
|
|
426
|
-
logger.warn(formatCompact({
|
|
431
|
+
this.#logger.warn(formatCompact({
|
|
427
432
|
op: 'disconnect',
|
|
428
|
-
endpoint: this.#options.config.name,
|
|
429
433
|
code: codeNum,
|
|
430
434
|
error: `${reasonStr || 'closed'}${codeHint}`,
|
|
431
435
|
reconnect_ms: this.#options.config.reconnect_interval,
|
|
@@ -440,9 +444,9 @@ export class NapCatWsEndpoint implements EndpointInstance {
|
|
|
440
444
|
|
|
441
445
|
ws.on('error', (err) => {
|
|
442
446
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
443
|
-
logger.warn(formatCompact({
|
|
447
|
+
this.#logger.warn(formatCompact({
|
|
444
448
|
op: 'ws_error',
|
|
445
|
-
endpoint: this.#options.config.
|
|
449
|
+
endpoint: this.#options.config.id,
|
|
446
450
|
ok: false,
|
|
447
451
|
error: error.message,
|
|
448
452
|
}));
|
package/src/ws-transport.ts
CHANGED
|
@@ -23,7 +23,7 @@ export function decodeWsPayload(data: unknown): string {
|
|
|
23
23
|
export function handleNapCatWsMessage(
|
|
24
24
|
data: unknown,
|
|
25
25
|
options: {
|
|
26
|
-
readonly
|
|
26
|
+
readonly endpointId: string;
|
|
27
27
|
readonly pending: Map<string, NapCatPendingAction>;
|
|
28
28
|
readonly admit: (ev: NapCatEvent) => void;
|
|
29
29
|
},
|
|
@@ -50,7 +50,7 @@ export function handleNapCatWsMessage(
|
|
|
50
50
|
} catch (error) {
|
|
51
51
|
logger.warn(formatCompact({
|
|
52
52
|
op: 'napcat_parse_failed',
|
|
53
|
-
endpoint: options.
|
|
53
|
+
endpoint: options.endpointId,
|
|
54
54
|
error: error instanceof Error ? error.message : String(error),
|
|
55
55
|
}));
|
|
56
56
|
}
|
package/src/wss-endpoint.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { clearInterval } from 'node:timers';
|
|
|
5
5
|
import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
|
|
6
6
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
7
7
|
import type { HttpHost, WsConnection } from '@zhin.js/host-http';
|
|
8
|
-
import { formatCompact,
|
|
8
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
9
9
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
10
10
|
import { createNapCatEndpointManagement } from './endpoint-management.js';
|
|
11
11
|
import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
|
|
@@ -40,8 +40,6 @@ import {
|
|
|
40
40
|
} from './ws-types.js';
|
|
41
41
|
import { verifyNapCatAccessToken } from './wss-auth.js';
|
|
42
42
|
|
|
43
|
-
const logger = getLogger('napcat');
|
|
44
|
-
|
|
45
43
|
export interface NapCatWssEndpointOptions {
|
|
46
44
|
readonly id: CapabilityId;
|
|
47
45
|
readonly gateway: MessageGateway;
|
|
@@ -50,6 +48,8 @@ export interface NapCatWssEndpointOptions {
|
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
export class NapCatWssEndpoint implements EndpointInstance {
|
|
51
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
52
|
+
|
|
53
53
|
readonly #options: NapCatWssEndpointOptions;
|
|
54
54
|
readonly #inboundDeduper = new InboundMessageDeduper();
|
|
55
55
|
readonly management: EndpointManagement = createNapCatEndpointManagement(this);
|
|
@@ -63,6 +63,7 @@ export class NapCatWssEndpoint implements EndpointInstance {
|
|
|
63
63
|
#unregisterAgent?: () => void;
|
|
64
64
|
|
|
65
65
|
constructor(options: NapCatWssEndpointOptions) {
|
|
66
|
+
this.#logger = getAdapterLogger('napcat', options.config.id);
|
|
66
67
|
this.#options = options;
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -70,16 +71,16 @@ export class NapCatWssEndpoint implements EndpointInstance {
|
|
|
70
71
|
if (this.#started) return;
|
|
71
72
|
this.#started = true;
|
|
72
73
|
this.#unregisterAgent = registerNapcatAgentEndpoint(
|
|
73
|
-
this.#options.config.
|
|
74
|
+
this.#options.config.id,
|
|
74
75
|
this as unknown as NapCatWsEndpoint,
|
|
75
76
|
);
|
|
76
77
|
const handle = this.#options.http.ws(this.#options.config.path);
|
|
77
78
|
this.#wsRelease = handle.onConnection((connection) => {
|
|
78
79
|
this.#acceptConnection(connection);
|
|
79
80
|
});
|
|
80
|
-
logger.info(formatCompact({
|
|
81
|
+
this.#logger.info(formatCompact({
|
|
81
82
|
op: 'listen',
|
|
82
|
-
endpoint: this.#options.config.
|
|
83
|
+
endpoint: this.#options.config.id,
|
|
83
84
|
mode: 'wss',
|
|
84
85
|
path: this.#options.config.path,
|
|
85
86
|
}));
|
|
@@ -147,20 +148,24 @@ export class NapCatWssEndpoint implements EndpointInstance {
|
|
|
147
148
|
conversation,
|
|
148
149
|
message: { conversation, id: msgId },
|
|
149
150
|
content: formatInboundContent(ev),
|
|
150
|
-
sender:
|
|
151
|
+
sender: {
|
|
152
|
+
id: senderUserId(ev),
|
|
153
|
+
name: nickname,
|
|
154
|
+
...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
|
|
155
|
+
},
|
|
156
|
+
endpointId: this.#options.config.id,
|
|
157
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
151
158
|
metadata: Object.freeze({
|
|
152
159
|
message_type: ev.message_type,
|
|
153
160
|
user_id: ev.user_id != null ? String(ev.user_id) : undefined,
|
|
154
161
|
group_id: ev.group_id != null ? String(ev.group_id) : undefined,
|
|
155
|
-
endpoint: this.#options.config.name,
|
|
156
162
|
time: ev.time,
|
|
157
163
|
self_id: ev.self_id != null ? String(ev.self_id) : undefined,
|
|
158
164
|
role: ev.sender?.role,
|
|
159
165
|
...(nickname ? { nickname } : {}),
|
|
160
|
-
...(mentioned ? { mentioned: true } : {}),
|
|
161
166
|
}),
|
|
162
167
|
}).catch((err) => {
|
|
163
|
-
logger.warn(formatCompact({
|
|
168
|
+
this.#logger.warn(formatCompact({
|
|
164
169
|
op: 'napcat_gateway_receive_failed',
|
|
165
170
|
target: `${conversation.kind}:${conversation.id}`,
|
|
166
171
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -189,7 +194,7 @@ export class NapCatWssEndpoint implements EndpointInstance {
|
|
|
189
194
|
);
|
|
190
195
|
socket.on('message', (data) => {
|
|
191
196
|
handleNapCatWsMessage(data, {
|
|
192
|
-
|
|
197
|
+
endpointId: this.#options.config.id,
|
|
193
198
|
pending: this.#pending,
|
|
194
199
|
admit: (event) => this.admit(event),
|
|
195
200
|
});
|
|
@@ -203,8 +208,8 @@ export class NapCatWssEndpoint implements EndpointInstance {
|
|
|
203
208
|
}
|
|
204
209
|
}
|
|
205
210
|
});
|
|
206
|
-
logger.debug(formatCompact({
|
|
207
|
-
endpoint: this.#options.config.
|
|
211
|
+
this.#logger.debug(formatCompact({
|
|
212
|
+
endpoint: this.#options.config.id,
|
|
208
213
|
mode: 'wss',
|
|
209
214
|
peer: connection.request.socket.remoteAddress,
|
|
210
215
|
}));
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|