@satorijs/adapter-lark 3.9.5 → 3.10.0

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/lib/bot.d.ts CHANGED
@@ -5,17 +5,14 @@ import { Internal } from './internal';
5
5
  export declare class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config> {
6
6
  static inject: string[];
7
7
  static MessageEncoder: typeof LarkMessageEncoder;
8
- _token?: string;
9
8
  _refresher?: NodeJS.Timeout;
10
9
  http: HTTP;
11
10
  assetsQuester: HTTP;
12
- internal: Internal;
11
+ internal: Internal<C>;
13
12
  constructor(ctx: C, config: LarkBot.Config);
14
13
  getResourceUrl(type: string, message_id: string, file_key: string): string;
15
14
  initialize(): Promise<void>;
16
15
  private refreshToken;
17
- get token(): string;
18
- set token(v: string);
19
16
  editMessage(channelId: string, messageId: string, content: h.Fragment): Promise<void>;
20
17
  deleteMessage(channelId: string, messageId: string): Promise<void>;
21
18
  getMessage(channelId: string, messageId: string, recursive?: boolean): Promise<Universal.Message>;
package/lib/content.d.ts CHANGED
@@ -299,6 +299,9 @@ export declare namespace MessageContent {
299
299
  name?: string;
300
300
  required?: boolean;
301
301
  action_type?: 'link' | 'request' | 'multi' | 'form_submit' | 'form_reset';
302
+ value?: Record<string, string>;
303
+ url?: string;
304
+ multi_url?: Omit<URLs, 'url'>;
302
305
  }
303
306
  interface ConfirmElement {
304
307
  title: PlainTextElement;
@@ -421,7 +424,7 @@ export declare namespace MessageContent {
421
424
  type Width = 'default' | 'fill' | string;
422
425
  type Type = 'default' | 'primary' | 'danger' | 'text' | 'primary_text' | 'danger_text' | 'primary_filled' | 'danger_filled' | 'laser';
423
426
  }
424
- type Element = DivElement | MarkdownElement | HRElement | ActionElement | NoteElement | ChartElement | TableElement | ImageElement | FormElement | InputElement | ButtonElement;
427
+ type Element = DivElement | MarkdownElement | HRElement | ActionElement | NoteElement | ChartElement | TableElement | ImageElement | FormElement | InputElement | ButtonElement | CheckerElement;
425
428
  }
426
429
  interface Template {
427
430
  type: 'template';
package/lib/index.cjs CHANGED
@@ -146,17 +146,21 @@ async function adaptSession(bot, body) {
146
146
  const toArg = /* @__PURE__ */ __name((value) => {
147
147
  if (typeof value === "string") {
148
148
  return `'${value}'`;
149
- } else if (typeof value === "number") {
150
- return value;
151
149
  } else {
152
- return `''`;
150
+ return value;
153
151
  }
154
152
  }, "toArg");
155
153
  for (let i = 0; i < args.length; ++i) {
156
154
  content += ` ${toArg(args[i])}`;
157
155
  }
158
156
  for (const [key, value] of Object.entries(options)) {
159
- content += ` --${key} ${toArg(value)}`;
157
+ if (value === true) {
158
+ content += ` --${key}`;
159
+ } else if (value === false) {
160
+ content += ` --no-${key}`;
161
+ } else {
162
+ content += ` --${key} ${toArg(value)}`;
163
+ }
160
164
  }
161
165
  if (body.event.action.input_value) {
162
166
  content += ` ${toArg(body.event.action.input_value)}`;
@@ -322,6 +326,7 @@ var HttpServer = class extends import_core2.Adapter {
322
326
  });
323
327
  if (!result) return ctx.status = 403;
324
328
  }
329
+ if (!ctx.request.is("json")) return ctx.status = 415;
325
330
  const body = this._tryDecryptBody(ctx.request.body);
326
331
  if (body?.type === "url_verification" && body?.challenge && typeof body.challenge === "string") {
327
332
  ctx.response.body = { challenge: body.challenge };
@@ -576,13 +581,13 @@ var LarkMessageEncoder = class extends import_core3.MessageEncoder {
576
581
  } else if (type === "at") {
577
582
  if (this.card) {
578
583
  if (attrs.type === "all") {
579
- this.textContent += `<at id=all>${attrs.name ?? "所有人"}</at>`;
584
+ this.textContent += `<at id=all>${attrs.name ?? ""}</at>`;
580
585
  } else {
581
586
  this.textContent += `<at id=${attrs.id}>${attrs.name ?? ""}</at>`;
582
587
  }
583
588
  } else {
584
589
  if (attrs.type === "all") {
585
- this.textContent += `<at user_id="all">${attrs.name ?? "所有人"}</at>`;
590
+ this.textContent += `<at user_id="all">${attrs.name ?? ""}</at>`;
586
591
  } else {
587
592
  this.textContent += `<at user_id="${attrs.id}">${attrs.name ?? ""}</at>`;
588
593
  }
@@ -620,7 +625,7 @@ var LarkMessageEncoder = class extends import_core3.MessageEncoder {
620
625
  const length = this.card?.elements.length;
621
626
  await this.render(children);
622
627
  if (this.card?.elements.length > length) {
623
- const elements = this.card?.elements.slice(length);
628
+ const elements = this.card?.elements.splice(length);
624
629
  this.card.elements.push({
625
630
  tag: "form",
626
631
  name: attrs.name || "Form",
@@ -628,24 +633,56 @@ var LarkMessageEncoder = class extends import_core3.MessageEncoder {
628
633
  });
629
634
  }
630
635
  } else if (type === "input") {
631
- this.flushText();
632
- this.card?.elements.push({
633
- tag: "action",
634
- actions: [{
635
- tag: "input",
636
+ if (attrs.type === "checkbox") {
637
+ this.flushText();
638
+ await this.render(children);
639
+ this.card?.elements.push({
640
+ tag: "checker",
636
641
  name: attrs.name,
637
- width: attrs.width,
638
- label: attrs.label && {
642
+ checked: attrs.checked,
643
+ text: {
639
644
  tag: "plain_text",
640
- content: attrs.label
641
- },
642
- placeholder: attrs.placeholder && {
645
+ content: this.textContent
646
+ }
647
+ });
648
+ } else if (attrs.type === "submit") {
649
+ this.flushText(true);
650
+ await this.render(children);
651
+ this.card?.elements.push({
652
+ tag: "button",
653
+ name: attrs.name,
654
+ text: {
643
655
  tag: "plain_text",
644
- content: attrs.placeholder
656
+ content: this.textContent
645
657
  },
646
- behaviors: this.createBehavior(attrs)
647
- }]
648
- });
658
+ action_type: "form_submit",
659
+ value: {
660
+ _satori_type: "command",
661
+ content: attrs.text
662
+ }
663
+ });
664
+ } else {
665
+ this.flushText();
666
+ await this.render(children);
667
+ this.card?.elements.push({
668
+ tag: "action",
669
+ actions: [{
670
+ tag: "input",
671
+ name: attrs.name,
672
+ width: attrs.width,
673
+ label: this.textContent && {
674
+ tag: "plain_text",
675
+ content: this.textContent
676
+ },
677
+ placeholder: attrs.placeholder && {
678
+ tag: "plain_text",
679
+ content: attrs.placeholder
680
+ },
681
+ behaviors: this.createBehavior(attrs)
682
+ }]
683
+ });
684
+ }
685
+ this.textContent = "";
649
686
  } else if (type === "button") {
650
687
  this.card ??= { elements: [] };
651
688
  this.flushText(true);
@@ -883,7 +920,6 @@ var LarkBot = class extends import_core5.Bot {
883
920
  }
884
921
  static inject = ["server", "http"];
885
922
  static MessageEncoder = LarkMessageEncoder;
886
- _token;
887
923
  _refresher;
888
924
  http;
889
925
  assetsQuester;
@@ -931,7 +967,7 @@ var LarkBot = class extends import_core5.Bot {
931
967
  app_secret: this.config.appSecret
932
968
  });
933
969
  this.logger.debug("refreshed token %s", token);
934
- this.token = token;
970
+ this.http.config.headers.Authorization = `Bearer ${token}`;
935
971
  } catch (error) {
936
972
  this.logger.error("failed to refresh token, retrying in 10s");
937
973
  this.logger.error(error);
@@ -941,13 +977,6 @@ var LarkBot = class extends import_core5.Bot {
941
977
  this._refresher = setTimeout(() => this.refreshToken(), timeout);
942
978
  this.online();
943
979
  }
944
- get token() {
945
- return this._token;
946
- }
947
- set token(v) {
948
- this._token = v;
949
- this.http.config.headers.Authorization = `Bearer ${v}`;
950
- }
951
980
  async editMessage(channelId, messageId, content) {
952
981
  const encoder = new LarkMessageEncoder(this, channelId);
953
982
  encoder.editMessageIds = [messageId];
package/lib/internal.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Dict, HTTP } from '@satorijs/core';
1
+ import { Context, Dict, HTTP } from '@satorijs/core';
2
2
  import { LarkBot } from './bot';
3
3
  export interface Internal {
4
4
  }
@@ -28,9 +28,9 @@ export interface InternalRoute {
28
28
  multipart?: boolean;
29
29
  type?: 'raw-json' | 'binary';
30
30
  }
31
- export declare class Internal {
31
+ export declare class Internal<C extends Context = Context> {
32
32
  private bot;
33
- constructor(bot: LarkBot);
33
+ constructor(bot: LarkBot<C>);
34
34
  private _assertResponse;
35
35
  private _buildData;
36
36
  static define(routes: Dict<Partial<Record<HTTP.Method, string | InternalRoute>>>): void;
package/lib/utils.d.ts CHANGED
@@ -146,9 +146,9 @@ export type Sender = {
146
146
  tenant_key: string;
147
147
  });
148
148
  export declare function adaptSender(sender: Sender, session: Session): Session;
149
- export declare function adaptMessage(bot: LarkBot, data: Events['im.message.receive_v1'], session: Session, details?: boolean): Promise<Session>;
149
+ export declare function adaptMessage<C extends Context = Context>(bot: LarkBot<C>, data: Events['im.message.receive_v1'], session: Session, details?: boolean): Promise<Session>;
150
150
  export declare function adaptSession<C extends Context>(bot: LarkBot<C>, body: EventPayload): Promise<C[typeof import("cordis").Context.session]>;
151
- export declare function decodeMessage(bot: LarkBot, body: Message, details?: boolean): Promise<Universal.Message>;
151
+ export declare function decodeMessage<C extends Context = Context>(bot: LarkBot<C>, body: Message, details?: boolean): Promise<Universal.Message>;
152
152
  /**
153
153
  * Get ID type from id string
154
154
  * @see https://open.larksuite.com/document/home/user-identity-introduction/introduction
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@satorijs/adapter-lark",
3
3
  "description": "Lark (飞书) Adapter for Satorijs",
4
- "version": "3.9.5",
4
+ "version": "3.10.0",
5
5
  "type": "module",
6
6
  "main": "lib/index.cjs",
7
7
  "types": "lib/index.d.ts",
@@ -37,7 +37,7 @@
37
37
  "@cordisjs/plugin-server": "^0.2.5",
38
38
  "@satorijs/core": "^4.5.0",
39
39
  "cordis": "^3.18.1",
40
- "cosmokit": "^1.6.3",
40
+ "cosmokit": "^1.7.2",
41
41
  "dedent": "^1.5.3"
42
42
  },
43
43
  "peerDependencies": {
package/src/bot.ts CHANGED
@@ -18,11 +18,10 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
18
18
  static inject = ['server', 'http']
19
19
  static MessageEncoder = LarkMessageEncoder
20
20
 
21
- _token?: string
22
21
  _refresher?: NodeJS.Timeout
23
22
  http: HTTP
24
23
  assetsQuester: HTTP
25
- internal: Internal
24
+ internal: Internal<C>
26
25
 
27
26
  constructor(ctx: C, config: LarkBot.Config) {
28
27
  super(ctx, config, 'lark')
@@ -86,7 +85,7 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
86
85
  app_secret: this.config.appSecret,
87
86
  })
88
87
  this.logger.debug('refreshed token %s', token)
89
- this.token = token
88
+ this.http.config.headers!.Authorization = `Bearer ${token}`
90
89
  } catch (error) {
91
90
  this.logger.error('failed to refresh token, retrying in 10s')
92
91
  this.logger.error(error)
@@ -97,15 +96,6 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
97
96
  this.online()
98
97
  }
99
98
 
100
- get token() {
101
- return this._token
102
- }
103
-
104
- set token(v: string) {
105
- this._token = v
106
- this.http.config.headers.Authorization = `Bearer ${v}`
107
- }
108
-
109
99
  async editMessage(channelId: string, messageId: string, content: h.Fragment) {
110
100
  const encoder = new LarkMessageEncoder(this, channelId)
111
101
  encoder.editMessageIds = [messageId]
@@ -118,9 +108,9 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
118
108
 
119
109
  async getMessage(channelId: string, messageId: string, recursive = true) {
120
110
  const data = await this.internal.getImMessage(messageId)
121
- const message = await Utils.decodeMessage(this, data.items[0], recursive)
111
+ const message = await Utils.decodeMessage(this, data.items![0], recursive)
122
112
  const im = await this.internal.getImChat(channelId)
123
- message.channel.type = im.chat_mode === 'p2p' ? Universal.Channel.Type.DIRECT : Universal.Channel.Type.TEXT
113
+ message.channel!.type = im.chat_mode === 'p2p' ? Universal.Channel.Type.DIRECT : Universal.Channel.Type.TEXT
124
114
  return message
125
115
  }
126
116
 
@@ -132,7 +122,7 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
132
122
 
133
123
  async getUser(userId: string, guildId?: string) {
134
124
  const data = await this.internal.getContactUser(userId)
135
- return Utils.decodeUser(data.user)
125
+ return Utils.decodeUser(data.user!)
136
126
  }
137
127
 
138
128
  async getChannel(channelId: string) {
@@ -156,7 +146,7 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
156
146
 
157
147
  async getGuildMemberList(guildId: string, after?: string) {
158
148
  const members = await this.internal.getImChatMembers(guildId, { page_token: after })
159
- const data = members.items.map(v => ({ user: { id: v.member_id, name: v.name }, name: v.name }))
149
+ const data = members.items!.map(v => ({ user: { id: v.member_id, name: v.name }, name: v.name }))
160
150
  return { data, next: members.page_token }
161
151
  }
162
152
 
package/src/content.ts CHANGED
@@ -378,6 +378,10 @@ export namespace MessageContent {
378
378
  name?: string
379
379
  required?: boolean
380
380
  action_type?: 'link' | 'request' | 'multi' | 'form_submit' | 'form_reset'
381
+ // legacy fields
382
+ value?: Record<string, string>
383
+ url?: string
384
+ multi_url?: Omit<URLs, 'url'>
381
385
  }
382
386
 
383
387
  export interface ConfirmElement {
@@ -526,6 +530,7 @@ export namespace MessageContent {
526
530
  | FormElement
527
531
  | InputElement
528
532
  | ButtonElement
533
+ | CheckerElement
529
534
  }
530
535
 
531
536
  export interface Template {
package/src/http.ts CHANGED
@@ -43,6 +43,9 @@ export class HttpServer<C extends Context = Context> extends Adapter<C, LarkBot<
43
43
  if (!result) return (ctx.status = 403)
44
44
  }
45
45
 
46
+ // only accept JSON body
47
+ if (!ctx.request.is('json')) return ctx.status = 415
48
+
46
49
  // try to decrypt message first if encryptKey is set
47
50
  const body = this._tryDecryptBody(ctx.request.body)
48
51
  // respond challenge message
@@ -81,7 +84,7 @@ export class HttpServer<C extends Context = Context> extends Adapter<C, LarkBot<
81
84
  if (!header) return
82
85
  const { app_id, event_type } = header
83
86
  body.type = event_type // add type to body to ease typescript type narrowing
84
- const bot = this.bots.find((bot) => bot.config.appId === app_id)
87
+ const bot = this.bots.find((bot) => bot.config.appId === app_id)!
85
88
  const session = await adaptSession(bot, body)
86
89
  bot.dispatch(session)
87
90
  }
package/src/internal.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Dict, HTTP, makeArray } from '@satorijs/core'
1
+ import { Context, Dict, HTTP, makeArray } from '@satorijs/core'
2
2
  import { LarkBot } from './bot'
3
3
 
4
4
  export interface Internal {}
@@ -33,8 +33,8 @@ export interface InternalRoute {
33
33
  type?: 'raw-json' | 'binary'
34
34
  }
35
35
 
36
- export class Internal {
37
- constructor(private bot: LarkBot) {}
36
+ export class Internal<C extends Context = Context> {
37
+ constructor(private bot: LarkBot<C>) {}
38
38
 
39
39
  private _assertResponse(response: HTTP.Response<BaseResponse>) {
40
40
  if (!response.data.code) return
@@ -113,12 +113,13 @@ export class Internal {
113
113
  const { argIndex, itemsKey = 'items', tokenKey = 'page_token' } = route.pagination
114
114
  const iterArgs = [...args]
115
115
  iterArgs[argIndex] = { ...args[argIndex] }
116
- let pagination: { data: any[]; next?: any } | undefined
116
+ type Pagniation = { data: any[]; next?: any }
117
+ let pagination: Pagniation | undefined
117
118
  result.next = async function () {
118
- pagination ??= await this[Symbol.for('satori.pagination')]()
119
+ pagination ??= await this[Symbol.for('satori.pagination')]() as Pagniation
119
120
  if (pagination.data.length) return { done: false, value: pagination.data.shift() }
120
121
  if (!pagination.next) return { done: true, value: undefined }
121
- pagination = await this[Symbol.for('satori.pagination')]()
122
+ pagination = await this[Symbol.for('satori.pagination')]() as Pagniation
122
123
  return this.next()
123
124
  }
124
125
  result[Symbol.asyncIterator] = function () {
package/src/message.ts CHANGED
@@ -208,13 +208,13 @@ export class LarkMessageEncoder<C extends Context = Context> extends MessageEnco
208
208
  } else if (type === 'at') {
209
209
  if (this.card) {
210
210
  if (attrs.type === 'all') {
211
- this.textContent += `<at id=all>${attrs.name ?? '所有人'}</at>`
211
+ this.textContent += `<at id=all>${attrs.name ?? ''}</at>`
212
212
  } else {
213
213
  this.textContent += `<at id=${attrs.id}>${attrs.name ?? ''}</at>`
214
214
  }
215
215
  } else {
216
216
  if (attrs.type === 'all') {
217
- this.textContent += `<at user_id="all">${attrs.name ?? '所有人'}</at>`
217
+ this.textContent += `<at user_id="all">${attrs.name ?? ''}</at>`
218
218
  } else {
219
219
  this.textContent += `<at user_id="${attrs.id}">${attrs.name ?? ''}</at>`
220
220
  }
@@ -253,7 +253,7 @@ export class LarkMessageEncoder<C extends Context = Context> extends MessageEnco
253
253
  const length = this.card?.elements.length
254
254
  await this.render(children)
255
255
  if (this.card?.elements.length > length) {
256
- const elements = this.card?.elements.slice(length)
256
+ const elements = this.card?.elements.splice(length)
257
257
  this.card.elements.push({
258
258
  tag: 'form',
259
259
  name: attrs.name || 'Form',
@@ -261,24 +261,56 @@ export class LarkMessageEncoder<C extends Context = Context> extends MessageEnco
261
261
  })
262
262
  }
263
263
  } else if (type === 'input') {
264
- this.flushText()
265
- this.card?.elements.push({
266
- tag: 'action',
267
- actions: [{
268
- tag: 'input',
264
+ if (attrs.type === 'checkbox') {
265
+ this.flushText()
266
+ await this.render(children)
267
+ this.card?.elements.push({
268
+ tag: 'checker',
269
269
  name: attrs.name,
270
- width: attrs.width,
271
- label: attrs.label && {
270
+ checked: attrs.checked,
271
+ text: {
272
272
  tag: 'plain_text',
273
- content: attrs.label,
273
+ content: this.textContent,
274
274
  },
275
- placeholder: attrs.placeholder && {
275
+ })
276
+ } else if (attrs.type === 'submit') {
277
+ this.flushText(true)
278
+ await this.render(children)
279
+ this.card?.elements.push({
280
+ tag: 'button',
281
+ name: attrs.name,
282
+ text: {
276
283
  tag: 'plain_text',
277
- content: attrs.placeholder,
284
+ content: this.textContent,
278
285
  },
279
- behaviors: this.createBehavior(attrs),
280
- }],
281
- })
286
+ action_type: 'form_submit',
287
+ value: {
288
+ _satori_type: 'command',
289
+ content: attrs.text,
290
+ },
291
+ })
292
+ } else {
293
+ this.flushText()
294
+ await this.render(children)
295
+ this.card?.elements.push({
296
+ tag: 'action',
297
+ actions: [{
298
+ tag: 'input',
299
+ name: attrs.name,
300
+ width: attrs.width,
301
+ label: this.textContent && {
302
+ tag: 'plain_text',
303
+ content: this.textContent,
304
+ },
305
+ placeholder: attrs.placeholder && {
306
+ tag: 'plain_text',
307
+ content: attrs.placeholder,
308
+ },
309
+ behaviors: this.createBehavior(attrs),
310
+ }],
311
+ })
312
+ }
313
+ this.textContent = ''
282
314
  } else if (type === 'button') {
283
315
  this.card ??= { elements: [] }
284
316
  this.flushText(true)
package/src/utils.ts CHANGED
@@ -168,7 +168,12 @@ export function adaptSender(sender: Sender, session: Session): Session {
168
168
  return session
169
169
  }
170
170
 
171
- export async function adaptMessage(bot: LarkBot, data: Events['im.message.receive_v1'], session: Session, details = true): Promise<Session> {
171
+ export async function adaptMessage<C extends Context = Context>(
172
+ bot: LarkBot<C>,
173
+ data: Events['im.message.receive_v1'],
174
+ session: Session,
175
+ details = true,
176
+ ): Promise<Session> {
172
177
  const json = JSON.parse(data.message.content)
173
178
  const content: (string | h)[] = []
174
179
  switch (data.message.message_type) {
@@ -182,7 +187,7 @@ export async function adaptMessage(bot: LarkBot, data: Events['im.message.receiv
182
187
  // Lark's `at` Element would be `@user_id` in text
183
188
  text.split(' ').forEach((word) => {
184
189
  if (word.startsWith('@')) {
185
- const mention = data.message.mentions.find((mention) => mention.key === word)
190
+ const mention = data.message.mentions.find((mention) => mention.key === word)!
186
191
  content.push(h.at(mention.id.open_id, { name: mention.name }))
187
192
  } else {
188
193
  content.push(word)
@@ -261,17 +266,21 @@ export async function adaptSession<C extends Context>(bot: LarkBot<C>, body: Eve
261
266
  const toArg = (value: any) => {
262
267
  if (typeof value === 'string') {
263
268
  return `'${value}'`
264
- } else if (typeof value === 'number') {
269
+ } else { // number, boolean
265
270
  return value
266
- } else {
267
- return `''`
268
271
  }
269
272
  }
270
273
  for (let i = 0; i < args.length; ++i) {
271
274
  content += ` ${toArg(args[i])}`
272
275
  }
273
276
  for (const [key, value] of Object.entries(options)) {
274
- content += ` --${key} ${toArg(value)}`
277
+ if (value === true) {
278
+ content += ` --${key}`
279
+ } else if (value === false) {
280
+ content += ` --no-${key}`
281
+ } else {
282
+ content += ` --${key} ${toArg(value)}`
283
+ }
275
284
  }
276
285
  if (body.event.action.input_value) {
277
286
  content += ` ${toArg(body.event.action.input_value)}`
@@ -291,8 +300,8 @@ export async function adaptSession<C extends Context>(bot: LarkBot<C>, body: Eve
291
300
  }
292
301
 
293
302
  // TODO: This function has many duplicated code with `adaptMessage`, should refactor them
294
- export async function decodeMessage(bot: LarkBot, body: Message, details = true): Promise<Universal.Message> {
295
- const json = JSON.parse(body.body.content)
303
+ export async function decodeMessage<C extends Context = Context>(bot: LarkBot<C>, body: Message, details = true): Promise<Universal.Message> {
304
+ const json = JSON.parse(body.body!.content)
296
305
  const content: h[] = []
297
306
  switch (body.msg_type) {
298
307
  case 'text': {
@@ -305,7 +314,7 @@ export async function decodeMessage(bot: LarkBot, body: Message, details = true)
305
314
  // Lark's `at` Element would be `@user_id` in text
306
315
  text.split(' ').forEach((word) => {
307
316
  if (word.startsWith('@')) {
308
- const mention = body.mentions.find((mention) => mention.key === word)
317
+ const mention = body.mentions!.find((mention) => mention.key === word)!
309
318
  content.push(h.at(mention.id, { name: mention.name }))
310
319
  } else {
311
320
  content.push(h.text(word))
@@ -314,37 +323,37 @@ export async function decodeMessage(bot: LarkBot, body: Message, details = true)
314
323
  break
315
324
  }
316
325
  case 'image':
317
- content.push(h.image(bot.getResourceUrl('image', body.message_id, json.image_key)))
326
+ content.push(h.image(bot.getResourceUrl('image', body.message_id!, json.image_key)))
318
327
  break
319
328
  case 'audio':
320
- content.push(h.audio(bot.getResourceUrl('file', body.message_id, json.file_key)))
329
+ content.push(h.audio(bot.getResourceUrl('file', body.message_id!, json.file_key)))
321
330
  break
322
331
  case 'media':
323
- content.push(h.video(bot.getResourceUrl('file', body.message_id, json.file_key), {
332
+ content.push(h.video(bot.getResourceUrl('file', body.message_id!, json.file_key), {
324
333
  poster: json.image_key,
325
334
  }))
326
335
  break
327
336
  case 'file':
328
- content.push(h.file(bot.getResourceUrl('file', body.message_id, json.file_key)))
337
+ content.push(h.file(bot.getResourceUrl('file', body.message_id!, json.file_key)))
329
338
  break
330
339
  }
331
340
 
332
341
  return {
333
- timestamp: +body.update_time,
334
- createdAt: +body.create_time,
335
- updatedAt: +body.update_time,
342
+ timestamp: +body.update_time!,
343
+ createdAt: +body.create_time!,
344
+ updatedAt: +body.update_time!,
336
345
  id: body.message_id,
337
346
  messageId: body.message_id,
338
347
  user: {
339
- id: body.sender.id,
348
+ id: body.sender!.id,
340
349
  },
341
350
  channel: {
342
- id: body.chat_id,
351
+ id: body.chat_id!,
343
352
  type: Universal.Channel.Type.TEXT,
344
353
  },
345
354
  content: content.map((c) => c.toString()).join(' '),
346
355
  elements: content,
347
- quote: (body.upper_message_id && details) ? await bot.getMessage(body.chat_id, body.upper_message_id, false) : undefined,
356
+ quote: (body.upper_message_id && details) ? await bot.getMessage(body.chat_id!, body.upper_message_id, false) : undefined,
348
357
  }
349
358
  }
350
359
 
@@ -371,7 +380,7 @@ export function decodeChannel(channelId: string, guild: GetImChatResponse): Univ
371
380
 
372
381
  export function decodeGuild(guild: ListChat): Universal.Guild {
373
382
  return {
374
- id: guild.chat_id,
383
+ id: guild.chat_id!,
375
384
  name: guild.name,
376
385
  avatar: guild.avatar,
377
386
  }
@@ -379,7 +388,7 @@ export function decodeGuild(guild: ListChat): Universal.Guild {
379
388
 
380
389
  export function decodeUser(user: User): Universal.User {
381
390
  return {
382
- id: user.open_id,
391
+ id: user.open_id!,
383
392
  avatar: user.avatar?.avatar_origin,
384
393
  isBot: false,
385
394
  name: user.name,