@zhin.js/adapter-kook 1.1.20 → 1.1.22
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 +65 -0
- package/adapters/kook/index.js +17 -5
- package/adapters/kook/index.ts +17 -5
- package/lib/endpoint.js +3 -0
- package/lib/protocol.d.ts +2 -2
- package/lib/self-profile.d.ts +9 -0
- package/lib/self-profile.js +14 -0
- package/lib/side-event-dispatch.js +4 -3
- package/lib/side-event-map.d.ts +5 -0
- package/lib/side-event-map.js +15 -0
- package/package.json +20 -20
- package/plugin.js +1 -0
- package/schema.json +106 -1
- package/src/endpoint.ts +3 -0
- package/src/protocol.ts +2 -1
- package/src/self-profile.ts +20 -0
- package/src/side-event-dispatch.ts +4 -3
- package/src/side-event-map.ts +18 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# @zhin.js/adapter-kook
|
|
2
2
|
|
|
3
|
+
## 1.1.22
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b249e5e: ADR 0044 C4:事件映射迁出 core。新增 `@zhin.js/adapter-onebot-events`,承载 OneBot v11 / NapCat / icqq 的原始通知与请求 → 标准事件映射(`receiveOneBotLikeSideEvent`、`mapNoticeParts`、`mapRequestParts`、`resolveSideEventDedupeKey` 及 OneBot 映射表,icqq 差异用覆盖表表达);KOOK、Slack 的映射迁入各自适配器;`@zhin.js/core` 只保留标准事件名、类型与 `buildNotice` / `buildRequest` / `buildSystem` / `senderFromId`,不再含任何平台名。core 不再导出上述映射函数与 `ONEBOT_/KOOK_/SLACK_NOTICE_PARTS_MAP`、`SideEventPlatform`、`OneBotLike*` 类型,适配器改从共享包导入。
|
|
8
|
+
- 41ff1a5: ADR 0044 C5: every official adapter now declares a capability `profile` (its `segments` moved into `profile.default.messaging.segments`). icqq declares the complete profile (per conversation kind: scene, all 14 actions with real limits, events, feedback, delivery) and implements the seven new management ports (`pokeUser`, `unmuteGroupMember`, `muteAllGroupMembers`, `setGroupCard`, `setGroupTitle`, `setGroupEssence`, `inviteGroupMember`) with fresh bot-role reads. qq official declares its passive reply windows; undeclared capabilities stay unsupported.
|
|
9
|
+
- cbd3f14: ADR 0044 integration and C6 guard. `delivery.spool` now reproduces the pre-0044 media rule (icqq `false`, every other official adapter `true`). icqq narrows `actions.recall.others` unless the Bot is admin or owner, and declares recall for groups. Endpoint kind capabilities merge the Endpoint's `operations` (Discord reactions keep working; Discord declares reaction feedback). Adapters in the `@zhin.js/` scope are trusted: their custom prompt text is not labelled `external_content`. Core no longer keeps a telegram/discord interactive-policy table (adapters declare `segments.interactive`). New `pnpm check:no-platform-branches` blocks platform-name branches in runtime code.
|
|
10
|
+
- 4fe49b5: 支持配置按需生效:分离保存与有效版本,独立变更先应用,账号资料更新保留连接,模型按回合使用确定版本;Console 返回结构化应用结果。监听改为仅显式 --watch 启用,开发模板显式选择源码和配置监听。
|
|
11
|
+
|
|
12
|
+
自变更消费配置应用回执,避免已处理配置被二次重载;持久化本次写入修订和应用结果,未知结果或修订冲突时停止自动续作并保留现场,恢复不会覆盖未经本次变更确认的配置。
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [b249e5e]
|
|
15
|
+
- Updated dependencies [57661f6]
|
|
16
|
+
- Updated dependencies [cbd3f14]
|
|
17
|
+
- Updated dependencies [299863a]
|
|
18
|
+
- Updated dependencies [aaa93d7]
|
|
19
|
+
- Updated dependencies [bd524d1]
|
|
20
|
+
- Updated dependencies [126ae99]
|
|
21
|
+
- Updated dependencies [4fe49b5]
|
|
22
|
+
- Updated dependencies [cce07db]
|
|
23
|
+
- Updated dependencies [b652db3]
|
|
24
|
+
- Updated dependencies [0315ba0]
|
|
25
|
+
- Updated dependencies [00be764]
|
|
26
|
+
- @zhin.js/core@1.1.56
|
|
27
|
+
- @zhin.js/adapter@1.1.28
|
|
28
|
+
- @zhin.js/im-contract@1.1.11
|
|
29
|
+
- @zhin.js/tool@1.1.15
|
|
30
|
+
- @zhin.js/skill@1.1.13
|
|
31
|
+
- @zhin.js/host-http@1.1.14
|
|
32
|
+
- @zhin.js/feature-kit@1.1.12
|
|
33
|
+
- @zhin.js/client@1.1.24
|
|
34
|
+
- @zhin.js/page@1.1.14
|
|
35
|
+
- @zhin.js/agent-feature@1.1.13
|
|
36
|
+
- @zhin.js/permission@1.1.12
|
|
37
|
+
|
|
38
|
+
## 1.1.21
|
|
39
|
+
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- af8f803: Use the current Endpoint's platform profile for Agent account identity, with per-field configured fallbacks and scoped, identity-approved profile tools. Keep SOUL first-person and independent of account names. Profile ports preserve the source Client, cancellation, truthful update outcomes and private image authority.
|
|
43
|
+
|
|
44
|
+
Adapter Feature API 2.1 and Tool Feature API 1.1 describe the additive profile requirements; new Core, official adapters and generated plugins declare the corresponding floors. Existing compatible API-2.0/API-1.0 plugins remain accepted by the newer providers. npm releases remain patch.
|
|
45
|
+
|
|
46
|
+
Private IM assets now bind to the full canonical conversation and principal. Existing IM asset records that contain only the earlier lossy hash remain on disk until their original expiry, but cannot be safely rebound; recapture them. No automatic file deletion, platform profile mutation or workspace SOUL rewrite occurs during upgrade.
|
|
47
|
+
|
|
48
|
+
- Updated dependencies [b88e988]
|
|
49
|
+
- Updated dependencies [f78eb84]
|
|
50
|
+
- Updated dependencies [c15cef9]
|
|
51
|
+
- Updated dependencies [b0c02a2]
|
|
52
|
+
- Updated dependencies [af8f803]
|
|
53
|
+
- Updated dependencies [26fda97]
|
|
54
|
+
- Updated dependencies [976886c]
|
|
55
|
+
- Updated dependencies [032dc96]
|
|
56
|
+
- @zhin.js/adapter@1.1.27
|
|
57
|
+
- @zhin.js/client@1.1.23
|
|
58
|
+
- @zhin.js/im-contract@1.1.10
|
|
59
|
+
- @zhin.js/core@1.1.55
|
|
60
|
+
- @zhin.js/tool@1.1.14
|
|
61
|
+
- @zhin.js/page@1.1.13
|
|
62
|
+
- @zhin.js/host-http@1.1.13
|
|
63
|
+
- @zhin.js/agent-feature@1.1.12
|
|
64
|
+
- @zhin.js/feature-kit@1.1.11
|
|
65
|
+
- @zhin.js/permission@1.1.11
|
|
66
|
+
- @zhin.js/skill@1.1.12
|
|
67
|
+
|
|
3
68
|
## 1.1.20
|
|
4
69
|
|
|
5
70
|
### Patch Changes
|
package/adapters/kook/index.js
CHANGED
|
@@ -9,13 +9,25 @@ import {} from "../../lib/protocol.js";
|
|
|
9
9
|
export { KookWebhookEndpoint, KookWebsocketEndpoint, } from "../../lib/endpoint.js";
|
|
10
10
|
export default defineAdapter({
|
|
11
11
|
capabilities: ['inbound', 'outbound'],
|
|
12
|
-
operations: ['recall'],
|
|
13
12
|
// KOOK 图片上传后以原生卡片保留图文混排;KMarkdown 原生消费;
|
|
14
13
|
// 原生卡片按钮经 return-val 事件进入 canonical action 链路。
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
profile: {
|
|
15
|
+
default: {
|
|
16
|
+
messaging: {
|
|
17
|
+
segments: {
|
|
18
|
+
outboundMedia: ['url', 'upload'],
|
|
19
|
+
interactive: 'native',
|
|
20
|
+
markdown: 'native',
|
|
21
|
+
},
|
|
22
|
+
quote: true,
|
|
23
|
+
recall: {},
|
|
24
|
+
},
|
|
25
|
+
actions: {
|
|
26
|
+
recall: { scopes: ['private', 'group', 'channel'] },
|
|
27
|
+
quoteReply: { scopes: ['private', 'group', 'channel'] },
|
|
28
|
+
},
|
|
29
|
+
delivery: { send: true, proactive: true, spool: true },
|
|
30
|
+
},
|
|
19
31
|
},
|
|
20
32
|
createAdapter: context => new KookAdapter(context),
|
|
21
33
|
});
|
package/adapters/kook/index.ts
CHANGED
|
@@ -20,13 +20,25 @@ export type { KookClientTransport } from '../../src/ws.js';
|
|
|
20
20
|
|
|
21
21
|
export default defineAdapter<KookEndpointConfig>({
|
|
22
22
|
capabilities: ['inbound', 'outbound'],
|
|
23
|
-
operations: ['recall'],
|
|
24
23
|
// KOOK 图片上传后以原生卡片保留图文混排;KMarkdown 原生消费;
|
|
25
24
|
// 原生卡片按钮经 return-val 事件进入 canonical action 链路。
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
profile: {
|
|
26
|
+
default: {
|
|
27
|
+
messaging: {
|
|
28
|
+
segments: {
|
|
29
|
+
outboundMedia: ['url', 'upload'],
|
|
30
|
+
interactive: 'native',
|
|
31
|
+
markdown: 'native',
|
|
32
|
+
},
|
|
33
|
+
quote: true,
|
|
34
|
+
recall: {},
|
|
35
|
+
},
|
|
36
|
+
actions: {
|
|
37
|
+
recall: { scopes: ['private', 'group', 'channel'] },
|
|
38
|
+
quoteReply: { scopes: ['private', 'group', 'channel'] },
|
|
39
|
+
},
|
|
40
|
+
delivery: { send: true, proactive: true, spool: true },
|
|
41
|
+
},
|
|
30
42
|
},
|
|
31
43
|
createAdapter: context => new KookAdapter(context),
|
|
32
44
|
});
|
package/lib/endpoint.js
CHANGED
|
@@ -10,6 +10,7 @@ import { RuntimeKookClient, kookWebsocketClientOptions, kookWebhookClientOptions
|
|
|
10
10
|
import { recallKookMessage, sendKookOutbound } from './outbound.js';
|
|
11
11
|
import { KookSenderRoleResolver } from './sender-roles.js';
|
|
12
12
|
import { receiveKookSideEvent } from './side-event-dispatch.js';
|
|
13
|
+
import { createKookSelfProfile } from './self-profile.js';
|
|
13
14
|
/** 入站 message.receive 载荷:规范角色 owner/admin 进 roles,原始角色 id 进 permissions。 */
|
|
14
15
|
function kookInboundPayload(endpointId, conversation, msg, projection, selfId) {
|
|
15
16
|
return {
|
|
@@ -58,6 +59,7 @@ export class KookWebsocketEndpoint extends RuntimeKookClient {
|
|
|
58
59
|
stop: () => this.#stopFramework(), send: request => this.#sendFramework(request),
|
|
59
60
|
name: options.config.id, get transportState() { return endpoint.#transportState; },
|
|
60
61
|
management: this.#management, control: this.#control,
|
|
62
|
+
profile: createKookSelfProfile({ client: this, reportAccount: id => this[endpointSpec].reportSelfUserId(id) }),
|
|
61
63
|
});
|
|
62
64
|
}
|
|
63
65
|
get #transportState() {
|
|
@@ -206,6 +208,7 @@ export class KookWebhookEndpoint extends RuntimeKookClient {
|
|
|
206
208
|
start: signal => this.#startFramework(signal), open: () => this.#openFramework(), close: () => this.#closeFramework(),
|
|
207
209
|
stop: () => this.#stopFramework(), send: request => this.#sendFramework(request), name: options.config.id,
|
|
208
210
|
management: this.#management, control: this.#control,
|
|
211
|
+
profile: createKookSelfProfile({ client: this, reportAccount: id => this[endpointSpec].reportSelfUserId(id) }),
|
|
209
212
|
});
|
|
210
213
|
}
|
|
211
214
|
/** Used by webhook handler. */
|
package/lib/protocol.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import type { EndpointProfileConfiguration } from 'zhin.js/adapter';
|
|
2
2
|
import type { IncomingMessage } from 'node:http';
|
|
3
3
|
import { type ConversationRef } from '@zhin.js/im-contract';
|
|
4
4
|
import type { Locale } from 'zhin.js/i18n';
|
|
@@ -10,7 +10,7 @@ export declare enum KookPermission {
|
|
|
10
10
|
ChannelAdmin = 5
|
|
11
11
|
}
|
|
12
12
|
/** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
|
|
13
|
-
export interface KookEndpointConfig {
|
|
13
|
+
export interface KookEndpointConfig extends EndpointProfileConfiguration {
|
|
14
14
|
readonly apiProxy?: import('./api-proxy.js').KookApiProxy;
|
|
15
15
|
readonly streamProxy?: import('./stream-proxy.js').KookStreamProxy;
|
|
16
16
|
readonly id: string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type EndpointProfile } from 'zhin.js/adapter';
|
|
2
|
+
import type { RuntimeKookClient } from './ws.js';
|
|
3
|
+
interface KookSelfProfileOptions {
|
|
4
|
+
readonly client: Pick<RuntimeKookClient, 'getSelfInfo'>;
|
|
5
|
+
readonly reportAccount: (id: string) => void;
|
|
6
|
+
}
|
|
7
|
+
/** Bot account profile facts from the SDK's existing /user/me method. */
|
|
8
|
+
export declare function createKookSelfProfile({ client, reportAccount }: KookSelfProfileOptions): EndpointProfile;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createEndpointOperation } from 'zhin.js/adapter';
|
|
2
|
+
/** Bot account profile facts from the SDK's existing /user/me method. */
|
|
3
|
+
export function createKookSelfProfile({ client, reportAccount }) {
|
|
4
|
+
return Object.freeze({
|
|
5
|
+
writableFields: Object.freeze([]),
|
|
6
|
+
async read({ signal }) {
|
|
7
|
+
const self = await createEndpointOperation({ signal }).prepare(() => client.getSelfInfo());
|
|
8
|
+
if (!self?.id || typeof self.username !== 'string')
|
|
9
|
+
throw new Error('KOOK returned an incomplete self profile');
|
|
10
|
+
reportAccount(self.id);
|
|
11
|
+
return { nickname: self.username, ...(typeof self.avatar === 'string' ? { avatar: self.avatar } : {}) };
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { composeSideEventName, buildNotice,
|
|
1
|
+
import { composeSideEventName, buildNotice, senderFromId } from '@zhin.js/core';
|
|
2
2
|
import { formatCompact } from '@zhin.js/logger';
|
|
3
|
+
import { mapKookNoticeParts } from './side-event-map.js';
|
|
3
4
|
function extractKookNoticeType(raw) {
|
|
4
5
|
if (!raw || typeof raw !== 'object')
|
|
5
6
|
return null;
|
|
@@ -16,10 +17,10 @@ export function receiveKookSideEvent(emit, configId, raw, logger) {
|
|
|
16
17
|
const noticeType = extractKookNoticeType(raw);
|
|
17
18
|
if (!noticeType)
|
|
18
19
|
return false;
|
|
19
|
-
|
|
20
|
+
const parts = mapKookNoticeParts(noticeType);
|
|
21
|
+
if (!parts)
|
|
20
22
|
return false;
|
|
21
23
|
const event = raw;
|
|
22
|
-
const parts = mapNoticeParts('kook', noticeType);
|
|
23
24
|
const body = event.extra?.body;
|
|
24
25
|
const guildId = event.extra?.guild_id
|
|
25
26
|
?? (event.channel_type === 'GROUP' && event.type === 255 ? event.target_id : undefined);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SideEventParts } from '@zhin.js/core';
|
|
2
|
+
/** KOOK extra.type 原始值 → 标准 scene_type + sub_type */
|
|
3
|
+
export declare const KOOK_NOTICE_PARTS_MAP: Readonly<Record<string, SideEventParts>>;
|
|
4
|
+
/** 已登记的 KOOK 通知映射为标准 scene_type + sub_type;未登记返回 undefined。 */
|
|
5
|
+
export declare function mapKookNoticeParts(raw: string): SideEventParts | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** KOOK extra.type 原始值 → 标准 scene_type + sub_type */
|
|
2
|
+
export const KOOK_NOTICE_PARTS_MAP = {
|
|
3
|
+
joined_guild: { scene_type: 'group', sub_type: 'member_increase' },
|
|
4
|
+
exited_guild: { scene_type: 'group', sub_type: 'member_decrease' },
|
|
5
|
+
deleted_message: { scene_type: 'group', sub_type: 'recall' },
|
|
6
|
+
deleted_private_message: { scene_type: 'friend', sub_type: 'recall' },
|
|
7
|
+
added_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
8
|
+
deleted_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
9
|
+
private_added_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
10
|
+
private_deleted_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
11
|
+
};
|
|
12
|
+
/** 已登记的 KOOK 通知映射为标准 scene_type + sub_type;未登记返回 undefined。 */
|
|
13
|
+
export function mapKookNoticeParts(raw) {
|
|
14
|
+
return Object.prototype.hasOwnProperty.call(KOOK_NOTICE_PARTS_MAP, raw) ? KOOK_NOTICE_PARTS_MAP[raw] : undefined;
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-kook",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.22",
|
|
4
4
|
"description": "Zhin.js KOOK adapter for Plugin Runtime (WebSocket gateway or Webhook)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -33,26 +33,26 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"kook-client": "^1.0.5",
|
|
36
|
-
"@zhin.js/adapter": "1.1.
|
|
37
|
-
"@zhin.js/agent-feature": "1.1.
|
|
38
|
-
"@zhin.js/client": "1.1.
|
|
36
|
+
"@zhin.js/adapter": "1.1.28",
|
|
37
|
+
"@zhin.js/agent-feature": "1.1.13",
|
|
38
|
+
"@zhin.js/client": "1.1.24",
|
|
39
39
|
"@zhin.js/console-contract": "1.1.3",
|
|
40
|
-
"@zhin.js/core": "1.1.
|
|
41
|
-
"@zhin.js/feature-kit": "1.1.
|
|
42
|
-
"@zhin.js/host-http": "1.1.
|
|
43
|
-
"@zhin.js/im-contract": "1.1.
|
|
40
|
+
"@zhin.js/core": "1.1.56",
|
|
41
|
+
"@zhin.js/feature-kit": "1.1.12",
|
|
42
|
+
"@zhin.js/host-http": "1.1.14",
|
|
43
|
+
"@zhin.js/im-contract": "1.1.11",
|
|
44
44
|
"@zhin.js/logger": "1.1.2",
|
|
45
|
-
"@zhin.js/page": "1.1.
|
|
46
|
-
"@zhin.js/permission": "1.1.
|
|
47
|
-
"@zhin.js/skill": "1.1.
|
|
48
|
-
"@zhin.js/tool": "1.1.
|
|
45
|
+
"@zhin.js/page": "1.1.14",
|
|
46
|
+
"@zhin.js/permission": "1.1.12",
|
|
47
|
+
"@zhin.js/skill": "1.1.13",
|
|
48
|
+
"@zhin.js/tool": "1.1.15"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"zod": "^4.0.0",
|
|
52
|
-
"@zhin.js/adapter": "^1.1.
|
|
53
|
-
"@zhin.js/command": "^1.1.
|
|
54
|
-
"@zhin.js/core": "^1.1.
|
|
55
|
-
"zhin.js": "^1.1.
|
|
52
|
+
"@zhin.js/adapter": "^1.1.28",
|
|
53
|
+
"@zhin.js/command": "^1.1.14",
|
|
54
|
+
"@zhin.js/core": "^1.1.56",
|
|
55
|
+
"zhin.js": "^1.1.21"
|
|
56
56
|
},
|
|
57
57
|
"peerDependenciesMeta": {
|
|
58
58
|
"@zhin.js/command": {
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"typescript": "^6.0.3",
|
|
71
71
|
"vitest": "^4.1.10",
|
|
72
72
|
"zod": "^4.4.3",
|
|
73
|
-
"@zhin.js/host-http": "1.1.
|
|
74
|
-
"zhin.js": "1.1.
|
|
73
|
+
"@zhin.js/host-http": "1.1.14",
|
|
74
|
+
"zhin.js": "1.1.21"
|
|
75
75
|
},
|
|
76
76
|
"files": [
|
|
77
77
|
"adapters",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"features": [
|
|
104
104
|
{
|
|
105
105
|
"package": "@zhin.js/adapter",
|
|
106
|
-
"api": "^2.
|
|
106
|
+
"api": "^2.1.0"
|
|
107
107
|
},
|
|
108
108
|
{
|
|
109
109
|
"package": "@zhin.js/command",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
"package": "@zhin.js/tool",
|
|
114
|
-
"api": "^1.
|
|
114
|
+
"api": "^1.1.0"
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
117
|
"package": "@zhin.js/skill",
|
package/plugin.js
CHANGED
|
@@ -5,6 +5,7 @@ import { checkKookPlatformPermit } from "./lib/platform-permit.js";
|
|
|
5
5
|
import { createKookConsoleRpc } from "./lib/console.js";
|
|
6
6
|
export default definePlugin({
|
|
7
7
|
name: 'kook',
|
|
8
|
+
configUpdate: { featurePaths: [['nickname'], ['profile'], ['endpoints']] },
|
|
8
9
|
metadata: {
|
|
9
10
|
displayName: 'KOOK WebSocket Adapter',
|
|
10
11
|
},
|
package/schema.json
CHANGED
|
@@ -212,6 +212,27 @@
|
|
|
212
212
|
}
|
|
213
213
|
},
|
|
214
214
|
"description": "Optional fixed loopback TCP route for www.kookapp.cn JSON API only; verified TLS remains enabled."
|
|
215
|
+
},
|
|
216
|
+
"nickname": {
|
|
217
|
+
"type": [
|
|
218
|
+
"string",
|
|
219
|
+
"null"
|
|
220
|
+
],
|
|
221
|
+
"description": "账号昵称兜底",
|
|
222
|
+
"x-i18n": {
|
|
223
|
+
"en": {
|
|
224
|
+
"description": "Fallback account nickname"
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
"profile": {
|
|
229
|
+
"$ref": "#/$defs/selfProfileFallback",
|
|
230
|
+
"description": "账号资料兜底",
|
|
231
|
+
"x-i18n": {
|
|
232
|
+
"en": {
|
|
233
|
+
"description": "Fallback account profile"
|
|
234
|
+
}
|
|
235
|
+
}
|
|
215
236
|
}
|
|
216
237
|
},
|
|
217
238
|
"required": [
|
|
@@ -234,9 +255,93 @@
|
|
|
234
255
|
"description": "Command prefix. The default empty string allows unprefixed commands; '/' requires a leading slash. Each endpoints[i] can override it."
|
|
235
256
|
}
|
|
236
257
|
}
|
|
258
|
+
},
|
|
259
|
+
"nickname": {
|
|
260
|
+
"type": [
|
|
261
|
+
"string",
|
|
262
|
+
"null"
|
|
263
|
+
],
|
|
264
|
+
"description": "账号昵称兜底",
|
|
265
|
+
"x-i18n": {
|
|
266
|
+
"en": {
|
|
267
|
+
"description": "Fallback account nickname"
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"profile": {
|
|
272
|
+
"$ref": "#/$defs/selfProfileFallback",
|
|
273
|
+
"description": "账号资料兜底",
|
|
274
|
+
"x-i18n": {
|
|
275
|
+
"en": {
|
|
276
|
+
"description": "Fallback account profile"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
237
279
|
}
|
|
238
280
|
},
|
|
239
281
|
"required": [
|
|
240
282
|
"endpoints"
|
|
241
|
-
]
|
|
283
|
+
],
|
|
284
|
+
"$defs": {
|
|
285
|
+
"selfProfileFallback": {
|
|
286
|
+
"type": "object",
|
|
287
|
+
"additionalProperties": false,
|
|
288
|
+
"properties": {
|
|
289
|
+
"gender": {
|
|
290
|
+
"type": [
|
|
291
|
+
"string",
|
|
292
|
+
"null"
|
|
293
|
+
],
|
|
294
|
+
"enum": [
|
|
295
|
+
"male",
|
|
296
|
+
"female",
|
|
297
|
+
"other",
|
|
298
|
+
"unknown",
|
|
299
|
+
null
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
"age": {
|
|
303
|
+
"type": [
|
|
304
|
+
"integer",
|
|
305
|
+
"null"
|
|
306
|
+
],
|
|
307
|
+
"minimum": 0
|
|
308
|
+
},
|
|
309
|
+
"birthday": {
|
|
310
|
+
"type": [
|
|
311
|
+
"string",
|
|
312
|
+
"null"
|
|
313
|
+
],
|
|
314
|
+
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
|
|
315
|
+
},
|
|
316
|
+
"signature": {
|
|
317
|
+
"type": [
|
|
318
|
+
"string",
|
|
319
|
+
"null"
|
|
320
|
+
]
|
|
321
|
+
},
|
|
322
|
+
"avatar": {
|
|
323
|
+
"type": [
|
|
324
|
+
"string",
|
|
325
|
+
"null"
|
|
326
|
+
],
|
|
327
|
+
"pattern": "^(https?://[^\\s/?#]+(?:[/?#].*)?|)$"
|
|
328
|
+
},
|
|
329
|
+
"interests": {
|
|
330
|
+
"type": [
|
|
331
|
+
"array",
|
|
332
|
+
"null"
|
|
333
|
+
],
|
|
334
|
+
"items": {
|
|
335
|
+
"type": "string"
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
"bio": {
|
|
339
|
+
"type": [
|
|
340
|
+
"string",
|
|
341
|
+
"null"
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
242
347
|
}
|
package/src/endpoint.ts
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
import { recallKookMessage, sendKookOutbound } from './outbound.js';
|
|
43
43
|
import { KookSenderRoleResolver, type KookSenderRoleProjection } from './sender-roles.js';
|
|
44
44
|
import { receiveKookSideEvent } from './side-event-dispatch.js';
|
|
45
|
+
import { createKookSelfProfile } from './self-profile.js';
|
|
45
46
|
|
|
46
47
|
export interface KookEndpointOptions {
|
|
47
48
|
readonly id: CapabilityId;
|
|
@@ -105,6 +106,7 @@ export class KookWebsocketEndpoint extends RuntimeKookClient implements Endpoint
|
|
|
105
106
|
stop: () => this.#stopFramework(), send: request => this.#sendFramework(request),
|
|
106
107
|
name: options.config.id, get transportState() { return endpoint.#transportState; },
|
|
107
108
|
management: this.#management, control: this.#control,
|
|
109
|
+
profile: createKookSelfProfile({ client: this, reportAccount: id => this[endpointSpec].reportSelfUserId(id) }),
|
|
108
110
|
});
|
|
109
111
|
}
|
|
110
112
|
|
|
@@ -266,6 +268,7 @@ export class KookWebhookEndpoint extends RuntimeKookClient implements Endpoint {
|
|
|
266
268
|
start: signal => this.#startFramework(signal), open: () => this.#openFramework(), close: () => this.#closeFramework(),
|
|
267
269
|
stop: () => this.#stopFramework(), send: request => this.#sendFramework(request), name: options.config.id,
|
|
268
270
|
management: this.#management, control: this.#control,
|
|
271
|
+
profile: createKookSelfProfile({ client: this, reportAccount: id => this[endpointSpec].reportSelfUserId(id) }),
|
|
269
272
|
});
|
|
270
273
|
}
|
|
271
274
|
|
package/src/protocol.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EndpointProfileConfiguration } from 'zhin.js/adapter';
|
|
1
2
|
/** KOOK protocol helpers. Canonicalization is owned by Core. */
|
|
2
3
|
|
|
3
4
|
import { createDecipheriv, timingSafeEqual } from 'node:crypto';
|
|
@@ -28,7 +29,7 @@ export enum KookPermission {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
/** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
|
|
31
|
-
export interface KookEndpointConfig {
|
|
32
|
+
export interface KookEndpointConfig extends EndpointProfileConfiguration {
|
|
32
33
|
readonly apiProxy?: import('./api-proxy.js').KookApiProxy;
|
|
33
34
|
readonly streamProxy?: import('./stream-proxy.js').KookStreamProxy;
|
|
34
35
|
readonly id: string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createEndpointOperation, type EndpointProfile } from 'zhin.js/adapter';
|
|
2
|
+
import type { RuntimeKookClient } from './ws.js';
|
|
3
|
+
|
|
4
|
+
interface KookSelfProfileOptions {
|
|
5
|
+
readonly client: Pick<RuntimeKookClient, 'getSelfInfo'>;
|
|
6
|
+
readonly reportAccount: (id: string) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Bot account profile facts from the SDK's existing /user/me method. */
|
|
10
|
+
export function createKookSelfProfile({ client, reportAccount }: KookSelfProfileOptions): EndpointProfile {
|
|
11
|
+
return Object.freeze<EndpointProfile>({
|
|
12
|
+
writableFields: Object.freeze([]),
|
|
13
|
+
async read({ signal }) {
|
|
14
|
+
const self = await createEndpointOperation({ signal }).prepare(() => client.getSelfInfo());
|
|
15
|
+
if (!self?.id || typeof self.username !== 'string') throw new Error('KOOK returned an incomplete self profile');
|
|
16
|
+
reportAccount(self.id);
|
|
17
|
+
return { nickname: self.username, ...(typeof self.avatar === 'string' ? { avatar: self.avatar } : {}) };
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { composeSideEventName, buildNotice,
|
|
1
|
+
import { composeSideEventName, buildNotice, senderFromId } from '@zhin.js/core';
|
|
2
2
|
import type { EndpointEventEmitter } from 'zhin.js/adapter';
|
|
3
3
|
import { formatCompact, type getAdapterLogger } from '@zhin.js/logger';
|
|
4
4
|
import type { KookWebhookEventData } from './protocol.js';
|
|
5
|
+
import { mapKookNoticeParts } from './side-event-map.js';
|
|
5
6
|
|
|
6
7
|
function extractKookNoticeType(raw: unknown): string | null {
|
|
7
8
|
if (!raw || typeof raw !== 'object') return null;
|
|
@@ -22,9 +23,9 @@ export function receiveKookSideEvent(
|
|
|
22
23
|
): boolean {
|
|
23
24
|
const noticeType = extractKookNoticeType(raw);
|
|
24
25
|
if (!noticeType) return false;
|
|
25
|
-
|
|
26
|
+
const parts = mapKookNoticeParts(noticeType);
|
|
27
|
+
if (!parts) return false;
|
|
26
28
|
const event = raw as KookWebhookEventData;
|
|
27
|
-
const parts = mapNoticeParts('kook', noticeType);
|
|
28
29
|
const body = event.extra?.body;
|
|
29
30
|
const guildId = event.extra?.guild_id
|
|
30
31
|
?? (event.channel_type === 'GROUP' && event.type === 255 ? event.target_id : undefined);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SideEventParts } from '@zhin.js/core';
|
|
2
|
+
|
|
3
|
+
/** KOOK extra.type 原始值 → 标准 scene_type + sub_type */
|
|
4
|
+
export const KOOK_NOTICE_PARTS_MAP: Readonly<Record<string, SideEventParts>> = {
|
|
5
|
+
joined_guild: { scene_type: 'group', sub_type: 'member_increase' },
|
|
6
|
+
exited_guild: { scene_type: 'group', sub_type: 'member_decrease' },
|
|
7
|
+
deleted_message: { scene_type: 'group', sub_type: 'recall' },
|
|
8
|
+
deleted_private_message: { scene_type: 'friend', sub_type: 'recall' },
|
|
9
|
+
added_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
10
|
+
deleted_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
11
|
+
private_added_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
12
|
+
private_deleted_reaction: { scene_type: 'group', sub_type: 'emoji_reaction' },
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** 已登记的 KOOK 通知映射为标准 scene_type + sub_type;未登记返回 undefined。 */
|
|
16
|
+
export function mapKookNoticeParts(raw: string): SideEventParts | undefined {
|
|
17
|
+
return Object.prototype.hasOwnProperty.call(KOOK_NOTICE_PARTS_MAP, raw) ? KOOK_NOTICE_PARTS_MAP[raw] : undefined;
|
|
18
|
+
}
|