@larksuiteoapi/node-sdk 1.61.1 → 1.62.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -81,7 +81,7 @@ const res = await client.im.message.create({
81
81
  ````
82
82
  > tips:
83
83
  > * If you want to debug an API, you can click the link in the comment to enter the API debugging platform for debugging:
84
- > ![](doc/debugger-tip.png)
84
+ > ![](docs/assets/debugger-tip.png)
85
85
  > * How to obtain the semantic call interface:[Click here](https://github.com/larksuite/node-sdk/issues/42)
86
86
 
87
87
  #### Create Client
@@ -246,7 +246,7 @@ client.im.message.create({
246
246
  }
247
247
  })
248
248
  ```
249
- ![](doc/msg-card.png)
249
+ ![](docs/assets/msg-card.png)
250
250
  There will be a problem: **If the content of the message card is relatively rich, the generated template json is relatively large, and there will be more content that needs to be filled with data, and manual maintenance is more cumbersome**. To solve this problem, The Open-Platform provides the ability of [Template Message](https://open.feishu.cn/document/tools-and-resources/message-card-builder#3e1f2c7c).When sending a message card, you only need to provide the template id and the data content of the template. The sdk encapsulates this ability in terms of calling, and the interface that supports message cards will synchronously add a ByCard calling method, only need to pass `template_id` and `template_variable`. The above call can be rewritten as:
251
251
  ```typescript
252
252
  client.im.message.createByCard({
@@ -281,7 +281,7 @@ client.im.message.create({
281
281
  }
282
282
  })
283
283
  ```
284
- ![](doc/msg-card.png)
284
+ ![](docs/assets/msg-card.png)
285
285
 
286
286
  #### Configure request options
287
287
  If you want to modify the parameters of the request during the API call, such as carrying some headers, custom tenantToken, etc., you can use the second parameter of the request method to modify:
@@ -386,7 +386,7 @@ server.listen(3000);
386
386
  | cache | Cache | Cache | No | - |
387
387
 
388
388
  > Note: Some events are v1.0 version and are no longer maintained. The SDK retains support for them. It is strongly recommended to use new versions of events that are consistent with their functions. Move the mouse to the corresponding event subscription function to see the relevant documents:
389
- ![](doc/deprecated.png)
389
+ ![](docs/assets/deprecated.png)
390
390
 
391
391
  #### Combined with express
392
392
  The SDK provides an adapter for experss to convert eventDispatcher into express middleware, which can be seamlessly combined with services written using express (*The use of bodyParser in the example is not necessary, but the community mostly uses it to format body data*):
@@ -587,6 +587,28 @@ wsClient.start({
587
587
  ```
588
588
 
589
589
 
590
+ ### Channel module
591
+
592
+ `Channel` is a high-level module built on top of `WSClient` / `Client` that bundles transport, message normalization, safety policy, outbound sending, streaming replies, media upload, and card interactions into a single abstraction. It is the recommended entry point for conversational bots (AI chat, streaming replies, interactive card buttons, etc.).
593
+
594
+ ```typescript
595
+ import { createLarkChannel } from '@larksuiteoapi/node-sdk';
596
+
597
+ const channel = createLarkChannel({ appId, appSecret });
598
+
599
+ channel.on('message', async (msg) => {
600
+ await channel.send(
601
+ msg.chatId,
602
+ { markdown: `received: ${msg.content}` },
603
+ { replyTo: msg.messageId },
604
+ );
605
+ });
606
+
607
+ await channel.connect();
608
+ ```
609
+
610
+ Full reference (event subscription, sending, streaming, low-level helpers, error handling, configuration, etc.) — see [docs/channel.md](./docs/channel.md).
611
+
590
612
  ### [Message Card](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)
591
613
 
592
614
  The processing of the Message Card is also a kind of Event processing. The only difference between the two is that the processor of the Message Card is used to respond to the events generated by the interaction between the user and the Message Card. If the processor has a return value (*the value structure should be in line with the structure defined by [Message Card Structure](https://open.feishu.cn/document/ukTMukTMukTM/uEjNwUjLxYDM14SM2ATN)*), then the return value is used to update the responded message card:
package/README.zh.md CHANGED
@@ -5,58 +5,72 @@
5
5
  ![NPM License](https://img.shields.io/npm/l/%40larksuiteoapi%2Fnode-sdk)
6
6
 
7
7
  [English](https://github.com/larksuite/node-sdk/blob/main/README.md)
8
+
8
9
  ## 概述
10
+
9
11
  [飞书开放平台](https://open.feishu.cn/document/ukTMukTMukTM/uITNz4iM1MjLyUzM)提供了一系列服务端的原子api来实现多元化的功能,但在实际编码过程中感受不是很顺畅,原因在于使用这些api完成功能时,需要考虑很多额外的工作,如token的获取及其维护、数据加解密、请求的验签等等;再者,在实际编码过程中,少了函数调用的语义化描述,类型系统的支持,使得心智负担过重。
10
12
 
11
13
  凡此种种,都使得整体的开发体验不佳,基于此,为了让开放能力变得易用,我们编写了该SDK,将所有冗长的逻辑内置处理,提供完备的类型系统,对外提供语义化的编程接口,提高编码体验。😙
12
14
 
13
15
  以下是一些基于该sdk的官方教程:
14
- * [快速开发互动卡片](https://open.feishu.cn/document/home/quickly-develop-interactive-cards/introduction)
15
- * [快速开发人员及考勤管理系统](https://open.feishu.cn/document/home/quick-start-of-personnel-and-attendance-management-system/overview)
16
- * [快速接入多维表格](https://open.feishu.cn/document/home/quick-access-to-base/preparation)
17
- * [基于网页应用实现部门人员管理](https://open.feishu.cn/document/home/quick-access-to-base/department-personnel-management-based-on-web-app/overview)
18
- * [快速接入通讯录](https://open.feishu.cn/document/home/quick-access-to-contact-api/introduction)
19
- * [基于审批实现自动考勤管理](https://open.feishu.cn/document/home/automatic-attendance-management-based-on-approval/introduction)
16
+
17
+ - [快速开发互动卡片](https://open.feishu.cn/document/home/quickly-develop-interactive-cards/introduction)
18
+ - [快速开发人员及考勤管理系统](https://open.feishu.cn/document/home/quick-start-of-personnel-and-attendance-management-system/overview)
19
+ - [快速接入多维表格](https://open.feishu.cn/document/home/quick-access-to-base/preparation)
20
+ - [基于网页应用实现部门人员管理](https://open.feishu.cn/document/home/quick-access-to-base/department-personnel-management-based-on-web-app/overview)
21
+ - [快速接入通讯录](https://open.feishu.cn/document/home/quick-access-to-contact-api/introduction)
22
+ - [基于审批实现自动考勤管理](https://open.feishu.cn/document/home/automatic-attendance-management-based-on-approval/introduction)
20
23
 
21
24
  ## 概念
22
- - 开发文档:开放平台的开放接口的参考,**开发者必看,可以使用搜索功能,高效的查询文档**。[更多介绍说明](https://open.feishu.cn/document/) 。
23
25
 
26
+ - 开发文档:开放平台的开放接口的参考,**开发者必看,可以使用搜索功能,高效的查询文档**。[更多介绍说明](https://open.feishu.cn/document/) 。
24
27
  - 开发者后台:开发者开发应用的管理后台,[更多介绍说明](https://open.feishu.cn/app/) 。
25
-
26
28
  - 企业自建应用:应用仅仅可在本企业内安装使用,[更多介绍说明](https://open.feishu.cn/document/uQjL04CN/ukzM04SOzQjL5MDN) 。
27
-
28
29
  - 应用商店应用:应用会在 [应用目录](https://app.feishu.cn/?lang=zh-CN)
29
30
  展示,各个企业可以选择安装,[更多介绍说明](https://open.feishu.cn/document/uQjL04CN/ugTO5UjL4kTO14CO5kTN) 。
30
31
 
31
32
  ## 安装
33
+
32
34
  npm
33
- ```shell script
35
+
36
+ ```shell
34
37
  npm install @larksuiteoapi/node-sdk
35
38
  ```
39
+
36
40
  yarn
41
+
37
42
  ```
38
43
  yarn add @larksuiteoapi/node-sdk
39
44
  ```
40
45
 
41
46
  ## 如何使用
47
+
42
48
  提供ECMAScript,CommonJS2个版本,支持原生Javascript和Typescript的使用,示例均以Typescript为例。
43
49
 
44
50
  Typescript
51
+
45
52
  ```typescript
46
53
  import * as lark from '@larksuiteoapi/node-sdk';
47
54
  ```
55
+
48
56
  CommonJS
57
+
49
58
  ```javascript
50
59
  const lark = require('@larksuiteoapi/node-sdk');
51
60
  ```
61
+
52
62
  ECMAScript
63
+
53
64
  ```javascript
54
65
  import * as lark from '@larksuiteoapi/node-sdk';
55
66
  ```
67
+
56
68
  ### api调用
69
+
57
70
  飞书开放平台开放的所有 API 列表,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uYTM5UjL2ETO14iNxkTN/server-api-list)。
58
71
 
59
72
  SDK提供了语义化的调用方式,只需要依据相关参数构造出client实例,接着使用其上的语义化方法(*client.业务域.资源.方法*)即可完成api调用,调用过程及调用结果均有完备的类型进行提示,如向群聊中发送消息:
73
+
60
74
  ```typescript
61
75
  import * as lark from '@larksuiteoapi/node-sdk';
62
76
 
@@ -78,12 +92,15 @@ const res = await client.im.message.create({
78
92
  },
79
93
  });
80
94
  ```
81
- > tips:
82
- > * 如果想调试某个api,可以点击注释中的链接进入api调试台进行调试:
83
- > ![](doc/debugger-tip.png)
84
- > * 如何获取语义化调用接口:[点击这里](https://github.com/larksuite/node-sdk/issues/42)
95
+
96
+ > tips:
97
+ >
98
+ > - 如果想调试某个api,可以点击注释中的链接进入api调试台进行调试:
99
+ > ![](docs/assets/debugger-tip.png)
100
+ > - 如何获取语义化调用接口:[点击这里](https://github.com/larksuite/node-sdk/issues/42)
85
101
 
86
102
  #### 创建client
103
+
87
104
  对于自建应用,可以使用下面的代码创建一个client:
88
105
 
89
106
  ```typescript
@@ -96,6 +113,7 @@ const client = new lark.Client({
96
113
  ```
97
114
 
98
115
  对于商店应用,需要显示的指定appType为lark.AppType.ISV:
116
+
99
117
  ```typescript
100
118
  import * as lark from '@larksuiteoapi/node-sdk';
101
119
 
@@ -105,7 +123,9 @@ const client = new lark.Client({
105
123
  appType: lark.AppType.ISV,
106
124
  });
107
125
  ```
108
- **使用创建好的商店应用的client发起api调用时,还需在请求时手动传递[tenant_key](https://open.feishu.cn/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/g#d15ab5d)**,可以使用lark.withTenantKey来完成:
126
+
127
+ **使用创建好的商店应用的client发起api调用时,还需在请求时手动传递[tenant\_key](https://open.feishu.cn/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/g#d15ab5d)**,可以使用lark.withTenantKey来完成:
128
+
109
129
  ```typescript
110
130
  client.im.message.create({
111
131
  params: {
@@ -120,23 +140,26 @@ client.im.message.create({
120
140
  ```
121
141
 
122
142
  #### `Client`构造参数:
123
- | 参数 | 描述 | 类型 | 必须 | 默认 |
124
- | ---- | ---- | ---- | ---- | ---- |
125
- | appId | 应用的id | string | | - |
126
- | appSecret | 应用的密码 | string | 是 | - |
127
- | domain | 应用的域,分为飞书(https://open.feishu.cn)、lark(https://open.larksuite.com)、其它(需要传递完整的域名) | Domain | string | | Domain.Feishu |
128
- | httpInstance | sdk发送请求的http实例。*sdk内部默认使用axios.create()构造出一个defaultHttpInstance来进行http调用。*| HttpInstance | 否 | defaultHttpInstance。*可以从sdk中import它,在其上添加interceptors来完成业务需求。* |
129
- | loggerLevel | 日志级别 | LoggerLevel | 否 | info |
130
- | logger | - | Logger | 否 | - |
131
- | cache | 缓存器 | Cache | 否 | - |
132
- | disableTokenCache | 是否禁用缓存,如若禁用,则token等不会进行缓存,每次需要使用时都会重新拉取 | boolean | 否 | false |
133
- | appType | 应用的类型,分为商店应用或者自建应用 | AppType | 否 | AppType.SelfBuild |
134
- | helpDeskId | 服务台id | string | 否 | - |
135
- | helpDeskToken | 服务台token | string | 否 | - |
143
+
144
+ | 参数 | 描述 | 类型 | 必须 | 默认 |
145
+ | ----------------- | ---------------------------------------------------------------------------------- | ---------------- | -- | -------------------------------------------------------------- |
146
+ | appId | 应用的id | string | 是 | - |
147
+ | appSecret | 应用的密码 | string | | - |
148
+ | domain | 应用的域,分为飞书(<https://open.feishu.cn)、lark(https://open.larksuite.com)、其它(需要传递完整的域名)> | Domain \| string | 否 | Domain.Feishu |
149
+ | httpInstance | sdk发送请求的http实例。*sdk内部默认使用axios.create()构造出一个defaultHttpInstance来进行http调用。* | HttpInstance | 否 | defaultHttpInstance。*可以从sdk中import它,在其上添加interceptors来完成业务需求。* |
150
+ | loggerLevel | 日志级别 | LoggerLevel | 否 | info |
151
+ | logger | - | Logger | 否 | - |
152
+ | cache | 缓存器 | Cache | 否 | - |
153
+ | disableTokenCache | 是否禁用缓存,如若禁用,则token等不会进行缓存,每次需要使用时都会重新拉取 | boolean | 否 | false |
154
+ | appType | 应用的类型,分为商店应用或者自建应用 | AppType | 否 | AppType.SelfBuild |
155
+ | helpDeskId | 服务台id | string | 否 | - |
156
+ | helpDeskToken | 服务台token | string | 否 | - |
136
157
 
137
158
  #### 分页
138
- 针对返回值以分页形式呈现的接口,对其提供了迭代器方式的封装(方法名后缀为WithIterator),提高易用性,消弭了根据page_token来反复获取数据的繁琐操作,如获取用户列表:
139
- ``` typescript
159
+
160
+ 针对返回值以分页形式呈现的接口,对其提供了迭代器方式的封装(方法名后缀为WithIterator),提高易用性,消弭了根据page\_token来反复获取数据的繁琐操作,如获取用户列表:
161
+
162
+ ```typescript
140
163
  // 每次处理20条数据
141
164
  for await (const items of await client.contact.user.listWithIterator({
142
165
  params: {
@@ -157,9 +180,13 @@ const listIterator = await SDKClient.contact.user.listWithIterator({
157
180
  const { value } = await listIterator[Symbol.asyncIterator]().next();
158
181
  console.log(value);
159
182
  ```
160
- *当然也可以使用无迭代器封装的版本,这时候需要自己每次根据返回的page_token来手动进行分页调用。*
183
+
184
+ *当然也可以使用无迭代器封装的版本,这时候需要自己每次根据返回的page\_token来手动进行分页调用。*
185
+
161
186
  #### 文件上传
187
+
162
188
  和调用普通api的方式一样,按类型提示传递参数即可,内部封装了对文件上传的处理,如:
189
+
163
190
  ```typescript
164
191
  const res = await client.im.file.create({
165
192
  data: {
@@ -169,8 +196,11 @@ const res = await client.im.file.create({
169
196
  },
170
197
  });
171
198
  ```
199
+
172
200
  #### 文件下载
201
+
173
202
  对返回的二进制流进行了封装,消弭了对流本身的处理,只需调用writeFile方法即可将数据写入文件,如:
203
+
174
204
  ```typescript
175
205
  const resp = await client.im.file.get({
176
206
  path: {
@@ -179,7 +209,9 @@ const resp = await client.im.file.get({
179
209
  });
180
210
  await resp.writeFile(`filepath.suffix`);
181
211
  ```
212
+
182
213
  如果想要自定义对流的处理,可以调用getReadableStream方法获取到流,如将流写入文件:
214
+
183
215
  ```typescript
184
216
  import * as fs from 'fs';
185
217
 
@@ -192,10 +224,13 @@ const readableStream = resp.getReadableStream();
192
224
  const writableStream = fs.createWriteStream('file url');
193
225
  readableStream.pipe(writableStream);
194
226
  ```
227
+
195
228
  > 注意:流只能被消费一次,即如果使用了writeFile消费了流,则getReadableStream获取流会报错/获取到的流为空;如需消费多次流,可以使用getReadableStream获取流,然后读取流中的数据做缓存,将缓存的数据给消费方使用。
196
229
 
197
230
  #### 普通调用
231
+
198
232
  某些老版本的开放接口,无法生成对应的语义化调用方法,需要使用client上的request方法来进行手动调用:
233
+
199
234
  ```typescript
200
235
  import * as lark from '@larksuiteoapi/node-sdk';
201
236
 
@@ -213,8 +248,11 @@ const res = await client.request({
213
248
  params: {},
214
249
  });
215
250
  ```
251
+
216
252
  #### 消息卡片
253
+
217
254
  在发送[消息卡片](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)信息时,会先在[消息卡片搭建工具](https://open.feishu.cn/document/ukTMukTMukTM/uYzM3QjL2MzN04iNzcDN/message-card-builder)中搭建出消息卡片的模版,拿到生成的模版json,用数据替换其中内容相关的部分,将结果作为支持消息卡片api的参数来使用。如发送一个简单的具有`title`和`content`的消息卡片:
255
+
218
256
  ```typescript
219
257
  client.im.message.create({
220
258
  params: {
@@ -245,8 +283,10 @@ client.im.message.create({
245
283
  }
246
284
  })
247
285
  ```
248
- ![](doc/msg-card.png)
286
+
287
+ ![](docs/assets/msg-card.png)
249
288
  这样使用会有一个问题:**如果消息卡片内容比较丰富,生成的模版json比较大,与之相关需要数据填充的内容部分也会比较多,手动维护比较繁琐**。针对这个问题,开放平台提供了[模版消息](https://open.feishu.cn/document/tools-and-resources/message-card-builder#3e1f2c7c)的能力,发送消息卡片时只需要提供模版id和模版的数据内容即可。sdk对这个能力进行了调用上的封装,支持消息卡片的接口会同步的增加一个ByCard的调用方式,只需要传递`template_id`和`template_variable`即可。如上面的调用可以改写成:
289
+
250
290
  ```typescript
251
291
  client.im.message.createByCard({
252
292
  params: {
@@ -262,7 +302,9 @@ client.im.message.createByCard({
262
302
  }
263
303
  });
264
304
  ```
305
+
265
306
  如果想要快速体验消息卡片,可以使用sdk中内置的一个基础卡片:
307
+
266
308
  ```typescript
267
309
  import * as lark from '@larksuiteoapi/node-sdk';
268
310
 
@@ -280,11 +322,14 @@ client.im.message.create({
280
322
  }
281
323
  })
282
324
  ```
325
+
283
326
  效果同上:
284
- ![](doc/msg-card.png)
327
+ ![](docs/assets/msg-card.png)
285
328
 
286
329
  #### 配置请求选项
330
+
287
331
  如果想在api调用过程中修改请求的参数,如携带一些header,自定义tenantToken等,则可以使用请求方法的第二个参数来进行修改:
332
+
288
333
  ```typescript
289
334
  await client.im.message.create({
290
335
  params: {
@@ -301,15 +346,16 @@ await client.im.message.create({
301
346
  }
302
347
  });
303
348
  ```
349
+
304
350
  SDK亦将常用的修改操作封装成了方法,可以使用:
305
351
 
306
- | 方法 | 描述 |
307
- | ---- | ---- |
308
- | withTenantKey | 设置tenant key |
309
- | withTenantToken | 设置tenant token |
310
- | withHelpDeskCredential | 是否在请求中带入[服务台token](https://open.feishu.cn/document/ukTMukTMukTM/ugDOyYjL4gjM24CO4IjN) |
311
- | withUserAccessToken | 设置access token |
312
- | withAll | 将上述方法的结果合并起来 |
352
+ | 方法 | 描述 |
353
+ | ---------------------- | ------------------------------------------------------------------------------------- |
354
+ | withTenantKey | 设置tenant key |
355
+ | withTenantToken | 设置tenant token |
356
+ | withHelpDeskCredential | 是否在请求中带入[服务台token](https://open.feishu.cn/document/ukTMukTMukTM/ugDOyYjL4gjM24CO4IjN) |
357
+ | withUserAccessToken | 设置access token |
358
+ | withAll | 将上述方法的结果合并起来 |
313
359
 
314
360
  ```typescript
315
361
  await client.im.message.create({
@@ -339,14 +385,17 @@ await client.im.message.create({
339
385
  ```
340
386
 
341
387
  ### 处理事件
388
+
342
389
  飞书开放平台开放的所有事件列表,可点击[这里查看](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list)。
343
390
 
344
391
  针对事件处理的场景,我们所关心的仅是**监听何种事件**,以及事件发生后我们**做些什么**,其它诸如数据解密等工作是我们不想关心的。SDK提供了直观的方式来描述这部分逻辑:
392
+
345
393
  1. 构造事件处理器`EventDispatcher`的实例;
346
394
  2. 在实例上注册需要监听的事件及其处理函数;
347
395
  3. 将实例和服务进行绑定;
348
396
 
349
397
  `EventDispatcher`内部会进行数据解密等操作,如果没有传递相关参数,则会自动忽略。
398
+
350
399
  ```typescript
351
400
  import http from 'http';
352
401
  import * as lark from '@larksuiteoapi/node-sdk';
@@ -378,18 +427,20 @@ server.listen(3000);
378
427
 
379
428
  #### `EventDispatcher`构造参数
380
429
 
381
- | 参数 | 描述 | 类型 | 必须 | 默认 |
382
- | ---- | ---- | ---- | ---- | ---- |
383
- | [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case) | 推送数据加密的key,开启加密推送时需要使用来进行数据解密 | string | 否 | - |
384
- | loggerLevel | 日志级别 | LoggerLevel | 否 | lark.LoggerLevel.info |
385
- | logger | - | Logger | 否 | - |
386
- | cache | 缓存器 | Cache | 否 | - |
430
+ | 参数 | 描述 | 类型 | 必须 | 默认 |
431
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------- | -- | --------------------- |
432
+ | [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case) | 推送数据加密的key,开启加密推送时需要使用来进行数据解密 | string | 否 | - |
433
+ | loggerLevel | 日志级别 | LoggerLevel | 否 | lark.LoggerLevel.info |
434
+ | logger | - | Logger | 否 | - |
435
+ | cache | 缓存器 | Cache | 否 | - |
387
436
 
388
437
  > 注:有一些事件是v1.0版本且已经不在维护了,SDK保留了对其的支持,强烈建议使用与之功能相一致的新版事件代替。鼠标移动到相应事件订阅函数上即可看到相关文档:
389
- ![](doc/deprecated.png)
438
+ > ![](docs/assets/deprecated.png)
390
439
 
391
440
  #### 和express结合
441
+
392
442
  SDK提供了针对experss的适配器,用于将eventDispatcher转化为express的中间件,可无缝与使用express编写的服务相结合(*示例中的bodyParser的使用不是必须的,但社区大多用其来格式化body数据*):
443
+
393
444
  ```typescript
394
445
  import * as lark from '@larksuiteoapi/node-sdk';
395
446
  import express from 'express';
@@ -421,8 +472,11 @@ const eventDispatcher = new lark.EventDispatcher({
421
472
  server.use('/webhook/event', lark.adaptExpress(eventDispatcher));
422
473
  server.listen(3000);
423
474
  ```
475
+
424
476
  #### 和koa结合
477
+
425
478
  SDK提供了针对koa的适配器,用于将eventDispatcher转化为koa的中间件,可无缝与使用koa编写的服务相结合(*示例中的koaBody的使用不是必须的,但社区大多用其来格式化body数据*):
479
+
426
480
  ```typescript
427
481
  import * as lark from '@larksuiteoapi/node-sdk';
428
482
  import Koa from 'koa';
@@ -455,8 +509,11 @@ const eventDispatcher = new lark.EventDispatcher({
455
509
  server.use(lark.adaptKoa('/webhook/event', eventDispatcher));
456
510
  server.listen(3000);
457
511
  ```
512
+
458
513
  #### 和koa-router结合
514
+
459
515
  在使用koa来编写服务时,大多情况下会配合使用koa-router来对路由进行处理,因此SDK也提供了针对这一情况的适配:
516
+
460
517
  ```typescript
461
518
  import * as lark from '@larksuiteoapi/node-sdk';
462
519
  import Koa from 'koa';
@@ -509,9 +566,11 @@ server.sendResult(result);
509
566
  ```
510
567
 
511
568
  #### challenge校验
569
+
512
570
  在配置事件请求地址时,开放平台会向请求地址推送一个`application/json`格式的 POST请求,该POST请求用于验证所配置的请求地址的合法性,请求体中会携带一个`challenge`字段,**应用需要在 1 秒内,将接收到的challenge值原样返回给飞书开放平台**。详见:[文档](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/request-url-configuration-case)
513
571
 
514
572
  上面sdk提供出的适配器内部封装了这部分验证的逻辑,将options参数中的`autoChallenge`字段设为true即可启用:
573
+
515
574
  ```typescript
516
575
  // adaptDefault
517
576
  lark.adaptDefault('/webhook/event', eventDispatcher, {
@@ -535,14 +594,15 @@ router.post(
535
594
  ```
536
595
 
537
596
  ### 使用长链模式处理事件
597
+
538
598
  官方文档:[文档](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/event-subscription-guide/long-connection-mode#62c8b8c8)
539
599
 
540
600
  开发者通过集成飞书 SDK 与开放平台建立一条 WebSocket 全双工通道,当有事件回调发生时,开放平台会通过该通道向开发者发送消息。与传统的 Webhook 模式相比,长连接模式大大降低了接入成本,将原先 1 周左右的开发周期降低到 5 分钟。具体优势如下:
541
601
 
542
- * 测试阶段**无需使用内网穿透工具**,通过长连接模式在本地开发环境中即可接收事件回调。
543
- * 只在建连时进行鉴权,后续事件推送均为明文数据,无需开发者再处理解密和验签逻辑。
544
- * 只需保证运行环境具备访问公网能力即可,无需提供公网 IP 或域名。
545
- * 无需部署防火墙和配置白名单。
602
+ - 测试阶段**无需使用内网穿透工具**,通过长连接模式在本地开发环境中即可接收事件回调。
603
+ - 只在建连时进行鉴权,后续事件推送均为明文数据,无需开发者再处理解密和验签逻辑。
604
+ - 只需保证运行环境具备访问公网能力即可,无需提供公网 IP 或域名。
605
+ - 无需部署防火墙和配置白名单。
546
606
 
547
607
  > 注意事项
548
608
 
@@ -551,6 +611,7 @@ router.post(
551
611
  3. 目前长连接模式仅支持事件订阅,不支持回调订阅。
552
612
 
553
613
  SDK支持了该功能集成,`1.24.0`及之后的版本可用,示例代码:
614
+
554
615
  ```typescript
555
616
  import * as Lark from '@larksuiteoapi/node-sdk';
556
617
 
@@ -587,6 +648,28 @@ wsClient.start({
587
648
  });
588
649
  ```
589
650
 
651
+ ### Channel 模块
652
+
653
+ `Channel` 是在 `WSClient` / `Client` 之上封装的高层模块,一站式封装飞书机器人接入的传输、消息归一化、安全策略、出站发送、流式回复、媒体上传、卡片交互等杂活,适合会话式机器人(AI 对话、流式回复、卡片按钮等)场景。
654
+
655
+ ```typescript
656
+ import { createLarkChannel } from '@larksuiteoapi/node-sdk';
657
+
658
+ const channel = createLarkChannel({ appId, appSecret });
659
+
660
+ channel.on('message', async (msg) => {
661
+ await channel.send(
662
+ msg.chatId,
663
+ { markdown: `收到:${msg.content}` },
664
+ { replyTo: msg.messageId },
665
+ );
666
+ });
667
+
668
+ await channel.connect();
669
+ ```
670
+
671
+ 完整用法(事件监听、发送消息、流式回复、底层能力、错误处理、配置项等)见 [docs/channel.zh.md](./docs/channel.zh.md)。
672
+
590
673
  ### [消息卡片](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)
591
674
 
592
675
  对消息卡片的处理亦是对事件处理的一种,两者的不同点仅在于消息卡片的处理器用于响应用户与消息卡片交互所产生的事件,若处理器有返回值(*返回值的数据结构理应为符合[消息卡片结构](https://open.feishu.cn/document/ukTMukTMukTM/uEjNwUjLxYDM14SM2ATN)所定义的结构*),则返回值被用来更新被响应的消息卡片:
@@ -619,15 +702,16 @@ server.listen(3000);
619
702
 
620
703
  #### `CardActionHandler`构造参数
621
704
 
622
- | 参数 | 描述 | 类型 | 必须 | 默认 |
623
- | ---- | ---- | ---- | ---- | ---- |
624
- | [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case) | 推送数据加密的key,开启加密推送时需要使用来进行数据解密 | string | 否 | - |
625
- | [verificationToken](https://open.feishu.cn/document/ukTMukTMukTM/uYzMxEjL2MTMx4iNzETM) | 安全校验,开启消息的安全校验时需要使用 | string | 否 | - |
626
- | loggerLevel | 日志级别 | LoggerLevel | 否 | LoggerLevel.info |
627
- | logger | - | Logger | 否 | - |
628
- | cache | 缓存器 | Cache | 否 | - |
705
+ | 参数 | 描述 | 类型 | 必须 | 默认 |
706
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------- | -- | ---------------- |
707
+ | [encryptKey](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case) | 推送数据加密的key,开启加密推送时需要使用来进行数据解密 | string | 否 | - |
708
+ | [verificationToken](https://open.feishu.cn/document/ukTMukTMukTM/uYzMxEjL2MTMx4iNzETM) | 安全校验,开启消息的安全校验时需要使用 | string | 否 | - |
709
+ | loggerLevel | 日志级别 | LoggerLevel | 否 | LoggerLevel.info |
710
+ | logger | - | Logger | 否 | - |
711
+ | cache | 缓存器 | Cache | 否 | - |
629
712
 
630
713
  ### 一键创建应用
714
+
631
715
  SDK提供了`registerApp`方法,基于 OAuth 2.0 Device Authorization Grant(RFC 8628)协议实现一键创建应用。该方法会返回一个验证链接,用户在飞书/Lark中打开该链接完成授权后,即可自动注册应用并获取凭据,无需手动到开发者后台创建。
632
716
 
633
717
  ```typescript
@@ -661,37 +745,41 @@ try {
661
745
 
662
746
  #### `registerApp`参数
663
747
 
664
- | 参数 | 描述 | 类型 | 必须 | 默认 |
665
- | ---- | ---- | ---- | ---- | ---- |
666
- | domain | 自定义认证域名(仅 host 部分) | string | 否 | `accounts.feishu.cn` |
667
- | larkDomain | 自定义 Lark 认证域名(仅 host 部分),检测到 Lark 租户时自动切换 | string | 否 | `accounts.larksuite.com` |
668
- | source | 来源标识,拼入二维码 URL 的 `from` 参数,格式为 `node-sdk/{source}` | string | 否 | - |
669
- | signal | 用于取消轮询的 `AbortSignal` | AbortSignal | 否 | - |
670
- | onQRCodeReady | 验证链接就绪时的回调,参数为 `{ url, expireIn }`。可将 URL 渲染为二维码供用户扫码,或直接作为链接展示 | function | 是 | - |
671
- | onStatusChange | 轮询状态变化时的回调,参数为 `{ status, interval? }`。status 取值:`polling`、`slow_down`、`domain_switched` | function | 否 | - |
748
+ | 参数 | 描述 | 类型 | 必须 | 默认 |
749
+ | -------------- | ---------------------------------------------------------------------------------------- | ----------- | -- | ------------------------ |
750
+ | domain | 自定义认证域名(仅 host 部分) | string | 否 | `accounts.feishu.cn` |
751
+ | larkDomain | 自定义 Lark 认证域名(仅 host 部分),检测到 Lark 租户时自动切换 | string | 否 | `accounts.larksuite.com` |
752
+ | source | 来源标识,拼入二维码 URL 的 `from` 参数,格式为 `node-sdk/{source}` | string | 否 | - |
753
+ | signal | 用于取消轮询的 `AbortSignal` | AbortSignal | 否 | - |
754
+ | onQRCodeReady | 验证链接就绪时的回调,参数为 `{ url, expireIn }`。可将 URL 渲染为二维码供用户扫码,或直接作为链接展示 | function | 是 | - |
755
+ | onStatusChange | 轮询状态变化时的回调,参数为 `{ status, interval? }`。status 取值:`polling`、`slow_down`、`domain_switched` | function | 否 | - |
672
756
 
673
757
  #### 返回值
674
758
 
675
- | 字段 | 类型 | 描述 |
676
- | ---- | ---- | ---- |
677
- | client_id | string | App ID |
678
- | client_secret | string | App Secret |
679
- | user_info | object(可选) | 扫码用户信息 |
680
- | user_info.open_id | string(可选) | 扫码用户的 open_id |
681
- | user_info.tenant_brand | string(可选) | `"feishu"` 或 `"lark"` |
759
+ | 字段 | 类型 | 描述 |
760
+ | ------------------------ | ---------- | --------------------- |
761
+ | client\_id | string | App ID |
762
+ | client\_secret | string | App Secret |
763
+ | user\_info | object(可选) | 扫码用户信息 |
764
+ | user\_info.open\_id | string(可选) | 扫码用户的 open\_id |
765
+ | user\_info.tenant\_brand | string(可选) | `"feishu"` 或 `"lark"` |
682
766
 
683
767
  #### 错误处理
768
+
684
769
  抛出的错误对象包含 `code` 和 `description` 字段:
685
770
 
686
- | code | 描述 |
687
- | ---- | ---- |
688
- | `access_denied` | 用户拒绝了授权 |
689
- | `expired_token` | 二维码过期或轮询超时 |
690
- | `abort` | 通过 AbortSignal 取消 |
771
+ | code | 描述 |
772
+ | --------------- | ----------------- |
773
+ | `access_denied` | 用户拒绝了授权 |
774
+ | `expired_token` | 二维码过期或轮询超时 |
775
+ | `abort` | 通过 AbortSignal 取消 |
691
776
 
692
777
  ### 工具方法
778
+
693
779
  #### AESCipher
780
+
694
781
  解密。如果配置了[加密推送](https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-subscription-configure-/encrypt-key-encryption-configuration-case),开放平台会推送加密的数据,这时候需要对数据进行解密处理,调用此方法可以便捷的进行解密。(一般情况下,SDK中内置了解密逻辑,不需要手动进行处理)。
782
+
695
783
  ```typescript
696
784
  import * as lark from '@larksuiteoapi/node-sdk';
697
785
 
@@ -699,13 +787,17 @@ new lark.AESCipher('encrypt key').decrypt('content');
699
787
  ```
700
788
 
701
789
  ## Examples
790
+
702
791
  [快速开发自动回复机器人](https://github.com/larksuite/lark-samples/blob/main/react_and_nodejs/robot/README.zh.md)
703
792
 
704
793
  ## Blog
794
+
705
795
  [ISV(商店应用)开发指南](https://bytedance.feishu.cn/docx/RUZKdGwdyoH4KexMJgDcITQnn0b)
706
796
 
707
797
  ## 许可协议
798
+
708
799
  MIT
709
800
 
710
801
  ## 联系我们
802
+
711
803
  点击[服务端SDK](https://open.feishu.cn/document/ukTMukTMukTM/uETO1YjLxkTN24SM5UjN) 页面右上角【这篇文档是否对你有帮助?】提交反馈😘