@lansenger/openclaw-channel-lansenger 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +130 -0
  2. package/dist/index.d.ts +9 -0
  3. package/dist/index.js +1 -0
  4. package/dist/index.openclaw.d.ts +9 -0
  5. package/dist/index.openclaw.js +1 -0
  6. package/dist/src/lansenger-core/agents/binding-manager.d.ts +53 -0
  7. package/dist/src/lansenger-core/agents/binding-manager.js +1 -0
  8. package/dist/src/lansenger-core/config/config-loader.d.ts +17 -0
  9. package/dist/src/lansenger-core/config/config-loader.js +1 -0
  10. package/dist/src/lansenger-core/config/config.d.ts +101 -0
  11. package/dist/src/lansenger-core/config/config.js +1 -0
  12. package/dist/src/lansenger-core/config/index.d.ts +5 -0
  13. package/dist/src/lansenger-core/config/index.js +1 -0
  14. package/dist/src/lansenger-core/domain/lansenger-domain.d.ts +40 -0
  15. package/dist/src/lansenger-core/domain/lansenger-domain.js +1 -0
  16. package/dist/src/lansenger-core/index.d.ts +15 -0
  17. package/dist/src/lansenger-core/index.js +1 -0
  18. package/dist/src/lansenger-core/middleware/index.d.ts +22 -0
  19. package/dist/src/lansenger-core/middleware/index.js +1 -0
  20. package/dist/src/lansenger-core/middleware/outbound-message-handler.d.ts +8 -0
  21. package/dist/src/lansenger-core/middleware/outbound-message-handler.js +1 -0
  22. package/dist/src/lansenger-core/middleware/pairing-middleware.d.ts +5 -0
  23. package/dist/src/lansenger-core/middleware/pairing-middleware.js +1 -0
  24. package/dist/src/lansenger-core/middleware/special-message-handler.d.ts +9 -0
  25. package/dist/src/lansenger-core/middleware/special-message-handler.js +1 -0
  26. package/dist/src/lansenger-core/middleware/standard-message-handler.d.ts +10 -0
  27. package/dist/src/lansenger-core/middleware/standard-message-handler.js +1 -0
  28. package/dist/src/lansenger-core/pairing/pairing-manager.d.ts +22 -0
  29. package/dist/src/lansenger-core/pairing/pairing-manager.js +1 -0
  30. package/dist/src/lansenger-core/pairing/storage.d.ts +20 -0
  31. package/dist/src/lansenger-core/pairing/storage.js +1 -0
  32. package/dist/src/lansenger-core/processor/event-classifier.d.ts +42 -0
  33. package/dist/src/lansenger-core/processor/event-classifier.js +1 -0
  34. package/dist/src/lansenger-core/processor/index.d.ts +7 -0
  35. package/dist/src/lansenger-core/processor/index.js +1 -0
  36. package/dist/src/lansenger-core/processor/lansenger-processor.d.ts +35 -0
  37. package/dist/src/lansenger-core/processor/lansenger-processor.js +1 -0
  38. package/dist/src/lansenger-core/processor/message-converter.d.ts +78 -0
  39. package/dist/src/lansenger-core/processor/message-converter.js +1 -0
  40. package/dist/src/lansenger-core/processor/message-processor.d.ts +14 -0
  41. package/dist/src/lansenger-core/processor/message-processor.js +1 -0
  42. package/dist/src/lansenger-core/processor/openclaw-processor.d.ts +7 -0
  43. package/dist/src/lansenger-core/processor/openclaw-processor.js +1 -0
  44. package/dist/src/lansenger-core/receive/index.d.ts +5 -0
  45. package/dist/src/lansenger-core/receive/index.js +1 -0
  46. package/dist/src/lansenger-core/receive/receive.d.ts +74 -0
  47. package/dist/src/lansenger-core/receive/receive.js +1 -0
  48. package/dist/src/lansenger-core/receive/websocket.d.ts +131 -0
  49. package/dist/src/lansenger-core/receive/websocket.js +1 -0
  50. package/dist/src/lansenger-core/send/card.d.ts +77 -0
  51. package/dist/src/lansenger-core/send/card.js +1 -0
  52. package/dist/src/lansenger-core/send/group.d.ts +24 -0
  53. package/dist/src/lansenger-core/send/group.js +1 -0
  54. package/dist/src/lansenger-core/send/index.d.ts +8 -0
  55. package/dist/src/lansenger-core/send/index.js +1 -0
  56. package/dist/src/lansenger-core/send/media.d.ts +39 -0
  57. package/dist/src/lansenger-core/send/media.js +1 -0
  58. package/dist/src/lansenger-core/send/send.d.ts +179 -0
  59. package/dist/src/lansenger-core/send/send.js +1 -0
  60. package/dist/src/lansenger-core/send/text.d.ts +29 -0
  61. package/dist/src/lansenger-core/send/text.js +1 -0
  62. package/dist/src/lansenger-core/services/index.d.ts +4 -0
  63. package/dist/src/lansenger-core/services/index.js +1 -0
  64. package/dist/src/lansenger-core/services/lansenger-api-service.d.ts +145 -0
  65. package/dist/src/lansenger-core/services/lansenger-api-service.js +1 -0
  66. package/dist/src/lansenger-core/skills/calendar.d.ts +214 -0
  67. package/dist/src/lansenger-core/skills/calendar.js +1 -0
  68. package/dist/src/lansenger-core/skills/index.d.ts +33 -0
  69. package/dist/src/lansenger-core/skills/index.js +1 -0
  70. package/dist/src/lansenger-core/skills/meeting.d.ts +241 -0
  71. package/dist/src/lansenger-core/skills/meeting.js +1 -0
  72. package/dist/src/lansenger-core/skills/message.d.ts +110 -0
  73. package/dist/src/lansenger-core/skills/message.js +1 -0
  74. package/dist/src/lansenger-core/types/index.d.ts +48 -0
  75. package/dist/src/lansenger-core/types/index.js +1 -0
  76. package/dist/src/lansenger-core/types.d.ts +184 -0
  77. package/dist/src/lansenger-core/types.js +1 -0
  78. package/dist/src/lansenger-core/utils/dedup.d.ts +7 -0
  79. package/dist/src/lansenger-core/utils/dedup.js +1 -0
  80. package/dist/src/lansenger-core/utils/env.d.ts +9 -0
  81. package/dist/src/lansenger-core/utils/env.js +1 -0
  82. package/dist/src/lansenger-core/utils/error-handling.d.ts +162 -0
  83. package/dist/src/lansenger-core/utils/error-handling.js +1 -0
  84. package/dist/src/lansenger-core/utils/file-system.d.ts +24 -0
  85. package/dist/src/lansenger-core/utils/file-system.js +1 -0
  86. package/dist/src/lansenger-core/utils/group-filter.d.ts +14 -0
  87. package/dist/src/lansenger-core/utils/group-filter.js +1 -0
  88. package/dist/src/lansenger-core/utils/index.d.ts +12 -0
  89. package/dist/src/lansenger-core/utils/index.js +1 -0
  90. package/dist/src/lansenger-core/utils/media-tags.d.ts +20 -0
  91. package/dist/src/lansenger-core/utils/media-tags.js +1 -0
  92. package/dist/src/lansenger-core/utils/media.d.ts +19 -0
  93. package/dist/src/lansenger-core/utils/media.js +1 -0
  94. package/dist/src/lansenger-core/utils/pairing-session.d.ts +44 -0
  95. package/dist/src/lansenger-core/utils/pairing-session.js +1 -0
  96. package/dist/src/lansenger-core/utils/probe.d.ts +15 -0
  97. package/dist/src/lansenger-core/utils/probe.js +1 -0
  98. package/dist/src/lansenger-core/utils/staff-cache.d.ts +53 -0
  99. package/dist/src/lansenger-core/utils/staff-cache.js +1 -0
  100. package/dist/src/lansenger-core/utils/staff-info.d.ts +12 -0
  101. package/dist/src/lansenger-core/utils/staff-info.js +1 -0
  102. package/dist/src/lansenger-core/utils/token.d.ts +47 -0
  103. package/dist/src/lansenger-core/utils/token.js +1 -0
  104. package/dist/src/openclaw-adapter/accounts.d.ts +21 -0
  105. package/dist/src/openclaw-adapter/accounts.js +1 -0
  106. package/dist/src/openclaw-adapter/adapter.d.ts +36 -0
  107. package/dist/src/openclaw-adapter/adapter.js +1 -0
  108. package/dist/src/openclaw-adapter/channel.d.ts +8 -0
  109. package/dist/src/openclaw-adapter/channel.js +1 -0
  110. package/dist/src/openclaw-adapter/channels/config.d.ts +37 -0
  111. package/dist/src/openclaw-adapter/channels/config.js +1 -0
  112. package/dist/src/openclaw-adapter/index.d.ts +9 -0
  113. package/dist/src/openclaw-adapter/index.js +1 -0
  114. package/dist/src/openclaw-adapter/onboarding.d.ts +56 -0
  115. package/dist/src/openclaw-adapter/onboarding.js +1 -0
  116. package/dist/src/openclaw-adapter/openclaw-processor.d.ts +44 -0
  117. package/dist/src/openclaw-adapter/openclaw-processor.js +1 -0
  118. package/dist/src/openclaw-adapter/runtime-store.d.ts +16 -0
  119. package/dist/src/openclaw-adapter/runtime-store.js +1 -0
  120. package/dist/src/openclaw-adapter/runtime.d.ts +5 -0
  121. package/dist/src/openclaw-adapter/runtime.js +1 -0
  122. package/dist/src/openclaw-adapter/sdk.d.ts +60 -0
  123. package/dist/src/openclaw-adapter/sdk.js +1 -0
  124. package/dist/src/openclaw-adapter/status-issues.d.ts +19 -0
  125. package/dist/src/openclaw-adapter/status-issues.js +1 -0
  126. package/dist/src/openclaw-adapter/utils/message-utils.d.ts +16 -0
  127. package/dist/src/openclaw-adapter/utils/message-utils.js +1 -0
  128. package/dist/src/openclaw-adapter/utils/outbound-utils.d.ts +78 -0
  129. package/dist/src/openclaw-adapter/utils/outbound-utils.js +1 -0
  130. package/dist/src/openclaw-adapter/utils/status-utils.d.ts +68 -0
  131. package/dist/src/openclaw-adapter/utils/status-utils.js +1 -0
  132. package/dist/src/openclaw-adapter/utils/version-detector.d.ts +34 -0
  133. package/dist/src/openclaw-adapter/utils/version-detector.js +1 -0
  134. package/openclaw.plugin.json +223 -0
  135. package/package.json +98 -0
