@zhin.js/adapter-kook 1.1.15 → 1.1.16
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 +34 -0
- package/agents/kook/messages.js +48 -0
- package/agents/kook/messages.ts +48 -0
- package/agents/kook/skills/kook/tools/blacklist/index.js +4 -3
- package/agents/kook/skills/kook/tools/blacklist/index.ts +4 -3
- package/agents/kook/skills/kook/tools/create_role/index.js +2 -1
- package/agents/kook/skills/kook/tools/create_role/index.ts +2 -1
- package/agents/kook/skills/kook/tools/delete_role/index.js +2 -1
- package/agents/kook/skills/kook/tools/delete_role/index.ts +2 -1
- package/agents/kook/skills/kook/tools/grant_role/index.js +2 -1
- package/agents/kook/skills/kook/tools/grant_role/index.ts +2 -1
- package/agents/kook/skills/kook/tools/revoke_role/index.js +2 -1
- package/agents/kook/skills/kook/tools/revoke_role/index.ts +2 -1
- package/commands/kook/endpoint/definition.js +2 -2
- package/commands/kook/endpoint/definition.ts +2 -2
- package/lib/endpoint.d.ts +2 -2
- package/lib/endpoint.js +6 -4
- package/lib/i18n.d.ts +1 -0
- package/lib/i18n.js +9 -0
- package/lib/outbound.d.ts +1 -1
- package/lib/outbound.js +5 -4
- package/lib/protocol.d.ts +2 -1
- package/lib/protocol.js +6 -5
- package/package.json +16 -16
- package/schema.json +41 -6
- package/src/endpoint.ts +6 -4
- package/src/i18n.ts +10 -0
- package/src/outbound.ts +5 -4
- package/src/protocol.ts +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @zhin.js/adapter-kook
|
|
2
2
|
|
|
3
|
+
## 1.1.16
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 53bc6a0: 适配器配置标签、端点命令和工具反馈支持中英文;复用当前操作语言,保持协议值、用户内容、身份、权限与发送链路不变。Sandbox 展示使用项目语言,QQ 绑定与交互状态保留完整会话身份。
|
|
8
|
+
- 9cade30: 修复国际化调用链遗漏:Agent 审批、管理命令和错误反馈采用可信语言及实际命令前缀;游戏快捷帮助、工具反馈、平台默认卡片和后台通知贯通语言。协议即时回复复用受运行代约束的个人语言查询,业务验证支持不改变审批身份的双语展示元数据。
|
|
9
|
+
|
|
10
|
+
AI 正文、进度与耗尽摘要统一优先遵从用户明确语言要求,再跟随实际输入;个人/项目语言仅作兜底,固定界面文案继续使用配置语言,不增加翻译调用。
|
|
11
|
+
|
|
12
|
+
GitHub 工作区为 Git clone/pull/fetch/ls-remote 显式分隔选项与位置参数,保留仓库和分支校验;顺序写入 Bot 名称和邮箱,避免竞争同一配置文件锁。
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [334e92d]
|
|
15
|
+
- Updated dependencies [f3b7c9f]
|
|
16
|
+
- Updated dependencies [658a5fb]
|
|
17
|
+
- Updated dependencies [144a17b]
|
|
18
|
+
- Updated dependencies [18296cf]
|
|
19
|
+
- Updated dependencies [08e64de]
|
|
20
|
+
- Updated dependencies [9cade30]
|
|
21
|
+
- Updated dependencies [53bc6a0]
|
|
22
|
+
- Updated dependencies [7595136]
|
|
23
|
+
- Updated dependencies [66b6404]
|
|
24
|
+
- Updated dependencies [adb4af2]
|
|
25
|
+
- Updated dependencies [69f9ef6]
|
|
26
|
+
- Updated dependencies [17d1301]
|
|
27
|
+
- @zhin.js/adapter@1.1.23
|
|
28
|
+
- @zhin.js/host-http@1.1.10
|
|
29
|
+
- @zhin.js/core@1.1.51
|
|
30
|
+
- @zhin.js/permission@1.1.9
|
|
31
|
+
- @zhin.js/tool@1.1.10
|
|
32
|
+
- @zhin.js/skill@1.1.10
|
|
33
|
+
- @zhin.js/im-contract@1.1.7
|
|
34
|
+
- @zhin.js/agent-feature@1.1.10
|
|
35
|
+
- @zhin.js/feature-kit@1.1.9
|
|
36
|
+
|
|
3
37
|
## 1.1.15
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { createMessages } from 'zhin.js/i18n';
|
|
3
|
+
export const messages = createMessages({
|
|
4
|
+
"unknownAction": {
|
|
5
|
+
"zh-CN": "未知操作: {p0}",
|
|
6
|
+
"en": "Unknown action: {p0}"
|
|
7
|
+
},
|
|
8
|
+
"operationFailed": {
|
|
9
|
+
"zh-CN": "操作失败",
|
|
10
|
+
"en": "Operation failed"
|
|
11
|
+
},
|
|
12
|
+
"unblacklisted": {
|
|
13
|
+
"zh-CN": "已将 {p0} 从黑名单移除",
|
|
14
|
+
"en": "Removed {p0} from the blacklist"
|
|
15
|
+
},
|
|
16
|
+
"blacklisted": {
|
|
17
|
+
"zh-CN": "已将 {p0} 加入黑名单",
|
|
18
|
+
"en": "Added {p0} to the blacklist"
|
|
19
|
+
},
|
|
20
|
+
"roleCreated": {
|
|
21
|
+
"zh-CN": "已创建角色 \"{p0}\"",
|
|
22
|
+
"en": "Role \"{p0}\" created"
|
|
23
|
+
},
|
|
24
|
+
"roleDeleteFailed": {
|
|
25
|
+
"zh-CN": "删除角色失败",
|
|
26
|
+
"en": "Could not delete the role"
|
|
27
|
+
},
|
|
28
|
+
"roleDeleted": {
|
|
29
|
+
"zh-CN": "已删除角色 {p0}",
|
|
30
|
+
"en": "Role {p0} deleted"
|
|
31
|
+
},
|
|
32
|
+
"roleGrantFailed": {
|
|
33
|
+
"zh-CN": "授予角色失败",
|
|
34
|
+
"en": "Could not grant the role"
|
|
35
|
+
},
|
|
36
|
+
"roleGranted": {
|
|
37
|
+
"zh-CN": "已授予用户 {p0} 角色 {p1}",
|
|
38
|
+
"en": "Granted role {p1} to user {p0}"
|
|
39
|
+
},
|
|
40
|
+
"roleRevokeFailed": {
|
|
41
|
+
"zh-CN": "撤销角色失败",
|
|
42
|
+
"en": "Could not revoke the role"
|
|
43
|
+
},
|
|
44
|
+
"roleRevoked": {
|
|
45
|
+
"zh-CN": "已撤销用户 {p0} 的角色 {p1}",
|
|
46
|
+
"en": "Revoked role {p1} from user {p0}"
|
|
47
|
+
}
|
|
48
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createMessages } from 'zhin.js/i18n';
|
|
2
|
+
|
|
3
|
+
export const messages = createMessages({
|
|
4
|
+
"unknownAction": {
|
|
5
|
+
"zh-CN": "未知操作: {p0}",
|
|
6
|
+
"en": "Unknown action: {p0}"
|
|
7
|
+
},
|
|
8
|
+
"operationFailed": {
|
|
9
|
+
"zh-CN": "操作失败",
|
|
10
|
+
"en": "Operation failed"
|
|
11
|
+
},
|
|
12
|
+
"unblacklisted": {
|
|
13
|
+
"zh-CN": "已将 {p0} 从黑名单移除",
|
|
14
|
+
"en": "Removed {p0} from the blacklist"
|
|
15
|
+
},
|
|
16
|
+
"blacklisted": {
|
|
17
|
+
"zh-CN": "已将 {p0} 加入黑名单",
|
|
18
|
+
"en": "Added {p0} to the blacklist"
|
|
19
|
+
},
|
|
20
|
+
"roleCreated": {
|
|
21
|
+
"zh-CN": "已创建角色 \"{p0}\"",
|
|
22
|
+
"en": "Role \"{p0}\" created"
|
|
23
|
+
},
|
|
24
|
+
"roleDeleteFailed": {
|
|
25
|
+
"zh-CN": "删除角色失败",
|
|
26
|
+
"en": "Could not delete the role"
|
|
27
|
+
},
|
|
28
|
+
"roleDeleted": {
|
|
29
|
+
"zh-CN": "已删除角色 {p0}",
|
|
30
|
+
"en": "Role {p0} deleted"
|
|
31
|
+
},
|
|
32
|
+
"roleGrantFailed": {
|
|
33
|
+
"zh-CN": "授予角色失败",
|
|
34
|
+
"en": "Could not grant the role"
|
|
35
|
+
},
|
|
36
|
+
"roleGranted": {
|
|
37
|
+
"zh-CN": "已授予用户 {p0} 角色 {p1}",
|
|
38
|
+
"en": "Granted role {p1} to user {p0}"
|
|
39
|
+
},
|
|
40
|
+
"roleRevokeFailed": {
|
|
41
|
+
"zh-CN": "撤销角色失败",
|
|
42
|
+
"en": "Could not revoke the role"
|
|
43
|
+
},
|
|
44
|
+
"roleRevoked": {
|
|
45
|
+
"zh-CN": "已撤销用户 {p0} 的角色 {p1}",
|
|
46
|
+
"en": "Revoked role {p1} from user {p0}"
|
|
47
|
+
}
|
|
48
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { messages as t } from "../../../../messages.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -19,14 +20,14 @@ export default defineAgentTool({
|
|
|
19
20
|
switch (action) {
|
|
20
21
|
case 'add': {
|
|
21
22
|
const success = await member.addToBlackList(remark);
|
|
22
|
-
return { success, message: success ?
|
|
23
|
+
return { success, message: success ? t(context.locale, 'blacklisted', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
23
24
|
}
|
|
24
25
|
case 'remove': {
|
|
25
26
|
const success = await member.removeFromBlackList();
|
|
26
|
-
return { success, message: success ?
|
|
27
|
+
return { success, message: success ? t(context.locale, 'unblacklisted', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
27
28
|
}
|
|
28
29
|
default:
|
|
29
|
-
return { success: false, message:
|
|
30
|
+
return { success: false, message: t(context.locale, 'unknownAction', { p0: action }) };
|
|
30
31
|
}
|
|
31
32
|
},
|
|
32
33
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { messages as t } from "../../../../messages.js";
|
|
1
2
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -19,14 +20,14 @@ export default defineAgentTool<{ guild_id: string; action: 'add' | 'remove'; use
|
|
|
19
20
|
switch (action) {
|
|
20
21
|
case 'add': {
|
|
21
22
|
const success = await member.addToBlackList(remark);
|
|
22
|
-
return { success, message: success ?
|
|
23
|
+
return { success, message: success ? t(context.locale, 'blacklisted', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
23
24
|
}
|
|
24
25
|
case 'remove': {
|
|
25
26
|
const success = await member.removeFromBlackList();
|
|
26
|
-
return { success, message: success ?
|
|
27
|
+
return { success, message: success ? t(context.locale, 'unblacklisted', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
27
28
|
}
|
|
28
29
|
default:
|
|
29
|
-
return { success: false, message:
|
|
30
|
+
return { success: false, message: t(context.locale, 'unknownAction', { p0: action }) };
|
|
30
31
|
}
|
|
31
32
|
},
|
|
32
33
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { messages as t } from "../../../../messages.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -17,7 +18,7 @@ export default defineAgentTool({
|
|
|
17
18
|
const role = await client.pickGuild(guild_id).createRole(name);
|
|
18
19
|
return {
|
|
19
20
|
success: true,
|
|
20
|
-
message:
|
|
21
|
+
message: t(context.locale, 'roleCreated', { p0: name }),
|
|
21
22
|
role: { id: role.role_id, name: role.name },
|
|
22
23
|
};
|
|
23
24
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { messages as t } from "../../../../messages.js";
|
|
1
2
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -17,7 +18,7 @@ export default defineAgentTool<{ guild_id: string; name: string }>({
|
|
|
17
18
|
const role = await client.pickGuild(guild_id).createRole(name);
|
|
18
19
|
return {
|
|
19
20
|
success: true,
|
|
20
|
-
message:
|
|
21
|
+
message: t(context.locale, 'roleCreated', { p0: name }),
|
|
21
22
|
role: { id: role.role_id, name: role.name },
|
|
22
23
|
};
|
|
23
24
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { messages as t } from "../../../../messages.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -15,6 +16,6 @@ export default defineAgentTool({
|
|
|
15
16
|
async execute({ guild_id, role_id }, context) {
|
|
16
17
|
const client = context.$client;
|
|
17
18
|
const success = await client.pickGuild(guild_id).deleteRole(role_id);
|
|
18
|
-
return { success, message: success ?
|
|
19
|
+
return { success, message: success ? t(context.locale, 'roleDeleted', { p0: role_id }) : t(context.locale, 'roleDeleteFailed') };
|
|
19
20
|
},
|
|
20
21
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { messages as t } from "../../../../messages.js";
|
|
1
2
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -15,6 +16,6 @@ export default defineAgentTool<{ guild_id: string; role_id: string }>({
|
|
|
15
16
|
async execute({ guild_id, role_id }: { guild_id: string; role_id: string }, context) {
|
|
16
17
|
const client = context.$client;
|
|
17
18
|
const success = await client.pickGuild(guild_id).deleteRole(role_id);
|
|
18
|
-
return { success, message: success ?
|
|
19
|
+
return { success, message: success ? t(context.locale, 'roleDeleted', { p0: role_id }) : t(context.locale, 'roleDeleteFailed') };
|
|
19
20
|
},
|
|
20
21
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { messages as t } from "../../../../messages.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -16,6 +17,6 @@ export default defineAgentTool({
|
|
|
16
17
|
async execute({ guild_id, user_id, role_id }, context) {
|
|
17
18
|
const client = context.$client;
|
|
18
19
|
const success = await client.pickGuildMember(guild_id, user_id).grant(role_id);
|
|
19
|
-
return { success, message: success ?
|
|
20
|
+
return { success, message: success ? t(context.locale, 'roleGranted', { p0: user_id, p1: role_id }) : t(context.locale, 'roleGrantFailed') };
|
|
20
21
|
},
|
|
21
22
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { messages as t } from "../../../../messages.js";
|
|
1
2
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -16,6 +17,6 @@ export default defineAgentTool<{ guild_id: string; user_id: string; role_id: str
|
|
|
16
17
|
async execute({ guild_id, user_id, role_id }: { guild_id: string; user_id: string; role_id: string }, context) {
|
|
17
18
|
const client = context.$client;
|
|
18
19
|
const success = await client.pickGuildMember(guild_id, user_id).grant(role_id);
|
|
19
|
-
return { success, message: success ?
|
|
20
|
+
return { success, message: success ? t(context.locale, 'roleGranted', { p0: user_id, p1: role_id }) : t(context.locale, 'roleGrantFailed') };
|
|
20
21
|
},
|
|
21
22
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { messages as t } from "../../../../messages.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -16,6 +17,6 @@ export default defineAgentTool({
|
|
|
16
17
|
async execute({ guild_id, user_id, role_id }, context) {
|
|
17
18
|
const client = context.$client;
|
|
18
19
|
const success = await client.pickGuildMember(guild_id, user_id).revoke(role_id);
|
|
19
|
-
return { success, message: success ?
|
|
20
|
+
return { success, message: success ? t(context.locale, 'roleRevoked', { p0: user_id, p1: role_id }) : t(context.locale, 'roleRevokeFailed') };
|
|
20
21
|
},
|
|
21
22
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { messages as t } from "../../../../messages.js";
|
|
1
2
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
import { platformPermission } from '@zhin.js/permission';
|
|
@@ -16,6 +17,6 @@ export default defineAgentTool<{ guild_id: string; user_id: string; role_id: str
|
|
|
16
17
|
async execute({ guild_id, user_id, role_id }: { guild_id: string; user_id: string; role_id: string }, context) {
|
|
17
18
|
const client = context.$client;
|
|
18
19
|
const success = await client.pickGuildMember(guild_id, user_id).revoke(role_id);
|
|
19
|
-
return { success, message: success ?
|
|
20
|
+
return { success, message: success ? t(context.locale, 'roleRevoked', { p0: user_id, p1: role_id }) : t(context.locale, 'roleRevokeFailed') };
|
|
20
21
|
},
|
|
21
22
|
});
|
|
@@ -11,8 +11,8 @@ export const kookEndpointCommands = createEndpointCommands({
|
|
|
11
11
|
adapterDisplayName: 'KOOK',
|
|
12
12
|
fields: [
|
|
13
13
|
{ key: 'token', required: true, env: true, description: 'KOOK bot token' },
|
|
14
|
-
{ key: 'encrypt_key', env: true, description: 'webhook 加密密钥(connection: webhook)' },
|
|
15
|
-
{ key: 'verify_token', env: true, description: 'webhook 验证 token(connection: webhook)' },
|
|
14
|
+
{ key: 'encrypt_key', env: true, description: 'webhook 加密密钥(connection: webhook)', descriptionI18n: { en: "Webhook encryption secret (connection: webhook)" } },
|
|
15
|
+
{ key: 'verify_token', env: true, description: 'webhook 验证 token(connection: webhook)', descriptionI18n: { en: "Webhook verification token (connection: webhook)" } },
|
|
16
16
|
],
|
|
17
17
|
running: (use) => use(kookRuntimeStateToken).endpoints.values(),
|
|
18
18
|
describeEntry: (entry) => `token: ${String(entry.token)}`,
|
|
@@ -11,8 +11,8 @@ export const kookEndpointCommands = createEndpointCommands({
|
|
|
11
11
|
adapterDisplayName: 'KOOK',
|
|
12
12
|
fields: [
|
|
13
13
|
{ key: 'token', required: true, env: true, description: 'KOOK bot token' },
|
|
14
|
-
{ key: 'encrypt_key', env: true, description: 'webhook 加密密钥(connection: webhook)' },
|
|
15
|
-
{ key: 'verify_token', env: true, description: 'webhook 验证 token(connection: webhook)' },
|
|
14
|
+
{ key: 'encrypt_key', env: true, description: 'webhook 加密密钥(connection: webhook)', descriptionI18n: { en: "Webhook encryption secret (connection: webhook)" } },
|
|
15
|
+
{ key: 'verify_token', env: true, description: 'webhook 验证 token(connection: webhook)', descriptionI18n: { en: "Webhook verification token (connection: webhook)" } },
|
|
16
16
|
],
|
|
17
17
|
running: (use) => use(kookRuntimeStateToken).endpoints.values(),
|
|
18
18
|
describeEntry: (entry) => `token: ${String(entry.token)}`,
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare class KookWebsocketEndpoint extends Endpoint<KookClientTransport>
|
|
|
20
20
|
open(): void;
|
|
21
21
|
close(): void;
|
|
22
22
|
stop(): Promise<void>;
|
|
23
|
-
send(
|
|
23
|
+
send(request: EndpointSendRequest): Promise<string>;
|
|
24
24
|
/** Test / internal: admit a normalized message when open. */
|
|
25
25
|
admit(msg: KookInboundMessage): void;
|
|
26
26
|
recallMessage(messageId: string, conversation?: ConversationRef): Promise<void>;
|
|
@@ -46,7 +46,7 @@ export declare class KookWebhookEndpoint extends Endpoint<KookClientTransport> {
|
|
|
46
46
|
open(): void;
|
|
47
47
|
close(): void;
|
|
48
48
|
stop(): Promise<void>;
|
|
49
|
-
send(
|
|
49
|
+
send(request: EndpointSendRequest): Promise<string>;
|
|
50
50
|
admitEvent(event: KookWebhookEventData): Promise<void>;
|
|
51
51
|
/** Test / internal: admit a message when open. */
|
|
52
52
|
admit(msg: KookInboundMessage): void;
|
package/lib/endpoint.js
CHANGED
|
@@ -100,8 +100,9 @@ export class KookWebsocketEndpoint extends Endpoint {
|
|
|
100
100
|
this.#started = false;
|
|
101
101
|
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
102
102
|
}
|
|
103
|
-
async send(
|
|
104
|
-
const
|
|
103
|
+
async send(request) {
|
|
104
|
+
const { conversation } = request;
|
|
105
|
+
const messageId = await sendKookOutbound(this.#requireClient(), request);
|
|
105
106
|
rememberKookConversation(this.#sentConversations, messageId, conversation);
|
|
106
107
|
this.#logger.debug(formatCompact({
|
|
107
108
|
op: 'kook_send',
|
|
@@ -255,8 +256,9 @@ export class KookWebhookEndpoint extends Endpoint {
|
|
|
255
256
|
this.#started = false;
|
|
256
257
|
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
257
258
|
}
|
|
258
|
-
async send(
|
|
259
|
-
const
|
|
259
|
+
async send(request) {
|
|
260
|
+
const { conversation } = request;
|
|
261
|
+
const messageId = await sendKookOutbound(this.#requireClient(), request);
|
|
260
262
|
rememberKookConversation(this.#sentConversations, messageId, conversation);
|
|
261
263
|
this.#logger.debug(formatCompact({
|
|
262
264
|
op: 'kook_send',
|
package/lib/i18n.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const outboundMessages: (locale: import("zhin.js").Locale | undefined, key: "openLink" | "image" | "video" | "audio" | "file" | "unnamed", values?: import("zhin.js").MessageValues) => string;
|
package/lib/i18n.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createMessages } from 'zhin.js/i18n';
|
|
2
|
+
export const outboundMessages = createMessages({
|
|
3
|
+
openLink: { 'zh-CN': '打开链接', en: 'Open link' },
|
|
4
|
+
image: { 'zh-CN': '图片', en: 'Image' },
|
|
5
|
+
video: { 'zh-CN': '视频', en: 'Video' },
|
|
6
|
+
audio: { 'zh-CN': '音频', en: 'Audio' },
|
|
7
|
+
file: { 'zh-CN': '文件: {name}', en: 'File: {name}' },
|
|
8
|
+
unnamed: { 'zh-CN': '未命名', en: 'Unnamed' },
|
|
9
|
+
});
|
package/lib/outbound.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ import { type MessageRef } from '@zhin.js/im-contract';
|
|
|
2
2
|
import type { EndpointSendRequest } from 'zhin.js/adapter';
|
|
3
3
|
import type { KookClientTransport } from './ws.js';
|
|
4
4
|
/** Native cards preserve mixed text/images; SDK's ordinary segments stop at first media. */
|
|
5
|
-
export declare function sendKookOutbound(client: KookClientTransport, { conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
5
|
+
export declare function sendKookOutbound(client: KookClientTransport, { conversation, payload, locale }: EndpointSendRequest): Promise<string>;
|
|
6
6
|
/** Deletion requires the canonical conversation: KOOK has separate channel/private APIs. */
|
|
7
7
|
export declare function recallKookMessage(client: KookClientTransport, message: MessageRef): Promise<void>;
|
package/lib/outbound.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { EndpointDeliveryError, isMediaRef } from '@zhin.js/im-contract';
|
|
3
3
|
import { formatOutboundKmarkdown } from './protocol.js';
|
|
4
|
+
import { outboundMessages as t } from './i18n.js';
|
|
4
5
|
/** Native cards preserve mixed text/images; SDK's ordinary segments stop at first media. */
|
|
5
|
-
export async function sendKookOutbound(client, { conversation, payload }) {
|
|
6
|
+
export async function sendKookOutbound(client, { conversation, payload, locale }) {
|
|
6
7
|
try {
|
|
7
8
|
const items = Array.isArray(payload) ? payload : payload && typeof payload === 'object' ? [payload] : [payload];
|
|
8
9
|
let quote;
|
|
@@ -52,7 +53,7 @@ export async function sendKookOutbound(client, { conversation, payload }) {
|
|
|
52
53
|
for (const value of [data.description, data.content])
|
|
53
54
|
if (typeof value === 'string' && value)
|
|
54
55
|
modules.push({ type: 'section', mode: 'left', text: { type: 'plain-text', content: value } });
|
|
55
|
-
modules.push({ type: 'action-group', elements: [{ type: 'button', theme: 'secondary', click: 'link', value: url.href, text: { type: 'plain-text', content: '
|
|
56
|
+
modules.push({ type: 'action-group', elements: [{ type: 'button', theme: 'secondary', click: 'link', value: url.href, text: { type: 'plain-text', content: t(locale, 'openLink') } }] });
|
|
56
57
|
}
|
|
57
58
|
else if (item && typeof item === 'object' && item.type === 'image') {
|
|
58
59
|
hasImage = true;
|
|
@@ -87,12 +88,12 @@ export async function sendKookOutbound(client, { conversation, payload }) {
|
|
|
87
88
|
&& isMediaRef(item.data?.media) && !['url', 'file'].includes(item.data.media.kind)) {
|
|
88
89
|
throw new EndpointDeliveryError('unsupported_media', 'KOOK binary uploads currently support images only', 'rejected');
|
|
89
90
|
}
|
|
90
|
-
const text = formatOutboundKmarkdown([item]);
|
|
91
|
+
const text = formatOutboundKmarkdown([item], locale);
|
|
91
92
|
if (text)
|
|
92
93
|
modules.push({ type: 'section', mode: 'left', text: { type: 'kmarkdown', content: text } });
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
|
-
const body = hasImage || hasCard ? { __isCard: true, type: 'card', theme: 'secondary', size: 'lg', modules } : formatOutboundKmarkdown(payload);
|
|
96
|
+
const body = hasImage || hasCard ? { __isCard: true, type: 'card', theme: 'secondary', size: 'lg', modules } : formatOutboundKmarkdown(payload, locale);
|
|
96
97
|
const result = conversation.kind === 'private'
|
|
97
98
|
? await client.sendPrivateMsg(conversation.id, body, quote)
|
|
98
99
|
: await client.sendChannelMsg(conversation.id, body, quote);
|
package/lib/protocol.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** KOOK protocol helpers. Canonicalization is owned by Core. */
|
|
2
2
|
import type { IncomingMessage } from 'node:http';
|
|
3
3
|
import { type ConversationRef } from '@zhin.js/im-contract';
|
|
4
|
+
import type { Locale } from 'zhin.js/i18n';
|
|
4
5
|
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'mark' | 'off';
|
|
5
6
|
export declare enum KookPermission {
|
|
6
7
|
Normal = 1,
|
|
@@ -126,7 +127,7 @@ export declare function isKookBotMentioned(msg: KookInboundMessage, selfId?: str
|
|
|
126
127
|
* Wire-encode an already-rendered outbound payload into KOOK KMarkdown.
|
|
127
128
|
* Segment canonicalization is intentionally not done here.
|
|
128
129
|
*/
|
|
129
|
-
export declare function formatOutboundKmarkdown(payload: unknown): string;
|
|
130
|
+
export declare function formatOutboundKmarkdown(payload: unknown, locale?: Locale): string;
|
|
130
131
|
export declare function normalizeWebhookPath(path: string): string;
|
|
131
132
|
export declare function readTextBody(request: IncomingMessage, options?: {
|
|
132
133
|
readonly limit?: number;
|
package/lib/protocol.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createDecipheriv, timingSafeEqual } from 'node:crypto';
|
|
|
3
3
|
import { inflateSync } from 'node:zlib';
|
|
4
4
|
import { EndpointDeliveryError, isMediaRef } from '@zhin.js/im-contract';
|
|
5
5
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
6
|
+
import { outboundMessages as t } from './i18n.js';
|
|
6
7
|
const logger = getLogger('kook');
|
|
7
8
|
export var KookPermission;
|
|
8
9
|
(function (KookPermission) {
|
|
@@ -118,7 +119,7 @@ function resolveOutboundMediaUrl(seg) {
|
|
|
118
119
|
* Wire-encode an already-rendered outbound payload into KOOK KMarkdown.
|
|
119
120
|
* Segment canonicalization is intentionally not done here.
|
|
120
121
|
*/
|
|
121
|
-
export function formatOutboundKmarkdown(payload) {
|
|
122
|
+
export function formatOutboundKmarkdown(payload, locale) {
|
|
122
123
|
if (typeof payload === 'string')
|
|
123
124
|
return payload;
|
|
124
125
|
const segments = Array.isArray(payload)
|
|
@@ -152,7 +153,7 @@ export function formatOutboundKmarkdown(payload) {
|
|
|
152
153
|
}
|
|
153
154
|
case 'image': {
|
|
154
155
|
const url = resolveOutboundMediaUrl(item);
|
|
155
|
-
return url ? `` : '';
|
|
156
157
|
}
|
|
157
158
|
case 'face':
|
|
158
159
|
return `(emj)${String(data.name || 'emoji')}(emj)[${String(data.id ?? '')}]`;
|
|
@@ -160,15 +161,15 @@ export function formatOutboundKmarkdown(payload) {
|
|
|
160
161
|
return `[${String(data.text || data.url || '')}](${String(data.url || '')})`;
|
|
161
162
|
case 'video': {
|
|
162
163
|
const url = resolveOutboundMediaUrl(item);
|
|
163
|
-
return url ? `[
|
|
164
|
+
return url ? `[${t(locale, 'video')}](${url})` : '';
|
|
164
165
|
}
|
|
165
166
|
case 'audio': {
|
|
166
167
|
const url = resolveOutboundMediaUrl(item);
|
|
167
|
-
return url ? `[
|
|
168
|
+
return url ? `[${t(locale, 'audio')}](${url})` : '';
|
|
168
169
|
}
|
|
169
170
|
case 'file': {
|
|
170
171
|
const url = resolveOutboundMediaUrl(item);
|
|
171
|
-
return url ? `[
|
|
172
|
+
return url ? `[${t(locale, 'file', { name: String(data.name || t(locale, 'unnamed')) })}](${url})` : '';
|
|
172
173
|
}
|
|
173
174
|
case 'bold':
|
|
174
175
|
return `**${String(data.text ?? '')}**`;
|
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.16",
|
|
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,23 +33,23 @@
|
|
|
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/core": "1.1.
|
|
39
|
-
"@zhin.js/feature-kit": "1.1.
|
|
40
|
-
"@zhin.js/host-http": "1.1.
|
|
41
|
-
"@zhin.js/im-contract": "1.1.
|
|
36
|
+
"@zhin.js/adapter": "1.1.23",
|
|
37
|
+
"@zhin.js/agent-feature": "1.1.10",
|
|
38
|
+
"@zhin.js/core": "1.1.51",
|
|
39
|
+
"@zhin.js/feature-kit": "1.1.9",
|
|
40
|
+
"@zhin.js/host-http": "1.1.10",
|
|
41
|
+
"@zhin.js/im-contract": "1.1.7",
|
|
42
42
|
"@zhin.js/logger": "1.1.2",
|
|
43
|
-
"@zhin.js/permission": "1.1.
|
|
44
|
-
"@zhin.js/skill": "1.1.
|
|
45
|
-
"@zhin.js/tool": "1.1.
|
|
43
|
+
"@zhin.js/permission": "1.1.9",
|
|
44
|
+
"@zhin.js/skill": "1.1.10",
|
|
45
|
+
"@zhin.js/tool": "1.1.10"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"zod": "^4.0.0",
|
|
49
|
-
"@zhin.js/adapter": "^1.1.
|
|
50
|
-
"@zhin.js/command": "^1.1.
|
|
51
|
-
"@zhin.js/core": "^1.1.
|
|
52
|
-
"zhin.js": "^1.1.
|
|
49
|
+
"@zhin.js/adapter": "^1.1.23",
|
|
50
|
+
"@zhin.js/command": "^1.1.11",
|
|
51
|
+
"@zhin.js/core": "^1.1.51",
|
|
52
|
+
"zhin.js": "^1.1.16"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@zhin.js/command": {
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"typescript": "^6.0.3",
|
|
68
68
|
"vitest": "^4.1.10",
|
|
69
69
|
"zod": "^4.4.3",
|
|
70
|
-
"@zhin.js/host-http": "1.1.
|
|
71
|
-
"zhin.js": "1.1.
|
|
70
|
+
"@zhin.js/host-http": "1.1.10",
|
|
71
|
+
"zhin.js": "1.1.16"
|
|
72
72
|
},
|
|
73
73
|
"files": [
|
|
74
74
|
"adapters",
|
package/schema.json
CHANGED
|
@@ -55,7 +55,12 @@
|
|
|
55
55
|
"string",
|
|
56
56
|
"number"
|
|
57
57
|
],
|
|
58
|
-
"description": "框架 master(KOOK user id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
58
|
+
"description": "框架 master(KOOK user id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖",
|
|
59
|
+
"x-i18n": {
|
|
60
|
+
"en": {
|
|
61
|
+
"description": "Framework masters (KOOK user id; AI/tool permissions and endpoint management). endpoints[i].master can override this value."
|
|
62
|
+
}
|
|
63
|
+
}
|
|
59
64
|
},
|
|
60
65
|
"trusted": {
|
|
61
66
|
"type": "array",
|
|
@@ -66,7 +71,12 @@
|
|
|
66
71
|
],
|
|
67
72
|
"description": "Trusted KOOK user id"
|
|
68
73
|
},
|
|
69
|
-
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
74
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加",
|
|
75
|
+
"x-i18n": {
|
|
76
|
+
"en": {
|
|
77
|
+
"description": "Framework trusted users, below master authority. endpoints[i].trusted can add users."
|
|
78
|
+
}
|
|
79
|
+
}
|
|
70
80
|
},
|
|
71
81
|
"endpoints": {
|
|
72
82
|
"type": "array",
|
|
@@ -81,7 +91,12 @@
|
|
|
81
91
|
"string",
|
|
82
92
|
"number"
|
|
83
93
|
],
|
|
84
|
-
"description": "本 endpoint 的框架 master(KOOK user id);覆盖顶层 master"
|
|
94
|
+
"description": "本 endpoint 的框架 master(KOOK user id);覆盖顶层 master",
|
|
95
|
+
"x-i18n": {
|
|
96
|
+
"en": {
|
|
97
|
+
"description": "Framework masters for this endpoint (KOOK user id), overriding the top-level master list."
|
|
98
|
+
}
|
|
99
|
+
}
|
|
85
100
|
},
|
|
86
101
|
"trusted": {
|
|
87
102
|
"type": "array",
|
|
@@ -92,7 +107,12 @@
|
|
|
92
107
|
],
|
|
93
108
|
"description": "Trusted KOOK user id"
|
|
94
109
|
},
|
|
95
|
-
"description": "本 endpoint 的 trusted 列表"
|
|
110
|
+
"description": "本 endpoint 的 trusted 列表",
|
|
111
|
+
"x-i18n": {
|
|
112
|
+
"en": {
|
|
113
|
+
"description": "Trusted users for this endpoint."
|
|
114
|
+
}
|
|
115
|
+
}
|
|
96
116
|
},
|
|
97
117
|
"token": {
|
|
98
118
|
"type": "string",
|
|
@@ -171,7 +191,12 @@
|
|
|
171
191
|
"port",
|
|
172
192
|
"serverName"
|
|
173
193
|
],
|
|
174
|
-
"description": "WSS故障验收固定loopback,保持真实TLS身份"
|
|
194
|
+
"description": "WSS故障验收固定loopback,保持真实TLS身份",
|
|
195
|
+
"x-i18n": {
|
|
196
|
+
"en": {
|
|
197
|
+
"description": "Pin WSS fault-injection tests to loopback while preserving the actual TLS identity."
|
|
198
|
+
}
|
|
199
|
+
}
|
|
175
200
|
},
|
|
176
201
|
"apiProxy": {
|
|
177
202
|
"type": "object",
|
|
@@ -193,12 +218,22 @@
|
|
|
193
218
|
"id",
|
|
194
219
|
"token"
|
|
195
220
|
]
|
|
221
|
+
},
|
|
222
|
+
"x-i18n": {
|
|
223
|
+
"en": {
|
|
224
|
+
"description": "Multiple accounts: each entry defines an endpoint. id and token are required; other fields override instance defaults."
|
|
225
|
+
}
|
|
196
226
|
}
|
|
197
227
|
},
|
|
198
228
|
"commandPrefix": {
|
|
199
229
|
"type": "string",
|
|
200
230
|
"default": "",
|
|
201
|
-
"description": "命令前缀(默认 '' 无前缀,任意文本按命令匹配;如 '/' 要求 / 开头)。endpoints[i] 可逐项覆盖"
|
|
231
|
+
"description": "命令前缀(默认 '' 无前缀,任意文本按命令匹配;如 '/' 要求 / 开头)。endpoints[i] 可逐项覆盖",
|
|
232
|
+
"x-i18n": {
|
|
233
|
+
"en": {
|
|
234
|
+
"description": "Command prefix. The default empty string allows unprefixed commands; '/' requires a leading slash. Each endpoints[i] can override it."
|
|
235
|
+
}
|
|
236
|
+
}
|
|
202
237
|
}
|
|
203
238
|
},
|
|
204
239
|
"required": [
|
package/src/endpoint.ts
CHANGED
|
@@ -151,8 +151,9 @@ export class KookWebsocketEndpoint extends Endpoint<KookClientTransport> {
|
|
|
151
151
|
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
async send(
|
|
155
|
-
const
|
|
154
|
+
async send(request: EndpointSendRequest): Promise<string> {
|
|
155
|
+
const { conversation } = request;
|
|
156
|
+
const messageId = await sendKookOutbound(this.#requireClient(), request);
|
|
156
157
|
rememberKookConversation(this.#sentConversations, messageId, conversation);
|
|
157
158
|
this.#logger.debug(formatCompact({
|
|
158
159
|
op: 'kook_send',
|
|
@@ -321,8 +322,9 @@ export class KookWebhookEndpoint extends Endpoint<KookClientTransport> {
|
|
|
321
322
|
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
322
323
|
}
|
|
323
324
|
|
|
324
|
-
async send(
|
|
325
|
-
const
|
|
325
|
+
async send(request: EndpointSendRequest): Promise<string> {
|
|
326
|
+
const { conversation } = request;
|
|
327
|
+
const messageId = await sendKookOutbound(this.#requireClient(), request);
|
|
326
328
|
rememberKookConversation(this.#sentConversations, messageId, conversation);
|
|
327
329
|
this.#logger.debug(formatCompact({
|
|
328
330
|
op: 'kook_send',
|
package/src/i18n.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createMessages } from 'zhin.js/i18n';
|
|
2
|
+
|
|
3
|
+
export const outboundMessages = createMessages({
|
|
4
|
+
openLink: { 'zh-CN': '打开链接', en: 'Open link' },
|
|
5
|
+
image: { 'zh-CN': '图片', en: 'Image' },
|
|
6
|
+
video: { 'zh-CN': '视频', en: 'Video' },
|
|
7
|
+
audio: { 'zh-CN': '音频', en: 'Audio' },
|
|
8
|
+
file: { 'zh-CN': '文件: {name}', en: 'File: {name}' },
|
|
9
|
+
unnamed: { 'zh-CN': '未命名', en: 'Unnamed' },
|
|
10
|
+
});
|
package/src/outbound.ts
CHANGED
|
@@ -3,9 +3,10 @@ import { EndpointDeliveryError, isMediaRef, type MessageRef } from '@zhin.js/im-
|
|
|
3
3
|
import type { EndpointSendRequest } from 'zhin.js/adapter';
|
|
4
4
|
import { formatOutboundKmarkdown } from './protocol.js';
|
|
5
5
|
import type { KookClientTransport } from './ws.js';
|
|
6
|
+
import { outboundMessages as t } from './i18n.js';
|
|
6
7
|
|
|
7
8
|
/** Native cards preserve mixed text/images; SDK's ordinary segments stop at first media. */
|
|
8
|
-
export async function sendKookOutbound(client: KookClientTransport, { conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
9
|
+
export async function sendKookOutbound(client: KookClientTransport, { conversation, payload, locale }: EndpointSendRequest): Promise<string> {
|
|
9
10
|
try {
|
|
10
11
|
const items = Array.isArray(payload) ? payload : payload && typeof payload === 'object' ? [payload] : [payload];
|
|
11
12
|
let quote: { message_id: string } | undefined;
|
|
@@ -40,7 +41,7 @@ export async function sendKookOutbound(client: KookClientTransport, { conversati
|
|
|
40
41
|
if (['image', 'audio', 'artist', 'duration', 'platform', 'config'].some(key => data[key] !== undefined)) throw new EndpointDeliveryError('unsupported_operation', 'KOOK share media/app metadata is not implemented', 'not_sent');
|
|
41
42
|
modules.push({ type: 'section', mode: 'left', text: { type: 'plain-text', content: data.title } });
|
|
42
43
|
for (const value of [data.description, data.content]) if (typeof value === 'string' && value) modules.push({ type: 'section', mode: 'left', text: { type: 'plain-text', content: value } });
|
|
43
|
-
modules.push({ type: 'action-group', elements: [{ type: 'button', theme: 'secondary', click: 'link', value: url.href, text: { type: 'plain-text', content: '
|
|
44
|
+
modules.push({ type: 'action-group', elements: [{ type: 'button', theme: 'secondary', click: 'link', value: url.href, text: { type: 'plain-text', content: t(locale, 'openLink') } }] });
|
|
44
45
|
} else if (item && typeof item === 'object' && item.type === 'image') {
|
|
45
46
|
hasImage = true;
|
|
46
47
|
const media = item.data?.media;
|
|
@@ -66,11 +67,11 @@ export async function sendKookOutbound(client: KookClientTransport, { conversati
|
|
|
66
67
|
&& isMediaRef(item.data?.media) && !['url', 'file'].includes(item.data.media.kind)) {
|
|
67
68
|
throw new EndpointDeliveryError('unsupported_media', 'KOOK binary uploads currently support images only', 'rejected');
|
|
68
69
|
}
|
|
69
|
-
const text = formatOutboundKmarkdown([item]);
|
|
70
|
+
const text = formatOutboundKmarkdown([item], locale);
|
|
70
71
|
if (text) modules.push({ type: 'section', mode: 'left', text: { type: 'kmarkdown', content: text } });
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
|
-
const body = hasImage || hasCard ? { __isCard: true, type: 'card', theme: 'secondary', size: 'lg', modules } : formatOutboundKmarkdown(payload);
|
|
74
|
+
const body = hasImage || hasCard ? { __isCard: true, type: 'card', theme: 'secondary', size: 'lg', modules } : formatOutboundKmarkdown(payload, locale);
|
|
74
75
|
const result = conversation.kind === 'private'
|
|
75
76
|
? await client.sendPrivateMsg(conversation.id, body, quote)
|
|
76
77
|
: await client.sendChannelMsg(conversation.id, body, quote);
|
package/src/protocol.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { inflateSync } from 'node:zlib';
|
|
|
5
5
|
import type { IncomingMessage } from 'node:http';
|
|
6
6
|
import { EndpointDeliveryError, isMediaRef, type ConversationRef } from '@zhin.js/im-contract';
|
|
7
7
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
8
|
+
import type { Locale } from 'zhin.js/i18n';
|
|
9
|
+
import { outboundMessages as t } from './i18n.js';
|
|
8
10
|
|
|
9
11
|
const logger = getLogger('kook');
|
|
10
12
|
|
|
@@ -248,7 +250,7 @@ function resolveOutboundMediaUrl(seg: KookWireSegment): string | undefined {
|
|
|
248
250
|
* Wire-encode an already-rendered outbound payload into KOOK KMarkdown.
|
|
249
251
|
* Segment canonicalization is intentionally not done here.
|
|
250
252
|
*/
|
|
251
|
-
export function formatOutboundKmarkdown(payload: unknown): string {
|
|
253
|
+
export function formatOutboundKmarkdown(payload: unknown, locale?: Locale): string {
|
|
252
254
|
if (typeof payload === 'string') return payload;
|
|
253
255
|
|
|
254
256
|
const segments: Array<string | KookWireSegment> = Array.isArray(payload)
|
|
@@ -283,7 +285,7 @@ export function formatOutboundKmarkdown(payload: unknown): string {
|
|
|
283
285
|
}
|
|
284
286
|
case 'image': {
|
|
285
287
|
const url = resolveOutboundMediaUrl(item);
|
|
286
|
-
return url ? `` : '';
|
|
287
289
|
}
|
|
288
290
|
case 'face':
|
|
289
291
|
return `(emj)${String(data.name || 'emoji')}(emj)[${String(data.id ?? '')}]`;
|
|
@@ -291,15 +293,15 @@ export function formatOutboundKmarkdown(payload: unknown): string {
|
|
|
291
293
|
return `[${String(data.text || data.url || '')}](${String(data.url || '')})`;
|
|
292
294
|
case 'video': {
|
|
293
295
|
const url = resolveOutboundMediaUrl(item);
|
|
294
|
-
return url ? `[
|
|
296
|
+
return url ? `[${t(locale, 'video')}](${url})` : '';
|
|
295
297
|
}
|
|
296
298
|
case 'audio': {
|
|
297
299
|
const url = resolveOutboundMediaUrl(item);
|
|
298
|
-
return url ? `[
|
|
300
|
+
return url ? `[${t(locale, 'audio')}](${url})` : '';
|
|
299
301
|
}
|
|
300
302
|
case 'file': {
|
|
301
303
|
const url = resolveOutboundMediaUrl(item);
|
|
302
|
-
return url ? `[
|
|
304
|
+
return url ? `[${t(locale, 'file', { name: String(data.name || t(locale, 'unnamed')) })}](${url})` : '';
|
|
303
305
|
}
|
|
304
306
|
case 'bold':
|
|
305
307
|
return `**${String(data.text ?? '')}**`;
|