@openclaw/line 2026.5.2-beta.2 → 2026.5.3-beta.2

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 (109) hide show
  1. package/dist/accounts-UXAvdBo_.js +105 -0
  2. package/dist/api.js +11 -0
  3. package/dist/basic-cards-7DTG6E-A.js +307 -0
  4. package/dist/card-command-UlPc6Vuc.js +240 -0
  5. package/dist/channel-Rls9s60K.js +601 -0
  6. package/dist/channel-plugin-api.js +2 -0
  7. package/dist/channel.runtime-bXoj8_Sl.js +4 -0
  8. package/dist/contract-api.js +2 -0
  9. package/dist/index.js +45 -0
  10. package/dist/markdown-to-line-CCWK6PJh.js +789 -0
  11. package/dist/monitor-B4_RxHc0.js +1523 -0
  12. package/dist/monitor.runtime-DyxYlrM9.js +2 -0
  13. package/dist/outbound-media-BfhBmWq5.js +55 -0
  14. package/dist/outbound.runtime-B-luYwEB.js +2 -0
  15. package/dist/probe-D9BPzb2n.js +30 -0
  16. package/dist/probe.runtime-N91OWW1J.js +2 -0
  17. package/dist/quick-reply-fallback-HskUUWsn.js +55 -0
  18. package/dist/reply-payload-transform-CFGTs9ln.js +713 -0
  19. package/dist/runtime-api.js +277 -0
  20. package/dist/schedule-cards-BwQChTdM.js +359 -0
  21. package/dist/secret-contract-api.js +5 -0
  22. package/dist/setup-api.js +2 -0
  23. package/dist/setup-entry.js +11 -0
  24. package/dist/setup-surface-DCH7CE-y.js +281 -0
  25. package/package.json +14 -6
  26. package/api.ts +0 -11
  27. package/channel-plugin-api.ts +0 -1
  28. package/contract-api.ts +0 -5
  29. package/index.ts +0 -54
  30. package/runtime-api.ts +0 -187
  31. package/secret-contract-api.ts +0 -4
  32. package/setup-api.ts +0 -2
  33. package/setup-entry.ts +0 -9
  34. package/src/account-helpers.ts +0 -16
  35. package/src/accounts.test.ts +0 -290
  36. package/src/accounts.ts +0 -187
  37. package/src/actions.ts +0 -61
  38. package/src/auto-reply-delivery.test.ts +0 -248
  39. package/src/auto-reply-delivery.ts +0 -200
  40. package/src/bindings.ts +0 -65
  41. package/src/bot-access.ts +0 -48
  42. package/src/bot-handlers.test.ts +0 -1089
  43. package/src/bot-handlers.ts +0 -642
  44. package/src/bot-message-context.test.ts +0 -405
  45. package/src/bot-message-context.ts +0 -581
  46. package/src/bot.ts +0 -70
  47. package/src/card-command.ts +0 -347
  48. package/src/channel-access-token.ts +0 -14
  49. package/src/channel-api.ts +0 -17
  50. package/src/channel-setup-status.contract.test.ts +0 -70
  51. package/src/channel-shared.ts +0 -48
  52. package/src/channel.logout.test.ts +0 -145
  53. package/src/channel.runtime.ts +0 -3
  54. package/src/channel.sendPayload.test.ts +0 -514
  55. package/src/channel.setup.ts +0 -11
  56. package/src/channel.status.test.ts +0 -63
  57. package/src/channel.ts +0 -154
  58. package/src/config-adapter.ts +0 -29
  59. package/src/config-schema.ts +0 -57
  60. package/src/download.test.ts +0 -133
  61. package/src/download.ts +0 -87
  62. package/src/flex-templates/basic-cards.ts +0 -395
  63. package/src/flex-templates/common.ts +0 -20
  64. package/src/flex-templates/media-control-cards.ts +0 -555
  65. package/src/flex-templates/message.ts +0 -13
  66. package/src/flex-templates/schedule-cards.ts +0 -467
  67. package/src/flex-templates/types.ts +0 -22
  68. package/src/flex-templates.ts +0 -32
  69. package/src/gateway.ts +0 -129
  70. package/src/group-keys.test.ts +0 -123
  71. package/src/group-keys.ts +0 -65
  72. package/src/group-policy.ts +0 -22
  73. package/src/markdown-to-line.test.ts +0 -348
  74. package/src/markdown-to-line.ts +0 -416
  75. package/src/message-cards.test.ts +0 -204
  76. package/src/monitor.lifecycle.test.ts +0 -421
  77. package/src/monitor.runtime.ts +0 -1
  78. package/src/monitor.ts +0 -506
  79. package/src/outbound-media.test.ts +0 -189
  80. package/src/outbound-media.ts +0 -120
  81. package/src/outbound.runtime.ts +0 -12
  82. package/src/outbound.ts +0 -356
  83. package/src/probe.contract.test.ts +0 -9
  84. package/src/probe.runtime.ts +0 -1
  85. package/src/probe.ts +0 -34
  86. package/src/quick-reply-fallback.ts +0 -10
  87. package/src/reply-chunks.test.ts +0 -179
  88. package/src/reply-chunks.ts +0 -110
  89. package/src/reply-payload-transform.test.ts +0 -387
  90. package/src/reply-payload-transform.ts +0 -317
  91. package/src/rich-menu.test.ts +0 -310
  92. package/src/rich-menu.ts +0 -326
  93. package/src/runtime.ts +0 -32
  94. package/src/send.test.ts +0 -346
  95. package/src/send.ts +0 -489
  96. package/src/setup-core.ts +0 -149
  97. package/src/setup-runtime-api.ts +0 -9
  98. package/src/setup-surface.test.ts +0 -474
  99. package/src/setup-surface.ts +0 -227
  100. package/src/signature.test.ts +0 -34
  101. package/src/signature.ts +0 -24
  102. package/src/status.ts +0 -37
  103. package/src/template-messages.ts +0 -333
  104. package/src/types.ts +0 -128
  105. package/src/webhook-node.test.ts +0 -513
  106. package/src/webhook-node.ts +0 -131
  107. package/src/webhook-utils.ts +0 -10
  108. package/src/webhook.ts +0 -111
  109. package/tsconfig.json +0 -16
