@openclaw/line 2026.7.2-beta.7 → 2026.7.34
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 +1 -1
- package/dist/.setup/accounts-DJVOv1JI.mjs +107 -0
- package/dist/.setup/api-D3h9w6oz.mjs +3 -0
- package/dist/.setup/api-DdlGHKoX.mjs +11 -0
- package/dist/.setup/basic-cards-C8Qwh2X1.mjs +307 -0
- package/dist/{card-command-ty11OJNt.js → .setup/card-command-CWrkUiGY.mjs} +51 -23
- package/dist/{channel-D4i_K4fQ.js → .setup/channel-Du0PrvOH.mjs} +76 -66
- package/dist/.setup/channel.runtime-b3suPB-W.mjs +4 -0
- package/dist/.setup/flex-templates-BP6VHjzK.mjs +814 -0
- package/dist/{markdown-to-line-DMDQTMhx.js → .setup/markdown-to-line-o89GT1Qn.mjs} +252 -254
- package/dist/{monitor-DXEodYFJ.js → .setup/monitor-DpxjN6Ks.mjs} +491 -658
- package/dist/.setup/monitor.runtime-BS-cGD5Q.mjs +2 -0
- package/dist/.setup/outbound.runtime-BeNDuEIF.mjs +2 -0
- package/dist/{probe-CM03wo6r.js → .setup/probe-BslD77tJ.mjs} +9 -7
- package/dist/.setup/probe.runtime-YwWmWIlk.mjs +2 -0
- package/dist/{reply-payload-transform-D5-dHB8b.js → .setup/reply-payload-transform-CYQIy_x8.mjs} +204 -80
- package/dist/{setup-surface-DRQ7n0En.js → .setup/setup-surface-M1ivmZ-G.mjs} +143 -158
- package/dist/api.js +2 -11
- package/dist/channel-plugin-api.js +1 -1
- package/dist/contract-api.js +1 -1
- package/dist/index.js +1 -1
- package/dist/runtime-api.js +56 -15
- package/dist/setup-api.js +1 -1
- package/dist/setup-entry.js +2 -1
- package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupCreateRoute.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupFailedType.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupJobFailedType.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupJobStatus.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/manage-audience/model/audienceGroupStatus.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexBoxBorderWidth.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexBoxCornerRadius.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexBubble.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexIconSize.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexSpanSize.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/flexTextFontSize.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/numberOfMessagesResponse.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/postbackAction.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/messaging-api/model/subscriptionPeriodDemographic.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/version.d.ts +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/version.js +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/event.d.ts +1 -2
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/event.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.d.ts +0 -1
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.js +0 -1
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/models.js.map +1 -1
- package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupCreateRoute.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupFailedType.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupJobFailedType.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupJobStatus.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/manage-audience/model/audienceGroupStatus.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexBoxBorderWidth.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexBoxCornerRadius.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexBubble.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexIconSize.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexSpanSize.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/flexTextFontSize.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/numberOfMessagesResponse.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/postbackAction.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/messaging-api/model/subscriptionPeriodDemographic.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/version.d.ts +1 -1
- package/node_modules/@line/bot-sdk/dist/version.js +1 -1
- package/node_modules/@line/bot-sdk/dist/webhook/model/event.d.ts +1 -2
- package/node_modules/@line/bot-sdk/dist/webhook/model/event.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/webhook/model/models.d.ts +0 -1
- package/node_modules/@line/bot-sdk/dist/webhook/model/models.d.ts.map +1 -1
- package/node_modules/@line/bot-sdk/dist/webhook/model/models.js +0 -1
- package/node_modules/@line/bot-sdk/dist/webhook/model/models.js.map +1 -1
- package/node_modules/@line/bot-sdk/lib/insight/model/getNumberOfFollowersResponse.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/liff/model/liffScope.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupCreateRoute.ts +4 -1
- package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupFailedType.ts +2 -1
- package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupJobFailedType.ts +2 -1
- package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupJobStatus.ts +4 -1
- package/node_modules/@line/bot-sdk/lib/manage-audience/model/audienceGroupStatus.ts +6 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/botInfoResponse.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexBoxBorderWidth.ts +6 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexBoxCornerRadius.ts +7 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexBubble.ts +7 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexIconSize.ts +10 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexSpanSize.ts +10 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/flexTextFontSize.ts +10 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/getAggregationUnitNameListResponse.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/getFollowersResponse.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/getJoinedMembershipUsersResponse.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/issueLinkTokenResponse.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/numberOfMessagesResponse.ts +5 -2
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/postbackAction.ts +4 -1
- package/node_modules/@line/bot-sdk/lib/messaging-api/model/subscriptionPeriodDemographic.ts +5 -1
- package/node_modules/@line/bot-sdk/lib/version.ts +1 -1
- package/node_modules/@line/bot-sdk/lib/webhook/.openapi-generator/FILES +0 -1
- package/node_modules/@line/bot-sdk/lib/webhook/model/event.ts +0 -2
- package/node_modules/@line/bot-sdk/lib/webhook/model/models.ts +0 -1
- package/node_modules/@line/bot-sdk/lib/webhook/model/stickerMessageContent.ts +1 -1
- package/node_modules/@line/bot-sdk/node_modules/@types/node/README.md +1 -1
- package/node_modules/@line/bot-sdk/node_modules/@types/node/fs/promises.d.ts +5 -16
- package/node_modules/@line/bot-sdk/node_modules/@types/node/package.json +3 -3
- package/node_modules/@line/bot-sdk/package.json +3 -3
- package/openclaw.plugin.json +75 -57
- package/package.json +6 -71
- package/dist/accounts-BqEVsDoB.js +0 -103
- package/dist/channel.runtime-BdhK8Xw7.js +0 -4
- package/dist/flex-templates-iKJsyCq-.js +0 -1339
- package/dist/monitor.runtime-CZquR7jI.js +0 -2
- package/dist/outbound.runtime-BS0IhU_M.js +0 -2
- package/dist/probe.runtime-D13ZtXsd.js +0 -2
- package/dist/quick-reply-fallback-D86FwAfr.js +0 -56
- package/dist/send-receipt-CY2ey8XH.js +0 -107
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.d.ts +0 -24
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.d.ts.map +0 -1
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.js +0 -14
- package/node_modules/@line/bot-sdk/dist/cjs/webhook/model/messageEditedEvent.js.map +0 -1
- package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.d.ts +0 -24
- package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.d.ts.map +0 -1
- package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.js +0 -13
- package/node_modules/@line/bot-sdk/dist/webhook/model/messageEditedEvent.js.map +0 -1
- package/node_modules/@line/bot-sdk/lib/webhook/model/messageEditedEvent.ts +0 -32
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { i as resolveLineAccount } from "./accounts-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { markdownToIRWithMeta, stripMarkdown, stripMarkdown as stripMarkdown$1 } from "openclaw/plugin-sdk/text-chunking";
|
|
1
|
+
import { i as resolveLineAccount } from "./accounts-DJVOv1JI.mjs";
|
|
2
|
+
import { o as validateLineMediaUrl, r as createLineSendReceipt } from "./reply-payload-transform-CYQIy_x8.mjs";
|
|
3
|
+
import { a as messageAction, o as postbackAction, s as uriAction, u as createReceiptCard } from "./flex-templates-BP6VHjzK.mjs";
|
|
5
4
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
6
|
-
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
7
5
|
import { messagingApi } from "@line/bot-sdk";
|
|
6
|
+
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
8
7
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
9
|
-
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
10
8
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
9
|
+
import { stripMarkdown, stripMarkdown as stripMarkdown$1 } from "openclaw/plugin-sdk/text-chunking";
|
|
11
10
|
//#region extensions/line/src/flex-templates/message.ts
|
|
12
11
|
/**
|
|
13
12
|
* Wrap a FlexContainer in a FlexMessage
|
|
@@ -54,19 +53,6 @@ function formatProductCarouselText(description, price) {
|
|
|
54
53
|
const descriptionText = truncateTemplateText(description, Math.max(0, COMPACT_TEMPLATE_TEXT_LIMIT - priceText.length - 1));
|
|
55
54
|
return descriptionText ? `${descriptionText}\n${priceText}` : priceText;
|
|
56
55
|
}
|
|
57
|
-
function normalizeCarouselColumnActions(column) {
|
|
58
|
-
return {
|
|
59
|
-
...column,
|
|
60
|
-
actions: column.actions.map((action) => normalizeLineAction(action)),
|
|
61
|
-
defaultAction: column.defaultAction === void 0 ? void 0 : normalizeLineAction(column.defaultAction)
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
function normalizeImageCarouselColumnAction(column) {
|
|
65
|
-
return {
|
|
66
|
-
...column,
|
|
67
|
-
action: normalizeLineAction(column.action, 12)
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
56
|
/**
|
|
71
57
|
* Create a confirm template (yes/no style dialog)
|
|
72
58
|
*/
|
|
@@ -74,7 +60,7 @@ function createConfirmTemplate(text, confirmAction, cancelAction, altText) {
|
|
|
74
60
|
const template = {
|
|
75
61
|
type: "confirm",
|
|
76
62
|
text: truncateTemplateText(text, 240),
|
|
77
|
-
actions: [
|
|
63
|
+
actions: [confirmAction, cancelAction]
|
|
78
64
|
};
|
|
79
65
|
return {
|
|
80
66
|
type: "template",
|
|
@@ -86,26 +72,25 @@ function createConfirmTemplate(text, confirmAction, cancelAction, altText) {
|
|
|
86
72
|
* Create a button template with title, text, and action buttons
|
|
87
73
|
*/
|
|
88
74
|
function createButtonTemplate(title, text, actions, options) {
|
|
89
|
-
const normalizedTitle = title || void 0;
|
|
90
75
|
const textLimit = resolveTemplateTextLimit({
|
|
91
|
-
title
|
|
76
|
+
title,
|
|
92
77
|
thumbnailImageUrl: options?.thumbnailImageUrl,
|
|
93
78
|
textOnlyLimit: 160
|
|
94
79
|
});
|
|
95
80
|
const template = {
|
|
96
81
|
type: "buttons",
|
|
97
|
-
|
|
82
|
+
title: truncateTemplateText(title, 40),
|
|
98
83
|
text: truncateTemplateText(text, textLimit),
|
|
99
|
-
actions: actions.slice(0, 4)
|
|
84
|
+
actions: actions.slice(0, 4),
|
|
100
85
|
thumbnailImageUrl: options?.thumbnailImageUrl,
|
|
101
86
|
imageAspectRatio: options?.imageAspectRatio ?? "rectangle",
|
|
102
87
|
imageSize: options?.imageSize ?? "cover",
|
|
103
88
|
imageBackgroundColor: options?.imageBackgroundColor,
|
|
104
|
-
defaultAction: options?.defaultAction
|
|
89
|
+
defaultAction: options?.defaultAction
|
|
105
90
|
};
|
|
106
91
|
return {
|
|
107
92
|
type: "template",
|
|
108
|
-
altText: truncateOptionalTemplateText(options?.altText, 400) ?? truncateTemplateText(
|
|
93
|
+
altText: truncateOptionalTemplateText(options?.altText, 400) ?? truncateTemplateText(`${title}: ${text}`, 400),
|
|
109
94
|
template
|
|
110
95
|
};
|
|
111
96
|
}
|
|
@@ -115,7 +100,7 @@ function createButtonTemplate(title, text, actions, options) {
|
|
|
115
100
|
function createTemplateCarousel(columns, options) {
|
|
116
101
|
const template = {
|
|
117
102
|
type: "carousel",
|
|
118
|
-
columns: columns.slice(0, 10)
|
|
103
|
+
columns: columns.slice(0, 10),
|
|
119
104
|
imageAspectRatio: options?.imageAspectRatio ?? "rectangle",
|
|
120
105
|
imageSize: options?.imageSize ?? "cover"
|
|
121
106
|
};
|
|
@@ -136,10 +121,10 @@ function createCarouselColumn(params) {
|
|
|
136
121
|
return {
|
|
137
122
|
title: truncateOptionalTemplateText(params.title, 40),
|
|
138
123
|
text: truncateTemplateText(params.text, textLimit),
|
|
139
|
-
actions: params.actions.slice(0, 3)
|
|
124
|
+
actions: params.actions.slice(0, 3),
|
|
140
125
|
thumbnailImageUrl: params.thumbnailImageUrl,
|
|
141
126
|
imageBackgroundColor: params.imageBackgroundColor,
|
|
142
|
-
defaultAction: params.defaultAction
|
|
127
|
+
defaultAction: params.defaultAction
|
|
143
128
|
};
|
|
144
129
|
}
|
|
145
130
|
/**
|
|
@@ -148,7 +133,7 @@ function createCarouselColumn(params) {
|
|
|
148
133
|
function createImageCarousel(columns, altText) {
|
|
149
134
|
const template = {
|
|
150
135
|
type: "image_carousel",
|
|
151
|
-
columns: columns.slice(0, 10)
|
|
136
|
+
columns: columns.slice(0, 10)
|
|
152
137
|
};
|
|
153
138
|
return {
|
|
154
139
|
type: "template",
|
|
@@ -162,7 +147,7 @@ function createImageCarousel(columns, altText) {
|
|
|
162
147
|
function createImageCarouselColumn(imageUrl, action) {
|
|
163
148
|
return {
|
|
164
149
|
imageUrl,
|
|
165
|
-
action
|
|
150
|
+
action
|
|
166
151
|
};
|
|
167
152
|
}
|
|
168
153
|
/**
|
|
@@ -245,29 +230,22 @@ function resolveLineChannelAccessToken(explicit, params) {
|
|
|
245
230
|
//#endregion
|
|
246
231
|
//#region extensions/line/src/send.ts
|
|
247
232
|
const userProfileCache = /* @__PURE__ */ new Map();
|
|
248
|
-
const PROFILE_CACHE_TTL_MS =
|
|
249
|
-
const PROFILE_CACHE_MAX_ENTRIES = 1e3;
|
|
250
|
-
function cacheUserProfile(userId, profile) {
|
|
251
|
-
userProfileCache.delete(userId);
|
|
252
|
-
userProfileCache.set(userId, profile);
|
|
253
|
-
if (userProfileCache.size <= PROFILE_CACHE_MAX_ENTRIES) return;
|
|
254
|
-
for (const [key, cached] of userProfileCache) if (profile.fetchedAt - cached.fetchedAt >= PROFILE_CACHE_TTL_MS) userProfileCache.delete(key);
|
|
255
|
-
pruneMapToMaxSize(userProfileCache, PROFILE_CACHE_MAX_ENTRIES);
|
|
256
|
-
}
|
|
233
|
+
const PROFILE_CACHE_TTL_MS = 3e5;
|
|
257
234
|
function normalizeTarget(to) {
|
|
258
235
|
const trimmed = to.trim();
|
|
259
236
|
if (!trimmed) throw new Error("Recipient is required for LINE sends");
|
|
260
237
|
const normalized = trimmed.replace(/^line:group:/i, "").replace(/^line:room:/i, "").replace(/^line:user:/i, "").replace(/^line:/i, "");
|
|
261
238
|
if (!normalized) throw new Error("Recipient is required for LINE sends");
|
|
262
|
-
if (normalized.length >= 33 && !/^[CUR]/.test(normalized)) throw new Error(`Recipient is not a valid LINE id (case-sensitive; expected leading capital C/U/R): ${
|
|
239
|
+
if (normalized.length >= 33 && !/^[CUR]/.test(normalized)) throw new Error(`Recipient is not a valid LINE id (case-sensitive; expected leading capital C/U/R): ${normalized.slice(0, 4)}…`);
|
|
263
240
|
return normalized;
|
|
264
241
|
}
|
|
265
242
|
function isLineUserChatId(chatId) {
|
|
266
243
|
return /^U/i.test(chatId);
|
|
267
244
|
}
|
|
268
245
|
function createLineMessagingClient(opts) {
|
|
246
|
+
const cfg = requireRuntimeConfig(opts.cfg, "LINE send");
|
|
269
247
|
const account = resolveLineAccount({
|
|
270
|
-
cfg
|
|
248
|
+
cfg,
|
|
271
249
|
accountId: opts.accountId
|
|
272
250
|
});
|
|
273
251
|
const token = resolveLineChannelAccessToken(opts.channelAccessToken, account);
|
|
@@ -324,7 +302,10 @@ function createLocationMessage(location) {
|
|
|
324
302
|
function logLineHttpError(err, context) {
|
|
325
303
|
if (!err || typeof err !== "object") return;
|
|
326
304
|
const { status, statusText, body } = err;
|
|
327
|
-
if (typeof body === "string")
|
|
305
|
+
if (typeof body === "string") {
|
|
306
|
+
const summary = status ? `${status} ${statusText ?? ""}`.trim() : "unknown status";
|
|
307
|
+
logVerbose(`line: ${context} failed (${summary}): ${body}`);
|
|
308
|
+
}
|
|
328
309
|
}
|
|
329
310
|
function recordLineOutboundActivity(accountId) {
|
|
330
311
|
recordChannelActivity({
|
|
@@ -344,10 +325,9 @@ function resolveLineReceiptKind(messages) {
|
|
|
344
325
|
async function pushLineMessages(to, messages, opts, behavior = {}) {
|
|
345
326
|
if (messages.length === 0) throw new Error("Message must be non-empty for LINE sends");
|
|
346
327
|
const { account, client, chatId } = createLinePushContext(to, opts);
|
|
347
|
-
const normalizedMessages = messages.map(normalizeLineMessageActions);
|
|
348
328
|
const pushRequest = client.pushMessage({
|
|
349
329
|
to: chatId,
|
|
350
|
-
messages
|
|
330
|
+
messages
|
|
351
331
|
});
|
|
352
332
|
if (behavior.errorContext) await pushRequest.catch((err) => {
|
|
353
333
|
logLineHttpError(err, behavior.errorContext);
|
|
@@ -355,7 +335,10 @@ async function pushLineMessages(to, messages, opts, behavior = {}) {
|
|
|
355
335
|
});
|
|
356
336
|
else await pushRequest;
|
|
357
337
|
recordLineOutboundActivity(account.accountId);
|
|
358
|
-
if (opts.verbose)
|
|
338
|
+
if (opts.verbose) {
|
|
339
|
+
const logMessage = behavior.verboseMessage?.(chatId, messages.length) ?? `line: pushed ${messages.length} messages to ${chatId}`;
|
|
340
|
+
logVerbose(logMessage);
|
|
341
|
+
}
|
|
359
342
|
return {
|
|
360
343
|
messageId: "push",
|
|
361
344
|
chatId,
|
|
@@ -369,10 +352,9 @@ async function pushLineMessages(to, messages, opts, behavior = {}) {
|
|
|
369
352
|
}
|
|
370
353
|
async function replyLineMessages(replyToken, messages, opts, behavior = {}) {
|
|
371
354
|
const { account, client } = createLineMessagingClient(opts);
|
|
372
|
-
const normalizedMessages = messages.map(normalizeLineMessageActions);
|
|
373
355
|
await client.replyMessage({
|
|
374
356
|
replyToken,
|
|
375
|
-
messages
|
|
357
|
+
messages
|
|
376
358
|
});
|
|
377
359
|
recordLineOutboundActivity(account.accountId);
|
|
378
360
|
if (opts.verbose) logVerbose(behavior.verboseMessage?.(messages.length) ?? `line: replied with ${messages.length} messages`);
|
|
@@ -395,13 +377,11 @@ async function sendMessageLine(to, text, opts) {
|
|
|
395
377
|
case "audio":
|
|
396
378
|
messages.push(createAudioMessage(mediaUrl, opts.durationMs ?? 6e4));
|
|
397
379
|
break;
|
|
398
|
-
default:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
break;
|
|
380
|
+
default: {
|
|
381
|
+
const previewImageUrl = opts.previewImageUrl?.trim() || mediaUrl;
|
|
382
|
+
await validateLineMediaUrl(previewImageUrl);
|
|
383
|
+
messages.push(createImageMessage(mediaUrl, previewImageUrl));
|
|
384
|
+
}
|
|
405
385
|
}
|
|
406
386
|
}
|
|
407
387
|
if (text?.trim()) messages.push(createTextMessage(text.trim()));
|
|
@@ -504,7 +484,7 @@ async function getUserProfile(userId, opts) {
|
|
|
504
484
|
displayName: profile.displayName,
|
|
505
485
|
pictureUrl: profile.pictureUrl
|
|
506
486
|
};
|
|
507
|
-
|
|
487
|
+
userProfileCache.set(userId, {
|
|
508
488
|
...result,
|
|
509
489
|
fetchedAt: Date.now()
|
|
510
490
|
});
|
|
@@ -519,184 +499,89 @@ async function getUserDisplayName(userId, opts) {
|
|
|
519
499
|
}
|
|
520
500
|
//#endregion
|
|
521
501
|
//#region extensions/line/src/markdown-to-line.ts
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
function toCodeBlock(ir, span) {
|
|
550
|
-
return {
|
|
551
|
-
...span.language ? { language: span.language } : {},
|
|
552
|
-
code: ir.text.slice(span.start, span.end).trim()
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
function rangesOverlap(left, right) {
|
|
556
|
-
return left.start < right.end && right.start < left.end;
|
|
557
|
-
}
|
|
558
|
-
function projectPlainText(ir, omitted = []) {
|
|
559
|
-
const insertions = [];
|
|
560
|
-
for (const link of ir.links) {
|
|
561
|
-
if (omitted.some((range) => rangesOverlap(range, link))) continue;
|
|
562
|
-
const href = link.href.trim();
|
|
563
|
-
const label = ir.text.slice(link.start, link.end).trim();
|
|
564
|
-
const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
|
|
565
|
-
if (href && label && label !== href && label !== comparableHref) insertions.push({
|
|
566
|
-
position: link.end,
|
|
567
|
-
text: ` (${href})`
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
for (const annotation of ir.annotations ?? []) if (annotation.type === "assistant_transcript_role" && !omitted.some((range) => rangesOverlap(range, annotation))) insertions.push({
|
|
571
|
-
position: annotation.start,
|
|
572
|
-
text: TRANSCRIPT_ROLE_PREFIX
|
|
573
|
-
});
|
|
574
|
-
const inlineCodeSpans = ir.styles.filter((span) => span.style === "code" && !omitted.some((range) => rangesOverlap(range, span)));
|
|
575
|
-
for (const span of inlineCodeSpans) if (stripMarkdown(ir.text.slice(span.start, span.end), { assistantTranscriptRoleHeaders: true }).startsWith(TRANSCRIPT_ROLE_PREFIX)) insertions.push({
|
|
576
|
-
position: span.start,
|
|
577
|
-
text: TRANSCRIPT_ROLE_PREFIX
|
|
578
|
-
});
|
|
579
|
-
insertions.sort((left, right) => left.position - right.position);
|
|
580
|
-
const underlineTags = [...ir.text.matchAll(/<\/?u>/gi)].map((match) => ({
|
|
581
|
-
start: match.index,
|
|
582
|
-
end: match.index + match[0].length
|
|
583
|
-
})).filter((tag) => !inlineCodeSpans.some((span) => rangesOverlap(tag, span)) && !omitted.some((span) => rangesOverlap(tag, span)));
|
|
584
|
-
const removed = [...omitted, ...underlineTags].toSorted((left, right) => left.start - right.start);
|
|
585
|
-
let output = "";
|
|
586
|
-
let cursor = 0;
|
|
587
|
-
let insertionIndex = 0;
|
|
588
|
-
const appendRange = (end) => {
|
|
589
|
-
while (insertionIndex < insertions.length) {
|
|
590
|
-
const insertion = insertions[insertionIndex];
|
|
591
|
-
if (!insertion || insertion.position > end) break;
|
|
592
|
-
if (insertion.position >= cursor) {
|
|
593
|
-
output += ir.text.slice(cursor, insertion.position) + insertion.text;
|
|
594
|
-
cursor = insertion.position;
|
|
502
|
+
/**
|
|
503
|
+
* Regex patterns for markdown detection
|
|
504
|
+
*/
|
|
505
|
+
const MARKDOWN_TABLE_REGEX = /^\|(.+)\|[\r\n]+\|[-:\s|]+\|[\r\n]+((?:\|.+\|[\r\n]*)+)/gm;
|
|
506
|
+
const MARKDOWN_CODE_BLOCK_REGEX = /```(\w*)\n([\s\S]*?)```/g;
|
|
507
|
+
const MARKDOWN_LINK_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
508
|
+
/**
|
|
509
|
+
* Detect and extract markdown tables from text
|
|
510
|
+
*/
|
|
511
|
+
function extractMarkdownTables(text) {
|
|
512
|
+
const tables = [];
|
|
513
|
+
let textWithoutTables = text;
|
|
514
|
+
MARKDOWN_TABLE_REGEX.lastIndex = 0;
|
|
515
|
+
let match;
|
|
516
|
+
const matches = [];
|
|
517
|
+
while ((match = MARKDOWN_TABLE_REGEX.exec(text)) !== null) {
|
|
518
|
+
const fullMatch = match[0];
|
|
519
|
+
const headerLine = match[1];
|
|
520
|
+
const bodyLines = match[2];
|
|
521
|
+
const headers = parseTableRow(headerLine);
|
|
522
|
+
const rows = bodyLines.trim().split(/[\r\n]+/).filter((line) => line.trim()).map(parseTableRow);
|
|
523
|
+
if (headers.length > 0 && rows.length > 0) matches.push({
|
|
524
|
+
fullMatch,
|
|
525
|
+
table: {
|
|
526
|
+
headers,
|
|
527
|
+
rows
|
|
595
528
|
}
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
output += ir.text.slice(cursor, end);
|
|
599
|
-
cursor = end;
|
|
600
|
-
};
|
|
601
|
-
for (const range of removed) {
|
|
602
|
-
appendRange(range.start);
|
|
603
|
-
cursor = Math.max(cursor, range.end);
|
|
604
|
-
while (insertionIndex < insertions.length && (insertions[insertionIndex]?.position ?? cursor) < cursor) insertionIndex += 1;
|
|
605
|
-
}
|
|
606
|
-
appendRange(ir.text.length);
|
|
607
|
-
return output.trim();
|
|
608
|
-
}
|
|
609
|
-
function sameSpanStyle(left, right) {
|
|
610
|
-
return left.weight === right.weight && left.style === right.style && left.decoration === right.decoration;
|
|
611
|
-
}
|
|
612
|
-
function renderTableCell(cell, fallback) {
|
|
613
|
-
if (!cell?.text.trim()) return {
|
|
614
|
-
text: fallback,
|
|
615
|
-
hasMarkup: false
|
|
616
|
-
};
|
|
617
|
-
const codeSpans = cell.styles.filter((span) => span.style === "code");
|
|
618
|
-
const tags = [...cell.text.matchAll(/<\/?u>/gi)].map((match) => ({
|
|
619
|
-
start: match.index,
|
|
620
|
-
end: match.index + match[0].length,
|
|
621
|
-
closing: match[0][1] === "/"
|
|
622
|
-
})).filter((tag) => !codeSpans.some((span) => rangesOverlap(tag, span)));
|
|
623
|
-
const boundaries = /* @__PURE__ */ new Set([0, cell.text.length]);
|
|
624
|
-
for (const style of cell.styles) {
|
|
625
|
-
boundaries.add(style.start);
|
|
626
|
-
boundaries.add(style.end);
|
|
627
|
-
}
|
|
628
|
-
for (const link of cell.links) boundaries.add(link.end);
|
|
629
|
-
for (const tag of tags) {
|
|
630
|
-
boundaries.add(tag.start);
|
|
631
|
-
boundaries.add(tag.end);
|
|
529
|
+
});
|
|
632
530
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const appendSpan = (span) => {
|
|
638
|
-
const previous = spans.at(-1);
|
|
639
|
-
if (previous && sameSpanStyle(previous, span)) previous.text = `${previous.text ?? ""}${span.text ?? ""}`;
|
|
640
|
-
else spans.push(span);
|
|
641
|
-
};
|
|
642
|
-
for (let index = 0; index < sortedBoundaries.length - 1; index += 1) {
|
|
643
|
-
const start = sortedBoundaries[index];
|
|
644
|
-
const end = sortedBoundaries[index + 1];
|
|
645
|
-
if (start === void 0 || end === void 0) continue;
|
|
646
|
-
const tag = tags.find((candidate) => candidate.start === start);
|
|
647
|
-
if (tag) {
|
|
648
|
-
underlineDepth += tag.closing ? -1 : 1;
|
|
649
|
-
hasMarkup = true;
|
|
650
|
-
continue;
|
|
651
|
-
}
|
|
652
|
-
const text = cell.text.slice(start, end);
|
|
653
|
-
if (text) {
|
|
654
|
-
const active = new Set(cell.styles.filter((style) => style.start <= start && style.end >= end).map((style) => style.style));
|
|
655
|
-
const weight = active.has("bold") ? "bold" : void 0;
|
|
656
|
-
const style = active.has("italic") ? "italic" : void 0;
|
|
657
|
-
const decoration = active.has("strikethrough") ? "line-through" : underlineDepth > 0 ? "underline" : void 0;
|
|
658
|
-
hasMarkup ||= weight !== void 0 || style !== void 0 || decoration !== void 0;
|
|
659
|
-
appendSpan({
|
|
660
|
-
type: "span",
|
|
661
|
-
text,
|
|
662
|
-
weight,
|
|
663
|
-
style,
|
|
664
|
-
decoration
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
for (const link of cell.links.filter((candidate) => candidate.end === end)) {
|
|
668
|
-
const href = link.href.trim();
|
|
669
|
-
const label = cell.text.slice(link.start, link.end).trim();
|
|
670
|
-
if (href && label && label !== href) {
|
|
671
|
-
appendSpan({
|
|
672
|
-
type: "span",
|
|
673
|
-
text: ` (${href})`
|
|
674
|
-
});
|
|
675
|
-
hasMarkup = true;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
531
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
532
|
+
const { fullMatch, table } = matches[i];
|
|
533
|
+
tables.unshift(table);
|
|
534
|
+
textWithoutTables = textWithoutTables.replace(fullMatch, "");
|
|
678
535
|
}
|
|
679
536
|
return {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
hasMarkup
|
|
537
|
+
tables,
|
|
538
|
+
textWithoutTables
|
|
683
539
|
};
|
|
684
540
|
}
|
|
685
|
-
|
|
686
|
-
|
|
541
|
+
/**
|
|
542
|
+
* Parse a single table row (pipe-separated values)
|
|
543
|
+
*/
|
|
544
|
+
function parseTableRow(row) {
|
|
545
|
+
return row.split("|").map((cell) => cell.trim()).filter((cell, index, arr) => {
|
|
546
|
+
if (index === 0 && cell === "") return false;
|
|
547
|
+
if (index === arr.length - 1 && cell === "") return false;
|
|
548
|
+
return true;
|
|
549
|
+
});
|
|
687
550
|
}
|
|
688
|
-
/**
|
|
551
|
+
/**
|
|
552
|
+
* Convert a markdown table to a LINE Flex Message bubble
|
|
553
|
+
*/
|
|
689
554
|
function convertTableToFlexBubble(table) {
|
|
690
|
-
const
|
|
691
|
-
|
|
555
|
+
const parseCell = (value) => {
|
|
556
|
+
const raw = value?.trim() ?? "";
|
|
557
|
+
if (!raw) return {
|
|
558
|
+
text: "-",
|
|
559
|
+
bold: false,
|
|
560
|
+
hasMarkup: false
|
|
561
|
+
};
|
|
562
|
+
let hasMarkup = false;
|
|
563
|
+
return {
|
|
564
|
+
text: raw.replace(/\*\*(.+?)\*\*/g, (_, inner) => {
|
|
565
|
+
hasMarkup = true;
|
|
566
|
+
return String(inner);
|
|
567
|
+
}).trim() || "-",
|
|
568
|
+
bold: /^\*\*.+\*\*$/.test(raw),
|
|
569
|
+
hasMarkup
|
|
570
|
+
};
|
|
571
|
+
};
|
|
572
|
+
const headerCells = table.headers.map((header) => parseCell(header));
|
|
573
|
+
const rowCells = table.rows.map((row) => row.map((cell) => parseCell(cell)));
|
|
692
574
|
const hasInlineMarkup = headerCells.some((cell) => cell.hasMarkup) || rowCells.some((row) => row.some((cell) => cell.hasMarkup));
|
|
693
|
-
if (table.headers.length === 2 && !hasInlineMarkup)
|
|
694
|
-
|
|
695
|
-
items: rowCells.map((row) => ({
|
|
575
|
+
if (table.headers.length === 2 && !hasInlineMarkup) {
|
|
576
|
+
const items = rowCells.map((row) => ({
|
|
696
577
|
name: row[0]?.text ?? "-",
|
|
697
578
|
value: row[1]?.text ?? "-"
|
|
698
|
-
}))
|
|
699
|
-
|
|
579
|
+
}));
|
|
580
|
+
return createReceiptCard({
|
|
581
|
+
title: headerCells.map((cell) => cell.text).join(" / "),
|
|
582
|
+
items
|
|
583
|
+
});
|
|
584
|
+
}
|
|
700
585
|
return {
|
|
701
586
|
type: "bubble",
|
|
702
587
|
body: {
|
|
@@ -709,7 +594,6 @@ function convertTableToFlexBubble(table) {
|
|
|
709
594
|
contents: headerCells.map((cell) => ({
|
|
710
595
|
type: "text",
|
|
711
596
|
text: cell.text,
|
|
712
|
-
contents: cell.contents,
|
|
713
597
|
weight: "bold",
|
|
714
598
|
size: "sm",
|
|
715
599
|
color: "#333333",
|
|
@@ -722,32 +606,68 @@ function convertTableToFlexBubble(table) {
|
|
|
722
606
|
type: "separator",
|
|
723
607
|
margin: "sm"
|
|
724
608
|
},
|
|
725
|
-
...rowCells.slice(0, 10).map((row, rowIndex) =>
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
609
|
+
...rowCells.slice(0, 10).map((row, rowIndex) => {
|
|
610
|
+
return {
|
|
611
|
+
type: "box",
|
|
612
|
+
layout: "horizontal",
|
|
613
|
+
contents: table.headers.map((_, colIndex) => {
|
|
614
|
+
const cell = row[colIndex] ?? {
|
|
615
|
+
text: "-",
|
|
616
|
+
bold: false,
|
|
617
|
+
hasMarkup: false
|
|
618
|
+
};
|
|
619
|
+
return {
|
|
620
|
+
type: "text",
|
|
621
|
+
text: cell.text,
|
|
622
|
+
size: "sm",
|
|
623
|
+
color: "#666666",
|
|
624
|
+
flex: 1,
|
|
625
|
+
wrap: true,
|
|
626
|
+
weight: cell.bold ? "bold" : void 0
|
|
627
|
+
};
|
|
628
|
+
}),
|
|
629
|
+
margin: rowIndex === 0 ? "md" : "sm"
|
|
630
|
+
};
|
|
631
|
+
})
|
|
745
632
|
],
|
|
746
633
|
paddingAll: "lg"
|
|
747
634
|
}
|
|
748
635
|
};
|
|
749
636
|
}
|
|
750
|
-
/**
|
|
637
|
+
/**
|
|
638
|
+
* Detect and extract code blocks from text
|
|
639
|
+
*/
|
|
640
|
+
function extractCodeBlocks(text) {
|
|
641
|
+
const codeBlocks = [];
|
|
642
|
+
let textWithoutCode = text;
|
|
643
|
+
MARKDOWN_CODE_BLOCK_REGEX.lastIndex = 0;
|
|
644
|
+
let match;
|
|
645
|
+
const matches = [];
|
|
646
|
+
while ((match = MARKDOWN_CODE_BLOCK_REGEX.exec(text)) !== null) {
|
|
647
|
+
const fullMatch = match[0];
|
|
648
|
+
const language = match[1] || void 0;
|
|
649
|
+
const code = match[2];
|
|
650
|
+
matches.push({
|
|
651
|
+
fullMatch,
|
|
652
|
+
block: {
|
|
653
|
+
language,
|
|
654
|
+
code: code.trim()
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
659
|
+
const { fullMatch, block } = matches[i];
|
|
660
|
+
codeBlocks.unshift(block);
|
|
661
|
+
textWithoutCode = textWithoutCode.replace(fullMatch, "");
|
|
662
|
+
}
|
|
663
|
+
return {
|
|
664
|
+
codeBlocks,
|
|
665
|
+
textWithoutCode
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Convert a code block to a LINE Flex Message bubble
|
|
670
|
+
*/
|
|
751
671
|
function convertCodeBlockToFlexBubble(block) {
|
|
752
672
|
const titleText = block.language ? `Code (${block.language})` : "Code";
|
|
753
673
|
const displayCode = block.code.length > 2e3 ? truncateUtf16Safe(block.code, 2e3) + "\n..." : block.code;
|
|
@@ -781,19 +701,97 @@ function convertCodeBlockToFlexBubble(block) {
|
|
|
781
701
|
}
|
|
782
702
|
};
|
|
783
703
|
}
|
|
784
|
-
/**
|
|
704
|
+
/**
|
|
705
|
+
* Extract markdown links from text
|
|
706
|
+
*/
|
|
707
|
+
function extractLinks(text) {
|
|
708
|
+
const links = [];
|
|
709
|
+
MARKDOWN_LINK_REGEX.lastIndex = 0;
|
|
710
|
+
let match;
|
|
711
|
+
while ((match = MARKDOWN_LINK_REGEX.exec(text)) !== null) links.push({
|
|
712
|
+
text: match[1],
|
|
713
|
+
url: match[2]
|
|
714
|
+
});
|
|
715
|
+
return {
|
|
716
|
+
links,
|
|
717
|
+
textWithLinks: text.replace(MARKDOWN_LINK_REGEX, "$1")
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Create a Flex Message with tappable link buttons
|
|
722
|
+
*/
|
|
723
|
+
function convertLinksToFlexBubble(links) {
|
|
724
|
+
return {
|
|
725
|
+
type: "bubble",
|
|
726
|
+
body: {
|
|
727
|
+
type: "box",
|
|
728
|
+
layout: "vertical",
|
|
729
|
+
contents: [{
|
|
730
|
+
type: "text",
|
|
731
|
+
text: "Links",
|
|
732
|
+
weight: "bold",
|
|
733
|
+
size: "md",
|
|
734
|
+
color: "#333333"
|
|
735
|
+
}],
|
|
736
|
+
paddingAll: "lg",
|
|
737
|
+
paddingBottom: "sm"
|
|
738
|
+
},
|
|
739
|
+
footer: {
|
|
740
|
+
type: "box",
|
|
741
|
+
layout: "vertical",
|
|
742
|
+
contents: links.slice(0, 4).map((link, index) => ({
|
|
743
|
+
type: "button",
|
|
744
|
+
action: uriAction(link.text, link.url),
|
|
745
|
+
style: index === 0 ? "primary" : "secondary",
|
|
746
|
+
margin: index > 0 ? "sm" : void 0
|
|
747
|
+
})),
|
|
748
|
+
paddingAll: "md"
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Main function: Process text for LINE output
|
|
754
|
+
* - Extracts tables → Flex Messages
|
|
755
|
+
* - Extracts code blocks → Flex Messages
|
|
756
|
+
* - Strips remaining markdown
|
|
757
|
+
* - Returns processed text + Flex Messages
|
|
758
|
+
*/
|
|
785
759
|
function processLineMessage(text) {
|
|
786
|
-
const
|
|
787
|
-
|
|
760
|
+
const flexMessages = [];
|
|
761
|
+
let processedText = text;
|
|
762
|
+
const { tables, textWithoutTables } = extractMarkdownTables(processedText);
|
|
763
|
+
processedText = textWithoutTables;
|
|
764
|
+
for (const table of tables) {
|
|
765
|
+
const bubble = convertTableToFlexBubble(table);
|
|
766
|
+
flexMessages.push(toFlexMessage("Table", bubble));
|
|
767
|
+
}
|
|
768
|
+
const { codeBlocks, textWithoutCode } = extractCodeBlocks(processedText);
|
|
769
|
+
processedText = textWithoutCode;
|
|
770
|
+
for (const block of codeBlocks) {
|
|
771
|
+
const bubble = convertCodeBlockToFlexBubble(block);
|
|
772
|
+
flexMessages.push(toFlexMessage("Code", bubble));
|
|
773
|
+
}
|
|
774
|
+
const { textWithLinks } = extractLinks(processedText);
|
|
775
|
+
processedText = textWithLinks;
|
|
776
|
+
processedText = stripMarkdown(processedText);
|
|
788
777
|
return {
|
|
789
|
-
text:
|
|
790
|
-
flexMessages
|
|
778
|
+
text: processedText,
|
|
779
|
+
flexMessages
|
|
791
780
|
};
|
|
792
781
|
}
|
|
793
|
-
/**
|
|
782
|
+
/**
|
|
783
|
+
* Check if text contains markdown that needs conversion
|
|
784
|
+
*/
|
|
794
785
|
function hasMarkdownToConvert(text) {
|
|
795
|
-
|
|
796
|
-
|
|
786
|
+
MARKDOWN_TABLE_REGEX.lastIndex = 0;
|
|
787
|
+
if (MARKDOWN_TABLE_REGEX.test(text)) return true;
|
|
788
|
+
MARKDOWN_CODE_BLOCK_REGEX.lastIndex = 0;
|
|
789
|
+
if (MARKDOWN_CODE_BLOCK_REGEX.test(text)) return true;
|
|
790
|
+
if (/\*\*[^*]+\*\*/.test(text)) return true;
|
|
791
|
+
if (/~~[^~]+~~/.test(text)) return true;
|
|
792
|
+
if (/^#{1,6}\s+/m.test(text)) return true;
|
|
793
|
+
if (/^>\s+/m.test(text)) return true;
|
|
794
|
+
return false;
|
|
797
795
|
}
|
|
798
796
|
//#endregion
|
|
799
|
-
export {
|
|
797
|
+
export { buildTemplateMessageFromPayload as A, createYesNoConfirm as B, pushMessagesLine as C, sendMessageLine as D, replyMessageLine as E, createImageCarousel as F, createImageCarouselColumn as I, createLinkMenu as L, createButtonTemplate as M, createCarouselColumn as N, showLoadingAnimation as O, createConfirmTemplate as P, createProductCarousel as R, pushMessageLine as S, pushTextMessageWithQuickReplies as T, toFlexMessage as V, getUserDisplayName as _, extractLinks as a, pushImageMessage as b, processLineMessage as c, createFlexMessage as d, createImageMessage as f, createVideoMessage as g, createTextMessageWithQuickReplies as h, extractCodeBlocks as i, createButtonMenu as j, resolveLineChannelAccessToken as k, stripMarkdown$1 as l, createQuickReplyItems as m, convertLinksToFlexBubble as n, extractMarkdownTables as o, createLocationMessage as p, convertTableToFlexBubble as r, hasMarkdownToConvert as s, convertCodeBlockToFlexBubble as t, createAudioMessage as u, getUserProfile as v, pushTemplateMessage as w, pushLocationMessage as x, pushFlexMessage as y, createTemplateCarousel as z };
|