@satorijs/adapter-lark 3.9.4 → 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 +1 -4
- package/lib/content.d.ts +4 -1
- package/lib/index.cjs +81 -37
- package/lib/internal.d.ts +3 -3
- package/lib/utils.d.ts +2 -2
- package/package.json +2 -2
- package/src/bot.ts +20 -23
- package/src/content.ts +5 -0
- package/src/http.ts +4 -1
- package/src/internal.ts +7 -6
- package/src/message.ts +57 -17
- package/src/utils.ts +30 -21
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
|
-
|
|
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 };
|
|
@@ -574,10 +579,18 @@ var LarkMessageEncoder = class extends import_core3.MessageEncoder {
|
|
|
574
579
|
if (type === "text") {
|
|
575
580
|
this.textContent += attrs.content;
|
|
576
581
|
} else if (type === "at") {
|
|
577
|
-
if (
|
|
578
|
-
|
|
582
|
+
if (this.card) {
|
|
583
|
+
if (attrs.type === "all") {
|
|
584
|
+
this.textContent += `<at id=all>${attrs.name ?? ""}</at>`;
|
|
585
|
+
} else {
|
|
586
|
+
this.textContent += `<at id=${attrs.id}>${attrs.name ?? ""}</at>`;
|
|
587
|
+
}
|
|
579
588
|
} else {
|
|
580
|
-
|
|
589
|
+
if (attrs.type === "all") {
|
|
590
|
+
this.textContent += `<at user_id="all">${attrs.name ?? ""}</at>`;
|
|
591
|
+
} else {
|
|
592
|
+
this.textContent += `<at user_id="${attrs.id}">${attrs.name ?? ""}</at>`;
|
|
593
|
+
}
|
|
581
594
|
}
|
|
582
595
|
} else if (type === "a") {
|
|
583
596
|
await this.render(children);
|
|
@@ -612,7 +625,7 @@ var LarkMessageEncoder = class extends import_core3.MessageEncoder {
|
|
|
612
625
|
const length = this.card?.elements.length;
|
|
613
626
|
await this.render(children);
|
|
614
627
|
if (this.card?.elements.length > length) {
|
|
615
|
-
const elements = this.card?.elements.
|
|
628
|
+
const elements = this.card?.elements.splice(length);
|
|
616
629
|
this.card.elements.push({
|
|
617
630
|
tag: "form",
|
|
618
631
|
name: attrs.name || "Form",
|
|
@@ -620,24 +633,56 @@ var LarkMessageEncoder = class extends import_core3.MessageEncoder {
|
|
|
620
633
|
});
|
|
621
634
|
}
|
|
622
635
|
} else if (type === "input") {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
tag: "
|
|
636
|
+
if (attrs.type === "checkbox") {
|
|
637
|
+
this.flushText();
|
|
638
|
+
await this.render(children);
|
|
639
|
+
this.card?.elements.push({
|
|
640
|
+
tag: "checker",
|
|
628
641
|
name: attrs.name,
|
|
629
|
-
|
|
630
|
-
|
|
642
|
+
checked: attrs.checked,
|
|
643
|
+
text: {
|
|
631
644
|
tag: "plain_text",
|
|
632
|
-
content:
|
|
633
|
-
}
|
|
634
|
-
|
|
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: {
|
|
635
655
|
tag: "plain_text",
|
|
636
|
-
content:
|
|
656
|
+
content: this.textContent
|
|
637
657
|
},
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
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 = "";
|
|
641
686
|
} else if (type === "button") {
|
|
642
687
|
this.card ??= { elements: [] };
|
|
643
688
|
this.flushText(true);
|
|
@@ -875,7 +920,6 @@ var LarkBot = class extends import_core5.Bot {
|
|
|
875
920
|
}
|
|
876
921
|
static inject = ["server", "http"];
|
|
877
922
|
static MessageEncoder = LarkMessageEncoder;
|
|
878
|
-
_token;
|
|
879
923
|
_refresher;
|
|
880
924
|
http;
|
|
881
925
|
assetsQuester;
|
|
@@ -916,23 +960,23 @@ var LarkBot = class extends import_core5.Bot {
|
|
|
916
960
|
this.online();
|
|
917
961
|
}
|
|
918
962
|
async refreshToken() {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
963
|
+
let timeout = import_core5.Time.minute * 20;
|
|
964
|
+
try {
|
|
965
|
+
const { tenant_access_token: token } = await this.internal.tenantAccessTokenInternalAuth({
|
|
966
|
+
app_id: this.config.appId,
|
|
967
|
+
app_secret: this.config.appSecret
|
|
968
|
+
});
|
|
969
|
+
this.logger.debug("refreshed token %s", token);
|
|
970
|
+
this.http.config.headers.Authorization = `Bearer ${token}`;
|
|
971
|
+
} catch (error) {
|
|
972
|
+
this.logger.error("failed to refresh token, retrying in 10s");
|
|
973
|
+
this.logger.error(error);
|
|
974
|
+
timeout = import_core5.Time.second * 10;
|
|
975
|
+
}
|
|
925
976
|
if (this._refresher) clearTimeout(this._refresher);
|
|
926
|
-
this._refresher = setTimeout(() => this.refreshToken(),
|
|
977
|
+
this._refresher = setTimeout(() => this.refreshToken(), timeout);
|
|
927
978
|
this.online();
|
|
928
979
|
}
|
|
929
|
-
get token() {
|
|
930
|
-
return this._token;
|
|
931
|
-
}
|
|
932
|
-
set token(v) {
|
|
933
|
-
this._token = v;
|
|
934
|
-
this.http.config.headers.Authorization = `Bearer ${v}`;
|
|
935
|
-
}
|
|
936
980
|
async editMessage(channelId, messageId, content) {
|
|
937
981
|
const encoder = new LarkMessageEncoder(this, channelId);
|
|
938
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
|
|
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
|
|
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.
|
|
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.
|
|
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')
|
|
@@ -74,31 +73,29 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
|
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
private async refreshToken() {
|
|
77
|
-
const { tenant_access_token: token } = await this.internal.tenantAccessTokenInternalAuth({
|
|
78
|
-
app_id: this.config.appId,
|
|
79
|
-
app_secret: this.config.appSecret,
|
|
80
|
-
})
|
|
81
|
-
this.logger.debug('refreshed token %s', token)
|
|
82
|
-
this.token = token
|
|
83
|
-
if (this._refresher) clearTimeout(this._refresher)
|
|
84
76
|
// https://open.feishu.cn/document/server-docs/authentication-management/access-token/tenant_access_token_internal
|
|
85
77
|
// tenant_access_token 的最大有效期是 2 小时。
|
|
86
78
|
// 剩余有效期小于 30 分钟时,调用本接口会返回一个新的 tenant_access_token,此时会同时存在两个有效的 tenant_access_token。
|
|
87
79
|
// 剩余有效期大于等于 30 分钟时,调用本接口会返回原有的 tenant_access_token。
|
|
88
80
|
// 初次获得 token 后的半小时内必须刷新一次,因为初次获得的 token 可能是 1.5 小时前生成的。
|
|
89
|
-
|
|
81
|
+
let timeout = Time.minute * 20
|
|
82
|
+
try {
|
|
83
|
+
const { tenant_access_token: token } = await this.internal.tenantAccessTokenInternalAuth({
|
|
84
|
+
app_id: this.config.appId,
|
|
85
|
+
app_secret: this.config.appSecret,
|
|
86
|
+
})
|
|
87
|
+
this.logger.debug('refreshed token %s', token)
|
|
88
|
+
this.http.config.headers!.Authorization = `Bearer ${token}`
|
|
89
|
+
} catch (error) {
|
|
90
|
+
this.logger.error('failed to refresh token, retrying in 10s')
|
|
91
|
+
this.logger.error(error)
|
|
92
|
+
timeout = Time.second * 10
|
|
93
|
+
}
|
|
94
|
+
if (this._refresher) clearTimeout(this._refresher)
|
|
95
|
+
this._refresher = setTimeout(() => this.refreshToken(), timeout)
|
|
90
96
|
this.online()
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
get token() {
|
|
94
|
-
return this._token
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
set token(v: string) {
|
|
98
|
-
this._token = v
|
|
99
|
-
this.http.config.headers.Authorization = `Bearer ${v}`
|
|
100
|
-
}
|
|
101
|
-
|
|
102
99
|
async editMessage(channelId: string, messageId: string, content: h.Fragment) {
|
|
103
100
|
const encoder = new LarkMessageEncoder(this, channelId)
|
|
104
101
|
encoder.editMessageIds = [messageId]
|
|
@@ -111,9 +108,9 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
|
|
|
111
108
|
|
|
112
109
|
async getMessage(channelId: string, messageId: string, recursive = true) {
|
|
113
110
|
const data = await this.internal.getImMessage(messageId)
|
|
114
|
-
const message = await Utils.decodeMessage(this, data.items[0], recursive)
|
|
111
|
+
const message = await Utils.decodeMessage(this, data.items![0], recursive)
|
|
115
112
|
const im = await this.internal.getImChat(channelId)
|
|
116
|
-
message.channel
|
|
113
|
+
message.channel!.type = im.chat_mode === 'p2p' ? Universal.Channel.Type.DIRECT : Universal.Channel.Type.TEXT
|
|
117
114
|
return message
|
|
118
115
|
}
|
|
119
116
|
|
|
@@ -125,7 +122,7 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
|
|
|
125
122
|
|
|
126
123
|
async getUser(userId: string, guildId?: string) {
|
|
127
124
|
const data = await this.internal.getContactUser(userId)
|
|
128
|
-
return Utils.decodeUser(data.user)
|
|
125
|
+
return Utils.decodeUser(data.user!)
|
|
129
126
|
}
|
|
130
127
|
|
|
131
128
|
async getChannel(channelId: string) {
|
|
@@ -149,7 +146,7 @@ export class LarkBot<C extends Context = Context> extends Bot<C, LarkBot.Config>
|
|
|
149
146
|
|
|
150
147
|
async getGuildMemberList(guildId: string, after?: string) {
|
|
151
148
|
const members = await this.internal.getImChatMembers(guildId, { page_token: after })
|
|
152
|
-
const data = members.items
|
|
149
|
+
const data = members.items!.map(v => ({ user: { id: v.member_id, name: v.name }, name: v.name }))
|
|
153
150
|
return { data, next: members.page_token }
|
|
154
151
|
}
|
|
155
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
|
-
|
|
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
|
@@ -206,10 +206,18 @@ export class LarkMessageEncoder<C extends Context = Context> extends MessageEnco
|
|
|
206
206
|
if (type === 'text') {
|
|
207
207
|
this.textContent += attrs.content
|
|
208
208
|
} else if (type === 'at') {
|
|
209
|
-
if (
|
|
210
|
-
|
|
209
|
+
if (this.card) {
|
|
210
|
+
if (attrs.type === 'all') {
|
|
211
|
+
this.textContent += `<at id=all>${attrs.name ?? ''}</at>`
|
|
212
|
+
} else {
|
|
213
|
+
this.textContent += `<at id=${attrs.id}>${attrs.name ?? ''}</at>`
|
|
214
|
+
}
|
|
211
215
|
} else {
|
|
212
|
-
|
|
216
|
+
if (attrs.type === 'all') {
|
|
217
|
+
this.textContent += `<at user_id="all">${attrs.name ?? ''}</at>`
|
|
218
|
+
} else {
|
|
219
|
+
this.textContent += `<at user_id="${attrs.id}">${attrs.name ?? ''}</at>`
|
|
220
|
+
}
|
|
213
221
|
}
|
|
214
222
|
} else if (type === 'a') {
|
|
215
223
|
await this.render(children)
|
|
@@ -245,7 +253,7 @@ export class LarkMessageEncoder<C extends Context = Context> extends MessageEnco
|
|
|
245
253
|
const length = this.card?.elements.length
|
|
246
254
|
await this.render(children)
|
|
247
255
|
if (this.card?.elements.length > length) {
|
|
248
|
-
const elements = this.card?.elements.
|
|
256
|
+
const elements = this.card?.elements.splice(length)
|
|
249
257
|
this.card.elements.push({
|
|
250
258
|
tag: 'form',
|
|
251
259
|
name: attrs.name || 'Form',
|
|
@@ -253,24 +261,56 @@ export class LarkMessageEncoder<C extends Context = Context> extends MessageEnco
|
|
|
253
261
|
})
|
|
254
262
|
}
|
|
255
263
|
} else if (type === 'input') {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
tag: '
|
|
264
|
+
if (attrs.type === 'checkbox') {
|
|
265
|
+
this.flushText()
|
|
266
|
+
await this.render(children)
|
|
267
|
+
this.card?.elements.push({
|
|
268
|
+
tag: 'checker',
|
|
261
269
|
name: attrs.name,
|
|
262
|
-
|
|
263
|
-
|
|
270
|
+
checked: attrs.checked,
|
|
271
|
+
text: {
|
|
264
272
|
tag: 'plain_text',
|
|
265
|
-
content:
|
|
273
|
+
content: this.textContent,
|
|
266
274
|
},
|
|
267
|
-
|
|
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: {
|
|
268
283
|
tag: 'plain_text',
|
|
269
|
-
content:
|
|
284
|
+
content: this.textContent,
|
|
270
285
|
},
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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 = ''
|
|
274
314
|
} else if (type === 'button') {
|
|
275
315
|
this.card ??= { elements: [] }
|
|
276
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
|
|
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
|
|
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
|
-
|
|
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
|
|
295
|
-
const json = JSON.parse(body.body
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|