@@ -1,34 +0,0 @@
1
- import crypto from "node:crypto";
2
- import { afterEach, describe, expect, it, vi } from "vitest";
3
- import { validateLineSignature } from "./signature.js";
4
-
5
- function sign(body: string, secret: string): string {
6
- return crypto.createHmac("SHA256", secret).update(body).digest("base64");
7
- }
8
-
9
- describe("validateLineSignature", () => {
10
- afterEach(() => {
11
- vi.restoreAllMocks();
12
- });
13
-
14
- it("accepts a valid signature", () => {
15
- const body = JSON.stringify({ events: [{ type: "message" }] });
16
- const secret = "top-secret";
17
-
18
- expect(validateLineSignature(body, sign(body, secret), secret)).toBe(true);
19
- });
20
-
21
- it("still performs timing-safe comparison when signature length mismatches", () => {
22
- const body = JSON.stringify({ events: [{ type: "message" }] });
23
- const secret = "top-secret";
24
- const spy = vi.spyOn(crypto, "timingSafeEqual");
25
-
26
- expect(validateLineSignature(body, "short", secret)).toBe(false);
27
- expect(spy).toHaveBeenCalledTimes(1);
28
-
29
- const [left, right] = spy.mock.calls[0] ?? [];
30
- expect(left).toBeInstanceOf(Buffer);
31
- expect(right).toBeInstanceOf(Buffer);
32
- expect(left?.byteLength).toBe(right?.byteLength);
33
- });
34
- });
package/src/signature.ts DELETED
@@ -1,24 +0,0 @@
1
- import crypto from "node:crypto";
2
-
3
- export function validateLineSignature(
4
- body: string,
5
- signature: string,
6
- channelSecret: string,
7
- ): boolean {
8
- const hash = crypto.createHmac("SHA256", channelSecret).update(body).digest("base64");
9
- const hashBuffer = Buffer.from(hash);
10
- const signatureBuffer = Buffer.from(signature);
11
-
12
- // Pad to equal length before constant-time comparison to prevent
13
- // leaking length information via early-return timing.
14
- const maxLen = Math.max(hashBuffer.length, signatureBuffer.length);
15
- const paddedHash = Buffer.alloc(maxLen);
16
- const paddedSig = Buffer.alloc(maxLen);
17
- hashBuffer.copy(paddedHash);
18
- signatureBuffer.copy(paddedSig);
19
-
20
- // Call timingSafeEqual unconditionally to ensure constant-time execution
21
- // regardless of length mismatch (avoids && short-circuit timing leak).
22
- const timingResult = crypto.timingSafeEqual(paddedHash, paddedSig);
23
- return hashBuffer.length === signatureBuffer.length && timingResult;
24
- }
package/src/status.ts DELETED
@@ -1,37 +0,0 @@
1
- import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
2
- import {
3
- buildTokenChannelStatusSummary,
4
- createComputedAccountStatusAdapter,
5
- createDefaultChannelRuntimeState,
6
- createDependentCredentialStatusIssueCollector,
7
- } from "openclaw/plugin-sdk/status-helpers";
8
- import { hasLineCredentials } from "./account-helpers.js";
9
- import { DEFAULT_ACCOUNT_ID, type ChannelPlugin, type ResolvedLineAccount } from "./channel-api.js";
10
-
11
- const loadLineProbeRuntime = createLazyRuntimeModule(() => import("./probe.runtime.js"));
12
-
13
- const collectLineStatusIssues = createDependentCredentialStatusIssueCollector({
14
- channel: "line",
15
- dependencySourceKey: "tokenSource",
16
- missingPrimaryMessage: "LINE channel access token not configured",
17
- missingDependentMessage: "LINE channel secret not configured",
18
- });
19
-
20
- export const lineStatusAdapter: NonNullable<ChannelPlugin<ResolvedLineAccount>["status"]> =
21
- createComputedAccountStatusAdapter<ResolvedLineAccount>({
22
- defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
23
- collectStatusIssues: collectLineStatusIssues,
24
- buildChannelSummary: ({ snapshot }) => buildTokenChannelStatusSummary(snapshot),
25
- probeAccount: async ({ account, timeoutMs }) =>
26
- await (await loadLineProbeRuntime()).probeLineBot(account.channelAccessToken, timeoutMs),
27
- resolveAccountSnapshot: ({ account }) => ({
28
- accountId: account.accountId,
29
- name: account.name,
30
- enabled: account.enabled,
31
- configured: hasLineCredentials(account),
32
- extra: {
33
- tokenSource: account.tokenSource,
34
- mode: "webhook",
35
- },
36
- }),
37
- });
@@ -1,333 +0,0 @@
1
- import type { messagingApi } from "@line/bot-sdk";
2
- import { messageAction, postbackAction, uriAction, type Action } from "./actions.js";
3
- import type { LineTemplateMessagePayload } from "./types.js";
4
-
5
- export { messageAction };
6
-
7
- type TemplateMessage = messagingApi.TemplateMessage;
8
- type ConfirmTemplate = messagingApi.ConfirmTemplate;
9
- type ButtonsTemplate = messagingApi.ButtonsTemplate;
10
- type CarouselTemplate = messagingApi.CarouselTemplate;
11
- type CarouselColumn = messagingApi.CarouselColumn;
12
- type ImageCarouselTemplate = messagingApi.ImageCarouselTemplate;
13
- type ImageCarouselColumn = messagingApi.ImageCarouselColumn;
14
-
15
- type TemplatePayloadAction = {
16
- type?: "uri" | "postback" | "message";
17
- uri?: string;
18
- data?: string;
19
- label: string;
20
- };
21
-
22
- function buildTemplatePayloadAction(action: TemplatePayloadAction): Action {
23
- if (action.type === "uri" && action.uri) {
24
- return uriAction(action.label, action.uri);
25
- }
26
- if (action.type === "postback" && action.data) {
27
- return postbackAction(action.label, action.data, action.label);
28
- }
29
- return messageAction(action.label, action.data ?? action.label);
30
- }
31
-
32
- /**
33
- * Create a confirm template (yes/no style dialog)
34
- */
35
- export function createConfirmTemplate(
36
- text: string,
37
- confirmAction: Action,
38
- cancelAction: Action,
39
- altText?: string,
40
- ): TemplateMessage {
41
- const template: ConfirmTemplate = {
42
- type: "confirm",
43
- text: text.slice(0, 240), // LINE limit
44
- actions: [confirmAction, cancelAction],
45
- };
46
-
47
- return {
48
- type: "template",
49
- altText: altText?.slice(0, 400) ?? text.slice(0, 400),
50
- template,
51
- };
52
- }
53
-
54
- /**
55
- * Create a button template with title, text, and action buttons
56
- */
57
- export function createButtonTemplate(
58
- title: string,
59
- text: string,
60
- actions: Action[],
61
- options?: {
62
- thumbnailImageUrl?: string;
63
- imageAspectRatio?: "rectangle" | "square";
64
- imageSize?: "cover" | "contain";
65
- imageBackgroundColor?: string;
66
- defaultAction?: Action;
67
- altText?: string;
68
- },
69
- ): TemplateMessage {
70
- const hasThumbnail = Boolean(options?.thumbnailImageUrl?.trim());
71
- const textLimit = hasThumbnail ? 160 : 60;
72
- const template: ButtonsTemplate = {
73
- type: "buttons",
74
- title: title.slice(0, 40), // LINE limit
75
- text: text.slice(0, textLimit), // LINE limit (60 if no thumbnail, 160 with thumbnail)
76
- actions: actions.slice(0, 4), // LINE limit: max 4 actions
77
- thumbnailImageUrl: options?.thumbnailImageUrl,
78
- imageAspectRatio: options?.imageAspectRatio ?? "rectangle",
79
- imageSize: options?.imageSize ?? "cover",
80
- imageBackgroundColor: options?.imageBackgroundColor,
81
- defaultAction: options?.defaultAction,
82
- };
83
-
84
- return {
85
- type: "template",
86
- altText: options?.altText?.slice(0, 400) ?? `${title}: ${text}`.slice(0, 400),
87
- template,
88
- };
89
- }
90
-
91
- /**
92
- * Create a carousel template with multiple columns
93
- */
94
- export function createTemplateCarousel(
95
- columns: CarouselColumn[],
96
- options?: {
97
- imageAspectRatio?: "rectangle" | "square";
98
- imageSize?: "cover" | "contain";
99
- altText?: string;
100
- },
101
- ): TemplateMessage {
102
- const template: CarouselTemplate = {
103
- type: "carousel",
104
- columns: columns.slice(0, 10), // LINE limit: max 10 columns
105
- imageAspectRatio: options?.imageAspectRatio ?? "rectangle",
106
- imageSize: options?.imageSize ?? "cover",
107
- };
108
-
109
- return {
110
- type: "template",
111
- altText: options?.altText?.slice(0, 400) ?? "View carousel",
112
- template,
113
- };
114
- }
115
-
116
- /**
117
- * Create a carousel column for use with createTemplateCarousel
118
- */
119
- export function createCarouselColumn(params: {
120
- title?: string;
121
- text: string;
122
- actions: Action[];
123
- thumbnailImageUrl?: string;
124
- imageBackgroundColor?: string;
125
- defaultAction?: Action;
126
- }): CarouselColumn {
127
- return {
128
- title: params.title?.slice(0, 40),
129
- text: params.text.slice(0, 120), // LINE limit
130
- actions: params.actions.slice(0, 3), // LINE limit: max 3 actions per column
131
- thumbnailImageUrl: params.thumbnailImageUrl,
132
- imageBackgroundColor: params.imageBackgroundColor,
133
- defaultAction: params.defaultAction,
134
- };
135
- }
136
-
137
- /**
138
- * Create an image carousel template (simpler, image-focused carousel)
139
- */
140
- export function createImageCarousel(
141
- columns: ImageCarouselColumn[],
142
- altText?: string,
143
- ): TemplateMessage {
144
- const template: ImageCarouselTemplate = {
145
- type: "image_carousel",
146
- columns: columns.slice(0, 10), // LINE limit: max 10 columns
147
- };
148
-
149
- return {
150
- type: "template",
151
- altText: altText?.slice(0, 400) ?? "View images",
152
- template,
153
- };
154
- }
155
-
156
- /**
157
- * Create an image carousel column for use with createImageCarousel
158
- */
159
- export function createImageCarouselColumn(imageUrl: string, action: Action): ImageCarouselColumn {
160
- return {
161
- imageUrl,
162
- action,
163
- };
164
- }
165
-
166
- /**
167
- * Create a simple yes/no confirmation dialog
168
- */
169
- export function createYesNoConfirm(
170
- question: string,
171
- options?: {
172
- yesText?: string;
173
- noText?: string;
174
- yesData?: string;
175
- noData?: string;
176
- altText?: string;
177
- },
178
- ): TemplateMessage {
179
- const yesAction: Action = options?.yesData
180
- ? postbackAction(options.yesText ?? "Yes", options.yesData, options.yesText ?? "Yes")
181
- : messageAction(options?.yesText ?? "Yes");
182
-
183
- const noAction: Action = options?.noData
184
- ? postbackAction(options.noText ?? "No", options.noData, options.noText ?? "No")
185
- : messageAction(options?.noText ?? "No");
186
-
187
- return createConfirmTemplate(question, yesAction, noAction, options?.altText);
188
- }
189
-
190
- /**
191
- * Create a button menu with simple text buttons
192
- */
193
- export function createButtonMenu(
194
- title: string,
195
- text: string,
196
- buttons: Array<{ label: string; text?: string }>,
197
- options?: {
198
- thumbnailImageUrl?: string;
199
- altText?: string;
200
- },
201
- ): TemplateMessage {
202
- const actions = buttons.slice(0, 4).map((btn) => messageAction(btn.label, btn.text));
203
-
204
- return createButtonTemplate(title, text, actions, {
205
- thumbnailImageUrl: options?.thumbnailImageUrl,
206
- altText: options?.altText,
207
- });
208
- }
209
-
210
- /**
211
- * Create a button menu with URL links
212
- */
213
- export function createLinkMenu(
214
- title: string,
215
- text: string,
216
- links: Array<{ label: string; url: string }>,
217
- options?: {
218
- thumbnailImageUrl?: string;
219
- altText?: string;
220
- },
221
- ): TemplateMessage {
222
- const actions = links.slice(0, 4).map((link) => uriAction(link.label, link.url));
223
-
224
- return createButtonTemplate(title, text, actions, {
225
- thumbnailImageUrl: options?.thumbnailImageUrl,
226
- altText: options?.altText,
227
- });
228
- }
229
-
230
- /**
231
- * Create a simple product/item carousel
232
- */
233
- export function createProductCarousel(
234
- products: Array<{
235
- title: string;
236
- description: string;
237
- imageUrl?: string;
238
- price?: string;
239
- actionLabel?: string;
240
- actionUrl?: string;
241
- actionData?: string;
242
- }>,
243
- altText?: string,
244
- ): TemplateMessage {
245
- const columns = products.slice(0, 10).map((product) => {
246
- const actions: Action[] = [];
247
-
248
- if (product.actionUrl) {
249
- actions.push(uriAction(product.actionLabel ?? "View", product.actionUrl));
250
- } else if (product.actionData) {
251
- actions.push(postbackAction(product.actionLabel ?? "Select", product.actionData));
252
- } else {
253
- actions.push(messageAction(product.actionLabel ?? "Select", product.title));
254
- }
255
-
256
- return createCarouselColumn({
257
- title: product.title,
258
- text: product.price
259
- ? `${product.description}\n${product.price}`.slice(0, 120)
260
- : product.description,
261
- thumbnailImageUrl: product.imageUrl,
262
- actions,
263
- });
264
- });
265
-
266
- return createTemplateCarousel(columns, { altText });
267
- }
268
-
269
- /**
270
- * Convert a TemplateMessagePayload from ReplyPayload to a LINE TemplateMessage
271
- */
272
- export function buildTemplateMessageFromPayload(
273
- payload: LineTemplateMessagePayload,
274
- ): TemplateMessage | null {
275
- switch (payload.type) {
276
- case "confirm": {
277
- const confirmAction = payload.confirmData.startsWith("http")
278
- ? uriAction(payload.confirmLabel, payload.confirmData)
279
- : payload.confirmData.includes("=")
280
- ? postbackAction(payload.confirmLabel, payload.confirmData, payload.confirmLabel)
281
- : messageAction(payload.confirmLabel, payload.confirmData);
282
-
283
- const cancelAction = payload.cancelData.startsWith("http")
284
- ? uriAction(payload.cancelLabel, payload.cancelData)
285
- : payload.cancelData.includes("=")
286
- ? postbackAction(payload.cancelLabel, payload.cancelData, payload.cancelLabel)
287
- : messageAction(payload.cancelLabel, payload.cancelData);
288
-
289
- return createConfirmTemplate(payload.text, confirmAction, cancelAction, payload.altText);
290
- }
291
-
292
- case "buttons": {
293
- const actions: Action[] = payload.actions
294
- .slice(0, 4)
295
- .map((action) => buildTemplatePayloadAction(action));
296
-
297
- return createButtonTemplate(payload.title, payload.text, actions, {
298
- thumbnailImageUrl: payload.thumbnailImageUrl,
299
- altText: payload.altText,
300
- });
301
- }
302
-
303
- case "carousel": {
304
- const columns: CarouselColumn[] = payload.columns.slice(0, 10).map((col) => {
305
- const colActions: Action[] = col.actions
306
- .slice(0, 3)
307
- .map((action) => buildTemplatePayloadAction(action));
308
-
309
- return createCarouselColumn({
310
- title: col.title,
311
- text: col.text,
312
- thumbnailImageUrl: col.thumbnailImageUrl,
313
- actions: colActions,
314
- });
315
- });
316
-
317
- return createTemplateCarousel(columns, { altText: payload.altText });
318
- }
319
-
320
- default:
321
- return null;
322
- }
323
- }
324
-
325
- export type {
326
- TemplateMessage,
327
- ConfirmTemplate,
328
- ButtonsTemplate,
329
- CarouselTemplate,
330
- CarouselColumn,
331
- ImageCarouselTemplate,
332
- ImageCarouselColumn,
333
- };
package/src/types.ts DELETED
@@ -1,128 +0,0 @@
1
- import type { BaseProbeResult } from "openclaw/plugin-sdk/channel-contract";
2
-
3
- export type LineTokenSource = "config" | "env" | "file" | "none";
4
-
5
- interface LineThreadBindingsConfig {
6
- enabled?: boolean;
7
- idleHours?: number;
8
- maxAgeHours?: number;
9
- spawnSessions?: boolean;
10
- defaultSpawnContext?: "isolated" | "fork";
11
- /** @deprecated Use spawnSessions instead. */
12
- spawnSubagentSessions?: boolean;
13
- /** @deprecated Use spawnSessions instead. */
14
- spawnAcpSessions?: boolean;
15
- }
16
-
17
- interface LineAccountBaseConfig {
18
- enabled?: boolean;
19
- channelAccessToken?: string;
20
- channelSecret?: string;
21
- tokenFile?: string;
22
- secretFile?: string;
23
- name?: string;
24
- allowFrom?: Array<string | number>;
25
- groupAllowFrom?: Array<string | number>;
26
- dmPolicy?: "open" | "allowlist" | "pairing" | "disabled";
27
- groupPolicy?: "open" | "allowlist" | "disabled";
28
- responsePrefix?: string;
29
- mediaMaxMb?: number;
30
- webhookPath?: string;
31
- threadBindings?: LineThreadBindingsConfig;
32
- groups?: Record<string, LineGroupConfig>;
33
- }
34
-
35
- export interface LineConfig extends LineAccountBaseConfig {
36
- accounts?: Record<string, LineAccountConfig>;
37
- defaultAccount?: string;
38
- }
39
-
40
- export interface LineAccountConfig extends LineAccountBaseConfig {}
41
-
42
- export interface LineGroupConfig {
43
- enabled?: boolean;
44
- allowFrom?: Array<string | number>;
45
- requireMention?: boolean;
46
- systemPrompt?: string;
47
- skills?: string[];
48
- }
49
-
50
- export interface ResolvedLineAccount {
51
- accountId: string;
52
- name?: string;
53
- enabled: boolean;
54
- channelAccessToken: string;
55
- channelSecret: string;
56
- tokenSource: LineTokenSource;
57
- config: LineConfig & LineAccountConfig;
58
- }
59
-
60
- export interface LineSendResult {
61
- messageId: string;
62
- chatId: string;
63
- }
64
-
65
- export type LineProbeResult = BaseProbeResult<string> & {
66
- bot?: {
67
- displayName?: string;
68
- userId?: string;
69
- basicId?: string;
70
- pictureUrl?: string;
71
- };
72
- };
73
-
74
- type LineFlexMessagePayload = {
75
- altText: string;
76
- contents: unknown;
77
- };
78
-
79
- export type LineTemplateMessagePayload =
80
- | {
81
- type: "confirm";
82
- text: string;
83
- confirmLabel: string;
84
- confirmData: string;
85
- cancelLabel: string;
86
- cancelData: string;
87
- altText?: string;
88
- }
89
- | {
90
- type: "buttons";
91
- title: string;
92
- text: string;
93
- actions: Array<{
94
- type: "message" | "uri" | "postback";
95
- label: string;
96
- data?: string;
97
- uri?: string;
98
- }>;
99
- thumbnailImageUrl?: string;
100
- altText?: string;
101
- }
102
- | {
103
- type: "carousel";
104
- columns: Array<{
105
- title?: string;
106
- text: string;
107
- thumbnailImageUrl?: string;
108
- actions: Array<{
109
- type: "message" | "uri" | "postback";
110
- label: string;
111
- data?: string;
112
- uri?: string;
113
- }>;
114
- }>;
115
- altText?: string;
116
- };
117
-
118
- export type LineChannelData = {
119
- quickReplies?: string[];
120
- location?: {
121
- title: string;
122
- address: string;
123
- latitude: number;
124
- longitude: number;
125
- };
126
- flexMessage?: LineFlexMessagePayload;
127
- templateMessage?: LineTemplateMessagePayload;
128
- };