package/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # OpenClaw Lanxin Channel Plugin
2
+
3
+ ## 项目简介
4
+
5
+ OpenClaw Lanxin Channel Plugin 是 OpenClaw 平台的蓝信渠道插件,用于实现 OpenClaw 与蓝信消息平台的集成。该插件支持:
6
+
7
+ - 接收蓝信消息并转发到 OpenClaw
8
+ - 发送消息从 OpenClaw 到蓝信
9
+ - 支持文本、图片、文件等多种消息类型
10
+ - 支持蓝信机器人的各种消息格式
11
+ - 提供配对码机制,确保消息安全
12
+
13
+ ## 功能特性
14
+
15
+ ### 安全机制
16
+ - 配对码验证,确保只有授权用户可以使用
17
+ - 支持配置允许发送者列表
18
+ - 群聊支持@机器人触发机制
19
+
20
+ ### 消息支持
21
+ - 文本消息(支持 Markdown 格式)
22
+ - 图片消息
23
+ - 文件消息
24
+ - 卡片消息(linkCard、appCard 等)
25
+
26
+ ### 连接方式
27
+ - WebSocket 长连接
28
+ - 支持蓝信开放平台 API
29
+
30
+ ## 安装与配置
31
+
32
+ ### 安装插件
33
+
34
+ ```bash
35
+ openclaw plugins install @lansenger/openclaw-lanxin
36
+ ```
37
+
38
+ 安装成功后会显示:`Installed plugin: openclaw-lanxin`
39
+
40
+ ### 初始化配置
41
+
42
+ ```bash
43
+ openclaw channels add --channel lanxin --token "{AppID}:{App Secret}:{domain}"
44
+ ```
45
+
46
+ 其中:
47
+ - `{AppID}`:蓝信应用的 App ID
48
+ - `{App Secret}`:蓝信应用的 App Secret
49
+ - `{domain}`:蓝信开放平台 API 网关地址
50
+
51
+ ### 配对码机制
52
+
53
+ 首次会话时,系统会要求用户输入配对码。用户输入配对码后,插件会验证配对码并授权用户访问。
54
+
55
+ - 配对码有效期为1小时
56
+ - 每个用户在1小时内只会生成一个配对码
57
+ - 配对码用于在 OpenClaw 中授权用户访问
58
+
59
+ ## 蓝信应用配置
60
+
61
+ 1. **创建应用**:在蓝信PC客户端(version>=9.5.50)-个人机器人-创建机器人
62
+ 2. **获取凭据**:从创建结果页面,获取 App ID 和 App Secret并配置到openclaw
63
+
64
+ ## 使用指南
65
+
66
+ ### 基本使用
67
+
68
+ 1. **发送文本消息**:直接在聊天中输入消息,机器人会自动处理
69
+ 2. **使用 Markdown**:直接使用 Markdown 语法,插件会自动处理
70
+
71
+
72
+ ### 消息格式
73
+
74
+ #### Markdown 格式
75
+
76
+ 蓝信支持 Markdown 格式。
77
+
78
+ #### 卡片消息
79
+
80
+ 支持 linkCard、appCard 等卡片消息格式,可根据需要使用不同的卡片类型。
81
+
82
+ ## 常见问题
83
+
84
+ ### 配对码问题
85
+ - 配对码有效期为1小时
86
+ - 每个用户在1小时内只会生成一个配对码
87
+ - 配对码用于在 OpenClaw 中授权用户访问
88
+
89
+ ### 消息类型支持
90
+ - 部分消息类型可能需要蓝信应用具备相应权限
91
+ - 大文件可能会受到蓝信平台的大小限制(单文件不超过 2MB)
92
+
93
+ ### 错误处理
94
+ - 查看 OpenClaw 日志了解详细错误信息
95
+ - 检查蓝信应用配置是否正确
96
+ - 确保网络连接正常
97
+
98
+ ## 版本历史
99
+
100
+ ### 0.0.6
101
+ - 优化代码质量和架构
102
+ - 完善架构设计文档
103
+ - 优化日志系统
104
+ - 修复 UI 配置问题
105
+
106
+ ### 0.0.4
107
+ - 添加 Markdown 消息支持
108
+ - 优化媒体文件处理
109
+ - 修复构建错误
110
+
111
+ ### 0.0.3
112
+ - 实现配对码机制
113
+ - 支持群聊消息
114
+ - 优化错误处理
115
+
116
+ ### 0.0.2
117
+ - 完善消息类型支持
118
+ - 优化配置管理
119
+
120
+ ### 0.0.1
121
+ - 初始版本
122
+ - 基本消息收发功能
123
+
124
+ ## 贡献
125
+
126
+ 欢迎提交 Issue 和 Pull Request 来改进这个项目。
127
+
128
+ ## 许可证
129
+
130
+ MIT License
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Lansenger (蓝信) channel plugin for Clawdbot/OpenClaw.
3
+ *
4
+ * Connects Lansenger bots via WebSocket long-connection (no public server required).
5
+ *
6
+ * Supports both OpenClaw version < 2026.3.23 and >= 2026.3.23
7
+ */
8
+ declare const plugin: any;
9
+ export default plugin;
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{openClawAdapter as e}from"./src/openclaw-adapter/adapter";import{emptyPluginConfigSchema as n}from"./src/openclaw-adapter/sdk";import{lansengerDock as r,lansengerPlugin as a}from"./src/openclaw-adapter/channel";import{setLansengerRuntime as t}from"./src/openclaw-adapter/runtime";const i={id:"openclaw-channel-lansenger",name:"Lansenger",description:"Lansenger (蓝信) channel plugin — WebSocket long-connection bot",configSchema:n(),register(n){e.init(n.runtime),t(n.runtime),e.isUsingNewSdk()?n.registerChannel(a):n.registerChannel({plugin:a,dock:r})},plugin:a,setRuntime:t,registerCliMetadata(e){e.registerCli(({program:e})=>{e.command("Lansenger").description("Lansenger channel management")},{descriptors:[{name:"Lansenger",description:"Lansenger channel management",hasSubcommands:!1}]})},registerFull(e){}},o=e.createPluginEntry(i);export default o;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Lansenger (蓝信) channel plugin for Clawdbot/OpenClaw.
3
+ *
4
+ * Connects Lansenger bots via WebSocket long-connection (no public server required).
5
+ *
6
+ * Supports both OpenClaw version < 2026.3.23 and >= 2026.3.23
7
+ */
8
+ declare const plugin: any;
9
+ export default plugin;
@@ -0,0 +1 @@
1
+ import{openClawAdapter as e}from"./src/openclaw-adapter/adapter";import{emptyPluginConfigSchema as n}from"./src/openclaw-adapter/sdk";import{lansengerDock as r,lansengerPlugin as a}from"./src/openclaw-adapter/channel";import{setLansengerRuntime as t}from"./src/openclaw-adapter/runtime";const i={id:"openclaw-channel-lansenger",name:"Lansenger",description:"Lansenger (蓝信) channel plugin — WebSocket long-connection bot",configSchema:n(),register(n){e.init(n.runtime),t(n.runtime),e.isUsingNewSdk()?n.registerChannel(a):n.registerChannel({plugin:a,dock:r})},plugin:a,setRuntime:t,registerCliMetadata(e){e.registerCli(({program:e})=>{e.command("Lansenger").description("Lansenger channel management")},{descriptors:[{name:"Lansenger",description:"Lansenger channel management",hasSubcommands:!1}]})},registerFull(e){}},o=e.createPluginEntry(i);export default o;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Binding manager for Lanxin bots and OpenClaw agents
3
+ */
4
+ /**
5
+ * Bot-Agent binding interface
6
+ */
7
+ export interface BotAgentBinding {
8
+ botId: string;
9
+ agentId: string;
10
+ lastUpdated: string;
11
+ }
12
+ /**
13
+ * Binding manager class
14
+ */
15
+ export declare class BindingManager {
16
+ private bindings;
17
+ private storagePath;
18
+ constructor();
19
+ /**
20
+ * Get storage file path
21
+ */
22
+ private getStorageFilePath;
23
+ /**
24
+ * Load bindings from storage
25
+ */
26
+ private loadBindings;
27
+ /**
28
+ * Save bindings to storage
29
+ */
30
+ private saveBindings;
31
+ /**
32
+ * Bind a bot to an agent
33
+ */
34
+ bindBotToAgent(botId: string, agentId: string): void;
35
+ /**
36
+ * Get agent ID for a bot
37
+ */
38
+ getBotAgent(botId: string): string;
39
+ /**
40
+ * Get all bindings
41
+ */
42
+ getAllBindings(): BotAgentBinding[];
43
+ /**
44
+ * Remove a binding
45
+ */
46
+ removeBinding(botId: string): void;
47
+ /**
48
+ * Check if a bot has a binding
49
+ */
50
+ hasBinding(botId: string): boolean;
51
+ }
52
+ export declare function createBindingManager(): BindingManager;
53
+ export declare function getBindingManager(): BindingManager;
@@ -0,0 +1 @@
1
+ import n from"fs";import i from"path";import{logger as t}from"../index.js";import{tryGetLansengerRuntime as e}from"../../openclaw-adapter/runtime-store.js";export class BindingManager{bindings=[];storagePath;constructor(){this.storagePath=this.getStorageFilePath(),this.loadBindings()}getStorageFilePath(){const s=e();let g;if(s&&s.state){const n=s.state.resolveStateDir();g=i.join(n,"extensions","openclaw-channel-lansenger"),t.info("Using runtime state directory for binding storage:",{stateDir:n})}else g=i.join("extensions","openclaw-channel-lansenger"),t.info("Using relative path for binding storage (runtime not available)");return n.existsSync(g)||n.mkdirSync(g,{recursive:!0}),i.join(g,"agent-bindings.json")}loadBindings(){try{if(n.existsSync(this.storagePath)){const i=n.readFileSync(this.storagePath,"utf8");this.bindings=JSON.parse(i),t.info(`Loaded ${this.bindings.length} bot-agent bindings`)}else t.info("No binding storage file found, initializing empty bindings"),this.bindings=[]}catch(n){t.error("Error loading bindings:",n),this.bindings=[]}}saveBindings(){try{n.writeFileSync(this.storagePath,JSON.stringify(this.bindings,null,2)),t.info(`Saved ${this.bindings.length} bot-agent bindings`)}catch(n){t.error("Error saving bindings:",n)}}bindBotToAgent(n,i){const e=this.bindings.findIndex(i=>i.botId===n);e>=0?(this.bindings[e]={botId:n,agentId:i,lastUpdated:(new Date).toISOString()},t.info(`Updated binding: ${n} -> ${i}`)):(this.bindings.push({botId:n,agentId:i,lastUpdated:(new Date).toISOString()}),t.info(`Added binding: ${n} -> ${i}`)),this.saveBindings()}getBotAgent(n){const i=this.bindings.find(i=>i.botId===n);return i?i.agentId:"default"}getAllBindings(){return[...this.bindings]}removeBinding(n){const i=this.bindings.length;this.bindings=this.bindings.filter(i=>i.botId!==n),this.bindings.length<i&&(t.info(`Removed binding for bot: ${n}`),this.saveBindings())}hasBinding(n){return this.bindings.some(i=>i.botId===n)}}let s=null;export function createBindingManager(){return s||(s=new BindingManager),s}export function getBindingManager(){return s||(s=new BindingManager),s}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Configuration loader for Lanxin plugin.
3
+ * Supports OpenClaw versions >= 2026.3.23
4
+ */
5
+ import type { LansengerAccountConfig } from "../types.js";
6
+ /**
7
+ * Load configuration using runtime API.
8
+ * @param runtime - The runtime object
9
+ * @returns The loaded configuration
10
+ */
11
+ export declare function loadConfig(runtime: any): LansengerAccountConfig;
12
+ /**
13
+ * Update configuration using runtime API.
14
+ * @param runtime - The runtime object
15
+ * @param config - The configuration to update
16
+ */
17
+ export declare function updateConfig(runtime: any, config: LansengerAccountConfig): void;
@@ -0,0 +1 @@
1
+ export function loadConfig(n){try{const o=n.config.loadConfig();return o.channels?.lanxin||{}}catch(n){return{}}}export function updateConfig(n,o){try{const c=n.config.loadConfig(),i={...c,channels:{...c.channels,lanxin:o}};n.config.writeConfigFile(i)}catch(n){}}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Configuration management for Lanxin channel plugin.
3
+ * Centralizes all configuration-related functionality and defaults.
4
+ */
5
+ import type { LansengerAccountConfig, LansengerBotType } from "../types.js";
6
+ /**
7
+ * Default configuration values for Lanxin channel plugin.
8
+ */
9
+ export declare const DEFAULT_CONFIG: {
10
+ botType: LansengerBotType;
11
+ webhookPort: number;
12
+ webhookPath: string;
13
+ apiGatewayUrl: string;
14
+ dmPolicy: "pairing";
15
+ allowFrom: string[];
16
+ };
17
+ /**
18
+ * API endpoints configuration.
19
+ */
20
+ export declare const API_ENDPOINTS: {
21
+ auth: {
22
+ tenantAccessToken: string;
23
+ appToken: string;
24
+ };
25
+ smartBot: {
26
+ privateMessage: string;
27
+ groupMessage: string;
28
+ groupsList: string;
29
+ uploadMedia: string;
30
+ };
31
+ webhookBot: {
32
+ message: string;
33
+ };
34
+ calendar: {
35
+ createEvent: string;
36
+ getEvent: string;
37
+ updateEvent: string;
38
+ deleteEvent: string;
39
+ listEvents: string;
40
+ };
41
+ meeting: {
42
+ createMeeting: string;
43
+ getMeeting: string;
44
+ updateMeeting: string;
45
+ deleteMeeting: string;
46
+ listMeetings: string;
47
+ startMeeting: string;
48
+ endMeeting: string;
49
+ };
50
+ };
51
+ /**
52
+ * Build a complete API URL from base URL and endpoint.
53
+ * @param baseUrl - The base API URL.
54
+ * @param endpoint - The API endpoint.
55
+ * @param params - Optional parameters to replace in the endpoint.
56
+ * @returns The complete API URL.
57
+ */
58
+ export declare function buildApiUrl(baseUrl: string, endpoint: string, ...params: string[]): string;
59
+ /**
60
+ * Get the WebSocket gateway URL from account config or use API gateway URL as default.
61
+ * @param config - The account config.
62
+ * @returns The WebSocket gateway URL.
63
+ */
64
+ export declare function getWssGatewayUrl(config: LansengerAccountConfig): string;
65
+ /**
66
+ * Get the API gateway URL from account config or use default.
67
+ * @param config - The account config.
68
+ * @returns The API gateway URL.
69
+ */
70
+ export declare function getApiGatewayUrl(config: LansengerAccountConfig): string;
71
+ /**
72
+ * Get the bot type from account config or use default.
73
+ * @param config - The account config.
74
+ * @returns The bot type.
75
+ */
76
+ export declare function getBotType(config: LansengerAccountConfig): LansengerBotType;
77
+ /**
78
+ * Get the webhook port from account config or use default.
79
+ * @param config - The account config.
80
+ * @returns The webhook port.
81
+ */
82
+ export declare function getWebhookPort(config: LansengerAccountConfig): number;
83
+ /**
84
+ * Get the webhook path from account config or use default.
85
+ * @param config - The account config.
86
+ * @returns The webhook path.
87
+ */
88
+ export declare function getWebhookPath(config: LansengerAccountConfig): string;
89
+ /**
90
+ * Get the DM policy from account config or use default.
91
+ * @param config - The account config.
92
+ * @returns The DM policy.
93
+ */
94
+ export declare function getDmPolicy(config: LansengerAccountConfig): "pairing" | "allowlist" | "open" | "disabled";
95
+ /**
96
+ * Get the allowFrom list from account config or use default.
97
+ * @param config - The account config.
98
+ * @returns The allowFrom list.
99
+ */
100
+ export declare function getAllowFrom(config: LansengerAccountConfig): string[];
101
+ export { loadConfig, updateConfig } from "./config-loader.js";
@@ -0,0 +1 @@
1
+ export const DEFAULT_CONFIG={botType:"smart",webhookPort:3e3,webhookPath:"/lanxin/events",apiGatewayUrl:"https://open.e.lanxin.cn/open/apigw",dmPolicy:"pairing",allowFrom:[]};export const API_ENDPOINTS={auth:{tenantAccessToken:"/auth/v3/tenant_access_token/internal",appToken:"/v1/apptoken/create"},smartBot:{privateMessage:"/v1/bot/messages/create",groupMessage:"/v1/messages/group/create",groupsList:"/v2/groups/fetch",uploadMedia:"/v1/medias/create"},webhookBot:{message:"/bot/v1/hook/messages/create"},calendar:{createEvent:"/v1/calendar/events/create",getEvent:"/v1/calendar/events/%s",updateEvent:"/v1/calendar/events/%s",deleteEvent:"/v1/calendar/events/%s",listEvents:"/v1/calendar/events/list"},meeting:{createMeeting:"/v1/meetings/create",getMeeting:"/v1/meetings/%s",updateMeeting:"/v1/meetings/%s",deleteMeeting:"/v1/meetings/%s",listMeetings:"/v1/meetings/list",startMeeting:"/v1/meetings/%s/start",endMeeting:"/v1/meetings/%s/end"}};export function buildApiUrl(e,t,...a){let n=t;return a.length>0&&(n=t.replace(/%s/g,()=>a.shift()||"")),`${e}${n}`}export function getWssGatewayUrl(e){let t=e.apiGatewayWssUrl||e.apiGatewayUrl||DEFAULT_CONFIG.apiGatewayUrl;return t=t.replace(/^`|`$/g,""),t.replace(/^http/,"ws")}export function getApiGatewayUrl(e){return(e.apiGatewayUrl||DEFAULT_CONFIG.apiGatewayUrl).replace(/^`|`$/g,"")}export function getBotType(e){return e.botType||DEFAULT_CONFIG.botType}export function getWebhookPort(e){return e.webhookPort||DEFAULT_CONFIG.webhookPort}export function getWebhookPath(e){return e.webhookPath||DEFAULT_CONFIG.webhookPath}export function getDmPolicy(e){return e.dmPolicy||DEFAULT_CONFIG.dmPolicy}export function getAllowFrom(e){const t=e.allowFrom;return t?t.map(e=>String(e)):DEFAULT_CONFIG.allowFrom}export{loadConfig,updateConfig}from"./config-loader.js";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Lanxin configuration utilities.
3
+ */
4
+ export * from './config.js';
5
+ export * from './config-loader.js';
@@ -0,0 +1 @@
1
+ export*from"./config.js";export*from"./config-loader.js";
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Lansenger API domain utilities.
3
+ */
4
+ import type { LansengerAccountConfig } from "../types.js";
5
+ /**
6
+ * Get the base API URL for Lansenger.
7
+ * @param apiGatewayUrl - Optional custom API gateway URL.
8
+ * @returns Base API URL.
9
+ */
10
+ export declare function getLansengerApiBase(apiGatewayUrl?: string): string;
11
+ /**
12
+ * Get the base API URL for Lansenger from account config.
13
+ * @param config - The account config.
14
+ * @returns Base API URL.
15
+ */
16
+ export declare function getLansengerApiBaseFromConfig(config: LansengerAccountConfig): string;
17
+ /**
18
+ * Get the API URL for smart bot operations.
19
+ * @param apiGatewayUrl - Optional custom API gateway URL.
20
+ * @returns Smart bot API URL.
21
+ */
22
+ export declare function getSmartBotApiUrl(apiGatewayUrl?: string): string;
23
+ /**
24
+ * Get the API URL for webhook bot operations.
25
+ * @param apiGatewayUrl - Optional custom API gateway URL.
26
+ * @returns Webhook bot API URL.
27
+ */
28
+ export declare function getWebhookBotApiUrl(apiGatewayUrl?: string): string;
29
+ /**
30
+ * Get the API URL for smart bot operations from account config.
31
+ * @param config - The account config.
32
+ * @returns Smart bot API URL.
33
+ */
34
+ export declare function getSmartBotApiUrlFromConfig(config: LansengerAccountConfig): string;
35
+ /**
36
+ * Get the API URL for webhook bot operations from account config.
37
+ * @param config - The account config.
38
+ * @returns Webhook bot API URL.
39
+ */
40
+ export declare function getWebhookBotApiUrlFromConfig(config: LansengerAccountConfig): string;
@@ -0,0 +1 @@
1
+ import{getApiGatewayUrl as e}from"../config/index.js";export function getLansengerApiBase(r){return r||e({})}export function getLansengerApiBaseFromConfig(r){return e(r)}export function getSmartBotApiUrl(e){return getLansengerApiBase(e)}export function getWebhookBotApiUrl(e){return getLansengerApiBase(e)}export function getSmartBotApiUrlFromConfig(e){return getLansengerApiBaseFromConfig(e)}export function getWebhookBotApiUrlFromConfig(e){return getLansengerApiBaseFromConfig(e)}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 蓝信核心功能 - 处理与蓝信开放平台的所有交互。
3
+ */
4
+ export * from './config/index.js';
5
+ export * from './receive/index.js';
6
+ export * from './send/index.js';
7
+ export * from './skills/index.js';
8
+ export * from './domain/lansenger-domain.js';
9
+ export * from './processor/index.js';
10
+ export * from './middleware/index.js';
11
+ export * from './pairing/pairing-manager.js';
12
+ export * from './services/index.js';
13
+ export * from './agents/binding-manager.js';
14
+ export * from './utils/index.js';
15
+ export type { LansengerConnectionMode, LansengerBotType, LansengerAccountConfig, LansengerConfig, LansengerTokenSource, ResolvedLansengerAccount, LansengerSendResult, LansengerProbeResult, LansengerMediaType, LansengerMsgType, SmartBotPrivateMessageRequest, SmartBotGroupMessageRequest, WebhookBotMessageRequest } from './types.js';
@@ -0,0 +1 @@
1
+ export*from"./config/index.js";export*from"./receive/index.js";export*from"./send/index.js";export*from"./skills/index.js";export*from"./domain/lansenger-domain.js";export*from"./processor/index.js";export*from"./middleware/index.js";export*from"./pairing/pairing-manager.js";export*from"./services/index.js";export*from"./agents/binding-manager.js";export*from"./utils/index.js";
@@ -0,0 +1,22 @@
1
+ import { PairingManager } from '../pairing/pairing-manager';
2
+ import { OutboundMessageHandler, outboundMessageHandler } from './outbound-message-handler';
3
+ import { StandardMessageHandler, standardMessageHandler } from './standard-message-handler';
4
+ import { PairingMiddleware, pairingMiddleware } from './pairing-middleware';
5
+ import { SpecialMessageHandler, specialMessageHandler } from './special-message-handler';
6
+ export interface MiddlewareContext {
7
+ message: any;
8
+ userId: string;
9
+ pairingManager?: PairingManager;
10
+ [key: string]: any;
11
+ }
12
+ export type MiddlewareFunction = (context: MiddlewareContext, next: () => Promise<void>) => Promise<void>;
13
+ export declare class MiddlewareManager {
14
+ private middlewares;
15
+ use(middleware: MiddlewareFunction): void;
16
+ run(context: MiddlewareContext): Promise<void>;
17
+ }
18
+ /**
19
+ * Create middleware manager instance
20
+ */
21
+ export declare function createMiddlewareManager(): MiddlewareManager;
22
+ export { OutboundMessageHandler, StandardMessageHandler, PairingMiddleware, SpecialMessageHandler, standardMessageHandler, pairingMiddleware, specialMessageHandler, outboundMessageHandler };
@@ -0,0 +1 @@
1
+ import{OutboundMessageHandler as e,outboundMessageHandler as a}from"./outbound-message-handler";import{StandardMessageHandler as r,standardMessageHandler as s}from"./standard-message-handler";import{PairingMiddleware as d,pairingMiddleware as i}from"./pairing-middleware";import{SpecialMessageHandler as t,specialMessageHandler as n}from"./special-message-handler";export class MiddlewareManager{middlewares=[];use(e){this.middlewares.push(e)}async run(e){let a=0;const r=async()=>{if(a<this.middlewares.length){const s=this.middlewares[a++];await s(e,r)}};await r()}}export function createMiddlewareManager(){return new MiddlewareManager}export{e as OutboundMessageHandler,r as StandardMessageHandler,d as PairingMiddleware,t as SpecialMessageHandler,s as standardMessageHandler,i as pairingMiddleware,n as specialMessageHandler,a as outboundMessageHandler};
@@ -0,0 +1,8 @@
1
+ import { MiddlewareFunction } from './index';
2
+ export declare class OutboundMessageHandler {
3
+ static create(): MiddlewareFunction;
4
+ }
5
+ /**
6
+ * Create outbound message handler instance
7
+ */
8
+ export declare const outboundMessageHandler: MiddlewareFunction;
@@ -0,0 +1 @@
1
+ import*as e from"fs";export class OutboundMessageHandler{static create(){return async(t,n)=>{const{openclawMessage:a,userId:s}=t;if(a)if("text"===a.type)t.lanxinMessage={type:"text",content:a.content,to:s,timestamp:a.timestamp};else if("image"===a.type){const n=a.content;if(e.existsSync(n)){const i=e.readFileSync(n,"base64");t.lanxinMessage={type:"image",content:i,filename:a.filename||"image.jpg",to:s,timestamp:a.timestamp}}}else if("file"===a.type){const n=a.content;if(e.existsSync(n)){const i=e.readFileSync(n,"base64");t.lanxinMessage={type:"file",content:i,filename:a.filename||"file.txt",to:s,timestamp:a.timestamp}}}else if("audio"===a.type){const n=a.content;if(e.existsSync(n)){const i=e.readFileSync(n,"base64");t.lanxinMessage={type:"audio",content:i,filename:a.filename||"audio.mp3",duration:a.duration||0,to:s,timestamp:a.timestamp}}}else if("video"===a.type){const n=a.content;if(e.existsSync(n)){const i=e.readFileSync(n,"base64");t.lanxinMessage={type:"video",content:i,filename:a.filename||"video.mp4",duration:a.duration||0,to:s,timestamp:a.timestamp}}}await n()}}}export const outboundMessageHandler=OutboundMessageHandler.create();
@@ -0,0 +1,5 @@
1
+ import { MiddlewareFunction } from './index';
2
+ export declare class PairingMiddleware {
3
+ static create(): MiddlewareFunction;
4
+ }
5
+ export declare const pairingMiddleware: MiddlewareFunction;
@@ -0,0 +1 @@
1
+ export class PairingMiddleware{static create(){return async(a,e)=>{await e()}}}export const pairingMiddleware=PairingMiddleware.create();
@@ -0,0 +1,9 @@
1
+ import { MiddlewareFunction } from './index';
2
+ export declare class SpecialMessageHandler {
3
+ private static commands;
4
+ static create(): MiddlewareFunction;
5
+ }
6
+ /**
7
+ * Create special message handler instance
8
+ */
9
+ export declare const specialMessageHandler: MiddlewareFunction;
@@ -0,0 +1 @@
1
+ import{getBotType as t,sendTextMessage as e,sendLinkCardMessage as n,sendAppCardMessage as s,sendOaCardMessage as a,sendAppArticlesMessage as i,sendSystemMessage as o,sendImageMessage as c,sendFileMessage as p,getBindingManager as l}from"../index";import r from"node:fs";import m from"node:path";import{fileURLToPath as d}from"node:url";const x=d(import.meta.url),y=m.dirname(x);export class SpecialMessageHandler{static commands={help:async t=>{t.response={type:"text",content:"蓝信 OpenClaw 插件支持以下命令:\n/lanxin send-all-message-types - 发送所有支持的消息类型\n/lanxin test-text - 测试文本消息\n/lanxin test-image - 测试图片消息\n/lanxin test-file - 测试文件消息\n/lanxin test-md - 测试Markdown消息\n/lanxin test-link-card - 测试链接卡片\n/lanxin test-app-card - 测试应用卡片\n/lanxin test-oa-card - 测试OA卡片\n/lanxin test-app-articles - 测试图文消息\n/lanxin test-system - 测试系统消息\n/lanxin agent - 查看当前机器人绑定的 Agent\n/lanxin agent-list - 查看所有机器人与 Agent 的绑定关系\n/lanxin help - 显示此帮助信息\n\n更多命令将在后续版本中添加。"}},"send-all-message-types":async c=>{const{userId:p,config:l}=c,r=t(l);await e(r,l,p,"这是文本消息"),await n(r,l,p,{title:"测试链接卡片",description:"这是一条测试链接卡片",link:"https://example.com",iconLink:"https://example.com/icon.png"}),await s(r,l,p,{bodyTitle:"测试应用卡片",bodyContent:"这是一条测试应用卡片",links:[{title:"查看详情",url:"https://example.com"}]}),await a(r,l,p,{title:"测试OA卡片",subTitle:"副标题",fields:[{key:"字段1",value:"值1"},{key:"字段2",value:"值2"}],link:"https://example.com"}),await i(r,l,p,[{title:"测试图文消息",description:"这是一条测试图文消息",imageUrl:"https://example.com/article-image.jpg",url:"https://example.com"}]),await o(r,l,p,{content:"这是一条测试系统消息"}),c.response={type:"text",content:"已发送所有支持的消息类型"}},"test-text":async n=>{const{userId:s,config:a}=n,i=t(a);await e(i,a,s,"这是一条测试文本消息"),n.response={type:"text",content:"已发送测试文本消息"}},"test-image":async n=>{const{userId:s,config:a}=n,i=t(a),o=m.join(y,"../../../assets/logo.png");r.existsSync(o)?(await c(i,a,s,o),n.response={type:"text",content:"已发送测试图片消息"}):(await e(i,a,s,"图片文件不存在:"+o),n.response={type:"text",content:"图片文件不存在"})},"test-file":async n=>{const{userId:s,config:a}=n,i=t(a),o=m.join(y,"../../../README.md");r.existsSync(o)?(await p(i,a,s,o),n.response={type:"text",content:"已发送测试文件消息"}):(await e(i,a,s,"文件不存在:"+o),n.response={type:"text",content:"文件不存在"})},"test-md":async n=>{const{userId:s,config:a}=n,i=t(a),o=m.join(y,"../../../README.md");if(r.existsSync(o)){const t=r.readFileSync(o,"utf8");await e(i,a,s,t,{hookToken:a.hookToken,isGroup:s.startsWith("oc_"),msgType:"formatText"}),n.response={type:"text",content:"已发送测试Markdown消息"}}else await e(i,a,s,"README.md文件不存在:"+o),n.response={type:"text",content:"README.md文件不存在"}},"test-link-card":async e=>{const{userId:s,config:a}=e,i=t(a);await n(i,a,s,{title:"测试链接卡片",description:"这是一条测试链接卡片",link:"https://example.com",iconLink:"https://example.com/icon.png"}),e.response={type:"text",content:"已发送测试链接卡片"}},"test-app-card":async e=>{const{userId:n,config:a}=e,i=t(a);await s(i,a,n,{bodyTitle:"测试应用卡片",bodyContent:"这是一条测试应用卡片",links:[{title:"查看详情",url:"https://example.com"}]}),e.response={type:"text",content:"已发送测试应用卡片"}},"test-oa-card":async e=>{const{userId:n,config:s}=e,i=t(s);await a(i,s,n,{title:"测试OA卡片",subTitle:"副标题",fields:[{key:"字段1",value:"值1"},{key:"字段2",value:"值2"}],link:"https://example.com"}),e.response={type:"text",content:"已发送测试OA卡片"}},"test-app-articles":async e=>{const{userId:n,config:s}=e,a=t(s);await i(a,s,n,[{title:"测试图文消息",description:"这是一条测试图文消息",imageUrl:"https://example.com/article-image.jpg",url:"https://example.com"}]),e.response={type:"text",content:"已发送测试图文消息"}},"test-system":async e=>{const{userId:n,config:s}=e,a=t(s);await o(a,s,n,{content:"这是一条测试系统消息"}),e.response={type:"text",content:"已发送测试系统消息"}},agent:async t=>{const{config:e}=t,n=l().getBotAgent(e.appId);t.response={type:"text",content:`当前机器人绑定的 Agent: ${n}`}},"agent-list":async t=>{const e=l().getAllBindings();if(0===e.length)t.response={type:"text",content:"暂无机器人与 Agent 的绑定关系"};else{const n=e.map(t=>`${t.botId} -> ${t.agentId}`).join("\n");t.response={type:"text",content:`机器人与 Agent 绑定关系:\n${n}`}}}};static create(){return async(t,e)=>{const{message:n}=t;if("text"===n.type&&n.content.startsWith("/lanxin ")){let s=n.content.substring(7).trim();const a={"帮助":"help","发送所有类型":"send-all-message-types","测试消息":"test-text","测试文本":"test-text","测试图片":"test-image","测试文件":"test-file","测试链接卡片":"test-link-card","测试应用卡片":"test-app-card","测试OA卡片":"test-oa-card","测试图文消息":"test-app-articles","测试系统消息":"test-system"};if(a[s]&&(s=a[s]),"配对"===s)return void await e();if(s.startsWith("配对 "))return void await e();const i=this.commands[s];i?await i(t):t.response={type:"text",content:`未知命令:${s}\n请使用 /lanxin help 查看可用命令。`}}else await e()}}}export const specialMessageHandler=SpecialMessageHandler.create();
@@ -0,0 +1,10 @@
1
+ import { MiddlewareFunction } from './index';
2
+ export declare class StandardMessageHandler {
3
+ private static processedMessages;
4
+ static create(): MiddlewareFunction;
5
+ private static downloadMedia;
6
+ }
7
+ /**
8
+ * Create standard message handler instance
9
+ */
10
+ export declare const standardMessageHandler: MiddlewareFunction;
@@ -0,0 +1 @@
1
+ import*as e from"fs";import*as t from"path";import*as a from"https";import{fileURLToPath as s}from"url";const i=s(import.meta.url),n=t.dirname(i);export class StandardMessageHandler{static processedMessages=new Set;static create(){return async(e,t)=>{const{message:a,userId:s}=e;if("message"===a.eventType){const t=a.messageId;if(this.processedMessages.has(t))return;if(this.processedMessages.add(t),"text"===a.messageType)e.openclawMessage={type:"text",content:a.content,from:s,timestamp:a.timestamp};else if("image"===a.messageType){const t=await this.downloadMedia(a.content,"images");e.openclawMessage={type:"image",content:t,filename:a.filename||"image.jpg",from:s,timestamp:a.timestamp}}else if("file"===a.messageType){const t=await this.downloadMedia(a.content,"files");e.openclawMessage={type:"file",content:t,filename:a.filename||"file.txt",from:s,timestamp:a.timestamp}}else if("audio"===a.messageType){const t=await this.downloadMedia(a.content,"audio");e.openclawMessage={type:"audio",content:t,filename:a.filename||"audio.mp3",duration:a.duration||0,from:s,timestamp:a.timestamp}}else if("video"===a.messageType){const t=await this.downloadMedia(a.content,"video");e.openclawMessage={type:"video",content:t,filename:a.filename||"video.mp4",duration:a.duration||0,from:s,timestamp:a.timestamp}}}await t()}}static async downloadMedia(s,i){const o=t.join(n,"../../../media",i);e.existsSync(o)||e.mkdirSync(o,{recursive:!0});const m=t.basename(s)||`${Date.now()}.bin`,r=t.join(o,m);return new Promise((t,i)=>{const n=e.createWriteStream(r);a.get(s,e=>{e.pipe(n),n.on("finish",()=>{n.close(),t(r)})}).on("error",t=>{e.unlink(r,()=>{}),i(t)})})}}export const standardMessageHandler=StandardMessageHandler.create();
@@ -0,0 +1,22 @@
1
+ interface PairingRequest {
2
+ code: string;
3
+ userId: string;
4
+ staffId: string;
5
+ createdAt: string;
6
+ }
7
+ export declare class PairingManager {
8
+ constructor();
9
+ generatePairingCode(): string;
10
+ getExistingPairingCode(identifier: string): string | null;
11
+ storePairingRequest(code: string, userId: string, staffId: string): void;
12
+ getPairingRequest(code: string): PairingRequest | null;
13
+ approveUser(staffId: string): void;
14
+ isUserApproved(staffId: string): boolean;
15
+ removePairingRequest(code: string): void;
16
+ approvePairingRequest(code: string): boolean;
17
+ getSessionByCode(code: string): {
18
+ staffId: string;
19
+ } | null;
20
+ }
21
+ export declare function createPairingManager(accountId?: string): PairingManager;
22
+ export {};
@@ -0,0 +1 @@
1
+ import{logger as e}from"../utils/error-handling.js";import{loadPairingData as r,savePairingData as i}from"./storage.js";export class PairingManager{constructor(){e.debug("Initialized PairingManager")}generatePairingCode(){const r="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";let i="";for(let e=0;e<8;e++)i+=r.charAt(Math.floor(36*Math.random()));return e.debug("Generated new pairing code",{code:i}),i}getExistingPairingCode(s){e.debug("Checking for existing pairing code",{identifier:s});const{pairingRequests:t,approvedUsers:d}=r();for(const r in t){const n=t[r];if(n.staffId===s||n.userId===s){const o=new Date(n.createdAt),a=((new Date).getTime()-o.getTime())/36e5;if(a<=1)return e.debug("Found existing valid pairing code",{identifier:s,code:r,diffInHours:a}),r;e.debug("Found existing but expired pairing code",{identifier:s,code:r,diffInHours:a}),delete t[r],i(t,d)}}return e.debug("No existing valid pairing code found",{identifier:s}),null}storePairingRequest(s,t,d){e.info("Storing pairing request",{code:s,userId:t,staffId:d});const{pairingRequests:n,approvedUsers:o}=r();e.info("Current pairingRequests before storing:",Object.keys(n)),n[s]={code:s,userId:t,staffId:d,createdAt:(new Date).toISOString()},e.info("Pairing request stored in memory:",n[s]),i(n,o),e.info("Pairing request stored successfully",{code:s,userId:t,staffId:d})}getPairingRequest(s){e.debug("Getting pairing request",{code:s});const{pairingRequests:t,approvedUsers:d}=r(),n=t[s];if(!n)return e.debug("No pairing request found",{code:s}),null;const o=new Date(n.createdAt),a=((new Date).getTime()-o.getTime())/36e5;return a>1?(e.debug("Pairing request expired",{code:s,diffInHours:a}),delete t[s],i(t,d),null):(e.debug("Found valid pairing request",{code:s,staffId:n.staffId}),n)}approveUser(s){e.debug("Approving user",{staffId:s});const{pairingRequests:t,approvedUsers:d}=r();d.includes(s)?e.debug("User already in approved list",{staffId:s}):(e.debug("Adding user to approved list",{staffId:s}),d.push(s),i(t,d),e.debug("User added to approved list successfully",{staffId:s,approvedUsers:d}))}isUserApproved(i){try{e.debug("Checking if user is approved",{staffId:i});const{approvedUsers:s}=r(),t=s.includes(i);return e.debug("User approval status",{staffId:i,isApproved:t,approvedUsers:s}),t}catch(r){return e.error("Error checking if user is approved",{error:r,staffId:i}),!1}}removePairingRequest(e){const{pairingRequests:s,approvedUsers:t}=r();delete s[e],i(s,t)}approvePairingRequest(r){e.debug("Approving pairing request",{code:r});const i=this.getPairingRequest(r);return i?(e.debug("Pairing request found, approving user",{code:r,staffId:i.staffId}),this.approveUser(i.staffId),this.removePairingRequest(r),e.debug("Pairing request approved successfully",{code:r,staffId:i.staffId}),!0):(e.debug("Pairing request not found or expired",{code:r}),!1)}getSessionByCode(r){e.debug("Getting session by code",{code:r});const i=this.getPairingRequest(r);return i?(e.debug("Found session for code",{code:r,staffId:i.staffId}),{staffId:i.staffId}):(e.debug("No session found for code",{code:r}),null)}}export function createPairingManager(e){return new PairingManager}
@@ -0,0 +1,20 @@
1
+ interface PairingData {
2
+ pairingRequests: Record<string, PairingRequest>;
3
+ approvedUsers: string[];
4
+ lastUpdated: string;
5
+ }
6
+ interface PairingRequest {
7
+ code: string;
8
+ userId: string;
9
+ staffId: string;
10
+ createdAt: string;
11
+ }
12
+ /**
13
+ * 从文件加载配对数据
14
+ */
15
+ export declare function loadPairingData(): PairingData;
16
+ /**
17
+ * 保存配对数据到文件
18
+ */
19
+ export declare function savePairingData(pairingRequests: Record<string, PairingRequest>, approvedUsers: string[]): void;
20
+ export {};
@@ -0,0 +1 @@
1
+ import{logger as t}from"../utils/error-handling.js";import{getStorageFilePath as a,readFile as e,writeFile as r,fileExists as i}from"../utils/file-system.js";export function loadPairingData(){try{const r=a();if(t.info("Loading pairing data from:",{filePath:r}),!i(r))return t.info("Pairing data file not found, returning empty data"),{pairingRequests:{},approvedUsers:[],lastUpdated:(new Date).toISOString()};const n=e(r),s=JSON.parse(n);return t.info("Loaded pairing data:",{pairingRequestsCount:Object.keys(s.pairingRequests).length,approvedUsersCount:s.approvedUsers.length,lastUpdated:s.lastUpdated}),s}catch(a){return t.error("Error loading pairing data:",a),{pairingRequests:{},approvedUsers:[],lastUpdated:(new Date).toISOString()}}}export function savePairingData(e,i){try{const n=a();t.info("Saving pairing data to:",{filePath:n}),t.info("Pairing data to save:",{pairingRequestsCount:Object.keys(e).length,approvedUsersCount:i.length});const s={pairingRequests:e,approvedUsers:i,lastUpdated:(new Date).toISOString()};r(n,JSON.stringify(s,null,2)),t.info("Saved pairing data to file successfully")}catch(a){t.error("Error saving pairing data:",a)}}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Event classifier for Lanxin channel plugin.
3
+ * Classifies and processes Lanxin subscription events based on event type.
4
+ */
5
+ import type { LanxinEvent, LanxinEventType } from "./message-converter.js";
6
+ /**
7
+ * Event handler interface
8
+ */
9
+ export interface EventHandler {
10
+ handle(event: LanxinEvent, accountId: string): Promise<any>;
11
+ }
12
+ /**
13
+ * Event classifier class
14
+ */
15
+ export declare class EventClassifier {
16
+ private handlers;
17
+ /**
18
+ * Register event handler
19
+ * @param eventType - Event type to handle
20
+ * @param handler - Event handler
21
+ */
22
+ registerHandler(eventType: LanxinEventType, handler: EventHandler): void;
23
+ /**
24
+ * Classify and process event
25
+ * @param event - Lanxin event
26
+ * @param accountId - Account ID
27
+ * @returns Process result
28
+ */
29
+ classifyAndProcess(event: LanxinEvent, accountId: string): Promise<any>;
30
+ /**
31
+ * Get registered event types
32
+ * @returns Registered event types
33
+ */
34
+ getRegisteredEventTypes(): LanxinEventType[];
35
+ /**
36
+ * Get handlers for event type
37
+ * @param eventType - Event type
38
+ * @returns Event handlers
39
+ */
40
+ getHandlers(eventType: LanxinEventType): EventHandler[];
41
+ }
42
+ export declare const eventClassifier: EventClassifier;
@@ -0,0 +1 @@
1
+ import{logger as e}from"../utils/error-handling.js";export class EventClassifier{handlers=new Map;registerHandler(e,r){this.handlers.has(e)||this.handlers.set(e,[]),this.handlers.get(e)?.push(r)}async classifyAndProcess(r,t){try{let s=r.eventType||r.type;!s&&r.data&&(s=r.data.eventType||r.data.type),e.info(`Classifying event type: ${s}`);const n=this.handlers.get(s);if(n&&n.length>0){return await Promise.all(n.map(e=>e.handle(r,t)))}return e.debug(`No handlers registered for event type: ${s}`),null}catch(t){return e.error("Error classifying and processing event",{error:t,event:r}),null}}getRegisteredEventTypes(){return Array.from(this.handlers.keys())}getHandlers(e){return this.handlers.get(e)||[]}}export const eventClassifier=new EventClassifier;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Processor module exports for Lansenger core functionality.
3
+ */
4
+ export * from './lansenger-processor.js';
5
+ export * from './message-processor.js';
6
+ export * from './message-converter.js';
7
+ export * from './event-classifier.js';
@@ -0,0 +1 @@
1
+ export*from"./lansenger-processor.js";export*from"./message-processor.js";export*from"./message-converter.js";export*from"./event-classifier.js";