@openclaw/line 2026.8.1-beta.3 → 2026.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-helpers-BSUyZwLm.js +12 -0
- package/dist/api.js +2 -2
- package/dist/{card-command-CyDSm-OU.js → card-command-BywtX77U.js} +66 -29
- package/dist/{channel-DmoKZXmG.js → channel-DpMgRaxl.js} +52 -349
- package/dist/channel-plugin-api.js +1 -1
- package/dist/channel.runtime-Bty5U_1N.js +4 -0
- package/dist/doctor-contract-api.js +141 -0
- package/dist/index.js +1 -1
- package/dist/{markdown-to-line-rEaras_0.js → markdown-to-line-CG9Jy22s.js} +29 -25
- package/dist/{monitor-BYXS_B6r.js → monitor-Ch6TIatG.js} +261 -166
- package/dist/monitor.runtime-Czc3NxNV.js +2 -0
- package/dist/outbound.runtime-CyleVzFR.js +3 -0
- package/dist/probe.runtime-DTxBWvKz.js +2 -0
- package/dist/rich-messages-t_zRL24p.js +760 -0
- package/dist/runtime-api.js +10 -11
- package/dist/{send-BJCeiiOB.js → send-B-K2B6au.js} +138 -104
- package/dist/{send-receipt-DKZzgHMO.js → send-retry-CUvrarfE.js} +137 -413
- package/dist/setup-api.js +1 -1
- package/dist/{setup-surface-W0Dbgu58.js → setup-surface-DSJ92oJ5.js} +24 -17
- package/dist/webhook-spool-contract-CNe2h1I2.js +58 -0
- package/node_modules/typebox/build/format/date.d.mts +1 -1
- package/node_modules/typebox/build/format/date.mjs +1 -1
- package/node_modules/typebox/build/format/date_time.d.mts +2 -2
- package/node_modules/typebox/build/format/date_time.mjs +3 -3
- package/node_modules/typebox/build/format/email.d.mts +1 -1
- package/node_modules/typebox/build/format/email.mjs +2 -2
- package/node_modules/typebox/build/format/hostname.mjs +2 -10
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_email.mjs +3 -3
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
- package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
- package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
- package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
- package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
- package/node_modules/typebox/build/format/idna/index.mjs +2 -0
- package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
- package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
- package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
- package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
- package/node_modules/typebox/build/format/ipv4.mjs +2 -32
- package/node_modules/typebox/build/format/ipv6.mjs +2 -61
- package/node_modules/typebox/build/format/iri.d.mts +2 -2
- package/node_modules/typebox/build/format/iri.mjs +26 -8
- package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
- package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
- package/node_modules/typebox/build/format/regex.d.mts +1 -2
- package/node_modules/typebox/build/format/regex.mjs +2 -6
- package/node_modules/typebox/build/format/time.d.mts +2 -2
- package/node_modules/typebox/build/format/time.mjs +19 -14
- package/node_modules/typebox/build/format/uri.d.mts +1 -1
- package/node_modules/typebox/build/format/uri.mjs +3 -130
- package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
- package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
- package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
- package/node_modules/typebox/build/format/uri_template.mjs +4 -5
- package/node_modules/typebox/build/format/url.d.mts +3 -3
- package/node_modules/typebox/build/format/url.mjs +4 -5
- package/node_modules/typebox/build/guard/emit.d.mts +3 -1
- package/node_modules/typebox/build/guard/emit.mjs +12 -5
- package/node_modules/typebox/build/guard/guard.d.mts +8 -2
- package/node_modules/typebox/build/guard/guard.mjs +25 -4
- package/node_modules/typebox/build/guard/string.d.mts +2 -2
- package/node_modules/typebox/build/guard/string.mjs +7 -7
- package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
- package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
- package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
- package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
- package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
- package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
- package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
- package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
- package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
- package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
- package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
- package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
- package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
- package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
- package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
- package/node_modules/typebox/build/schema/types/index.mjs +0 -2
- package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
- package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
- package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
- package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
- package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
- package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
- package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
- package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
- package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
- package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
- package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
- package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
- package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
- package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
- package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
- package/node_modules/typebox/build/type/script/parser.mjs +27 -23
- package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
- package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
- package/node_modules/typebox/package.json +27 -27
- package/node_modules/typebox/readme.md +79 -82
- package/openclaw.plugin.json +26 -2
- package/package.json +6 -6
- package/dist/channel.runtime-qrUV6wPE.js +0 -4
- package/dist/config-schema-Be3azjB_.js +0 -47
- package/dist/monitor.runtime-B2z_5ugU.js +0 -2
- package/dist/outbound.runtime-DDTeqaBW.js +0 -3
- package/dist/probe.runtime-D13ZtXsd.js +0 -2
- package/dist/quick-reply-fallback-D86FwAfr.js +0 -56
- package/node_modules/typebox/build/format/_idna.d.mts +0 -2
- package/node_modules/typebox/build/format/_idna.mjs +0 -246
- package/node_modules/typebox/build/format/_puny.d.mts +0 -1
- package/node_modules/typebox/build/format/_puny.mjs +0 -77
- package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
- package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
- package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
- package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
- package/dist/{probe-CM03wo6r.js → probe-4gc_YQ2L.js} +1 -1
package/dist/runtime-api.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { i as resolveLineAccount, n as normalizeAccountId, r as resolveDefaultLineAccountId, t as listLineAccountIds } from "./accounts-BqEVsDoB.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { a as
|
|
7
|
-
import { t as
|
|
8
|
-
import { _ as replyMessageLine, a as createQuickReplyItems, b as resolveLineChannelAccessToken, c as getUserDisplayName, d as pushImageMessage, f as pushLocationMessage, g as pushTextMessageWithQuickReplies, h as pushTemplateMessage, i as createLocationMessage, l as getUserProfile, m as pushMessagesLine, n as createFlexMessage, o as createTextMessageWithQuickReplies, p as pushMessageLine, r as createImageMessage, s as createVideoMessage, t as createAudioMessage, u as pushFlexMessage, v as sendMessageLine, y as showLoadingAnimation } from "./send-BJCeiiOB.js";
|
|
9
|
-
import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
|
|
2
|
+
import { _ as LineChannelConfigSchema, c as createDeviceControlCard, d as resolveExactLineGroupConfigKey, f as resolveLineGroupConfigEntry, g as setLineRuntime, l as createMediaPlayerCard, m as resolveLineGroupsConfig, p as resolveLineGroupLookupIds, s as createAppleTvRemoteCard, v as LineConfigSchema } from "./rich-messages-t_zRL24p.js";
|
|
3
|
+
import { S as createVideoMessage, a as createAgendaCard, b as createAudioMessage, c as createActionCard, d as createListCard, f as datetimePickerAction, g as postbackAction, l as createImageCard, o as createEventCard, p as messageAction, s as createReceiptCard, u as createInfoCard, v as uriAction, x as createImageMessage } from "./send-retry-CUvrarfE.js";
|
|
4
|
+
import { a as validateLineSignature, c as normalizeAllowFrom, i as parseLineWebhookBody, n as createLineNodeWebhookHandler, o as downloadLineMedia, r as readLineWebhookRequestBody, s as firstDefined, t as monitorLineProvider } from "./monitor-Ch6TIatG.js";
|
|
5
|
+
import { t as probeLineBot } from "./probe-4gc_YQ2L.js";
|
|
6
|
+
import { a as stripMarkdown, c as createButtonTemplate, d as createTemplateCarousel, i as processLineMessage, l as createCarouselColumn, n as convertTableToFlexBubble, o as toFlexMessage, r as hasMarkdownToConvert, s as buildTemplateMessageFromPayload, t as convertCodeBlockToFlexBubble, u as createConfirmTemplate } from "./markdown-to-line-CG9Jy22s.js";
|
|
7
|
+
import { _ as showLoadingAnimation, c as pushFlexMessage, d as pushMessageLine, f as pushMessagesLine, g as sendMessageLine, h as replyMessageLine, i as createTextMessageWithQuickReplies, l as pushImageMessage, m as pushTextMessageWithQuickReplies, n as createLocationMessage, o as getUserDisplayName, p as pushTemplateMessage, r as createQuickReplyItems, s as getUserProfile, t as createFlexMessage, u as pushLocationMessage, y as resolveLineChannelAccessToken } from "./send-B-K2B6au.js";
|
|
10
8
|
import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
9
|
+
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
10
|
+
import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
|
|
11
|
+
import { messagingApi } from "@line/bot-sdk";
|
|
11
12
|
import { DEFAULT_ACCOUNT_ID, formatDocsLink, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
12
13
|
import { buildComputedAccountStatusSnapshot, buildTokenChannelStatusSummary } from "openclaw/plugin-sdk/status-helpers";
|
|
14
|
+
import { clearAccountEntryFields } from "openclaw/plugin-sdk/core";
|
|
13
15
|
import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
14
|
-
import { messagingApi } from "@line/bot-sdk";
|
|
15
|
-
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
16
16
|
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-local-roots";
|
|
17
|
-
import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
|
|
18
17
|
import { loadWebMediaRaw } from "openclaw/plugin-sdk/web-media";
|
|
19
18
|
//#region extensions/line/src/webhook.ts
|
|
20
19
|
const LINE_WEBHOOK_MAX_RAW_BODY_BYTES = 64 * 1024;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { i as resolveLineAccount } from "./accounts-BqEVsDoB.js";
|
|
2
|
-
import { h as normalizeLineMessageActions, p as messageAction,
|
|
2
|
+
import { h as normalizeLineMessageActions, i as createLineSendReceipt, p as messageAction, r as runLinePushWithRetries, y as buildLineMediaMessage } from "./send-retry-CUvrarfE.js";
|
|
3
3
|
import { createChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
|
|
4
4
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
5
|
+
import { HTTPFetchError, messagingApi } from "@line/bot-sdk";
|
|
5
6
|
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
6
7
|
import { fetchWithRuntimeDispatcherOrMockedGlobal } from "openclaw/plugin-sdk/runtime-fetch";
|
|
7
|
-
import { HTTPFetchError, messagingApi } from "@line/bot-sdk";
|
|
8
|
-
import { collectErrorGraphCandidates, extractErrorCode } from "openclaw/plugin-sdk/error-runtime";
|
|
9
8
|
import { randomUUID } from "node:crypto";
|
|
10
9
|
import lineBotSdkPackage from "@line/bot-sdk/package.json" with { type: "json" };
|
|
11
10
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
12
11
|
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
13
12
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
14
|
-
import {
|
|
13
|
+
import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
|
14
|
+
import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
|
|
15
15
|
//#region extensions/line/src/channel-access-token.ts
|
|
16
16
|
function resolveLineChannelAccessToken(explicit, params) {
|
|
17
17
|
if (explicit?.trim()) return explicit.trim();
|
|
@@ -19,35 +19,69 @@ function resolveLineChannelAccessToken(explicit, params) {
|
|
|
19
19
|
return params.channelAccessToken.trim();
|
|
20
20
|
}
|
|
21
21
|
//#endregion
|
|
22
|
-
//#region extensions/line/src/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
//#region extensions/line/src/outbound-message-log.ts
|
|
23
|
+
const RECENT_SENT_LIMIT = 500;
|
|
24
|
+
const recentSentByAccount = /* @__PURE__ */ new Map();
|
|
25
|
+
function recentSentFor(accountId) {
|
|
26
|
+
const existing = recentSentByAccount.get(accountId);
|
|
27
|
+
if (existing) return existing;
|
|
28
|
+
const created = createDedupeCache({
|
|
29
|
+
ttlMs: 0,
|
|
30
|
+
maxSize: RECENT_SENT_LIMIT
|
|
31
|
+
});
|
|
32
|
+
recentSentByAccount.set(accountId, created);
|
|
33
|
+
return created;
|
|
34
|
+
}
|
|
35
|
+
function recordLineSentMessages(accountId, messageIds) {
|
|
36
|
+
if (messageIds.length === 0) return;
|
|
37
|
+
const recentSent = recentSentFor(accountId);
|
|
38
|
+
for (const messageId of messageIds) recentSent.check(messageId);
|
|
39
|
+
}
|
|
40
|
+
function quotesLineBotMessage(accountId, quotedMessageId) {
|
|
41
|
+
return recentSentByAccount.get(accountId)?.peek(quotedMessageId) ?? false;
|
|
42
|
+
}
|
|
38
43
|
//#endregion
|
|
39
44
|
//#region extensions/line/src/send.ts
|
|
40
|
-
const
|
|
45
|
+
const profileCache = {
|
|
46
|
+
values: /* @__PURE__ */ new Map(),
|
|
47
|
+
pending: /* @__PURE__ */ new Map()
|
|
48
|
+
};
|
|
49
|
+
const groupNameCache = {
|
|
50
|
+
values: /* @__PURE__ */ new Map(),
|
|
51
|
+
pending: /* @__PURE__ */ new Map()
|
|
52
|
+
};
|
|
41
53
|
const PROFILE_CACHE_TTL_MS = 300 * 1e3;
|
|
42
54
|
const PROFILE_CACHE_MAX_ENTRIES = 1e3;
|
|
43
55
|
const LINE_FLEX_ALT_TEXT_LIMIT = 1500;
|
|
44
56
|
const LINE_LOCATION_LABEL_LIMIT = 100;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
const LINE_PROVIDER_RESPONSE_MAX_BYTES = 16 * 1024;
|
|
58
|
+
function rememberLineIdentity(cache, key, value) {
|
|
59
|
+
const entry = {
|
|
60
|
+
value,
|
|
61
|
+
fetchedAt: Date.now()
|
|
62
|
+
};
|
|
63
|
+
cache.values.delete(key);
|
|
64
|
+
cache.values.set(key, entry);
|
|
65
|
+
if (cache.values.size <= PROFILE_CACHE_MAX_ENTRIES) return;
|
|
66
|
+
for (const [cachedKey, cached] of cache.values) if (entry.fetchedAt - cached.fetchedAt >= PROFILE_CACHE_TTL_MS) cache.values.delete(cachedKey);
|
|
67
|
+
pruneMapToMaxSize(cache.values, PROFILE_CACHE_MAX_ENTRIES);
|
|
68
|
+
}
|
|
69
|
+
async function loadLineIdentity(cache, key, load) {
|
|
70
|
+
const cached = cache.values.get(key);
|
|
71
|
+
if (cached && Date.now() - cached.fetchedAt < PROFILE_CACHE_TTL_MS) return cached.value;
|
|
72
|
+
const pending = cache.pending.get(key);
|
|
73
|
+
if (pending) return await pending;
|
|
74
|
+
const lookup = load().then((value) => {
|
|
75
|
+
rememberLineIdentity(cache, key, value);
|
|
76
|
+
return value;
|
|
77
|
+
});
|
|
78
|
+
cache.pending.set(key, lookup);
|
|
79
|
+
pruneMapToMaxSize(cache.pending, PROFILE_CACHE_MAX_ENTRIES);
|
|
80
|
+
try {
|
|
81
|
+
return await lookup;
|
|
82
|
+
} finally {
|
|
83
|
+
if (cache.pending.get(key) === lookup) cache.pending.delete(key);
|
|
84
|
+
}
|
|
51
85
|
}
|
|
52
86
|
function resolveLineProviderMessageIds(response, operation) {
|
|
53
87
|
const sentMessages = Array.isArray(response?.sentMessages) ? response.sentMessages : [];
|
|
@@ -74,9 +108,6 @@ function normalizeTarget(to) {
|
|
|
74
108
|
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): ${truncateUtf16Safe(normalized, 4)}…`);
|
|
75
109
|
return normalized;
|
|
76
110
|
}
|
|
77
|
-
function isLineUserChatId(chatId) {
|
|
78
|
-
return /^U/i.test(chatId);
|
|
79
|
-
}
|
|
80
111
|
function resolveLineMessagingAccount(opts) {
|
|
81
112
|
const account = resolveLineAccount({
|
|
82
113
|
cfg: requireRuntimeConfig(opts.cfg, "LINE send"),
|
|
@@ -114,15 +145,17 @@ async function sendLineProviderMessages(operation, token, request, retryKey) {
|
|
|
114
145
|
body: JSON.stringify(request)
|
|
115
146
|
});
|
|
116
147
|
const acceptedRetryConflict = retryKey !== void 0 && response.status === 409;
|
|
117
|
-
if (!response.ok && !acceptedRetryConflict)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
if (!response.ok && !acceptedRetryConflict) {
|
|
149
|
+
const body = await readResponseTextLimited(response, LINE_PROVIDER_RESPONSE_MAX_BYTES).catch(() => "");
|
|
150
|
+
throw new HTTPFetchError(`${response.status} - ${response.statusText}`, {
|
|
151
|
+
status: response.status,
|
|
152
|
+
statusText: response.statusText,
|
|
153
|
+
headers: response.headers,
|
|
154
|
+
body
|
|
155
|
+
});
|
|
156
|
+
}
|
|
123
157
|
try {
|
|
124
|
-
|
|
125
|
-
return text ? JSON.parse(text) : null;
|
|
158
|
+
return await readProviderJsonResponse(response, `LINE ${operation} response`, { maxBytes: LINE_PROVIDER_RESPONSE_MAX_BYTES });
|
|
126
159
|
} catch (error) {
|
|
127
160
|
throw createChannelPartialDeliveryError(error, {
|
|
128
161
|
messageIds: [],
|
|
@@ -136,28 +169,6 @@ function createTextMessage(text) {
|
|
|
136
169
|
text
|
|
137
170
|
};
|
|
138
171
|
}
|
|
139
|
-
function createImageMessage(originalContentUrl, previewImageUrl) {
|
|
140
|
-
return {
|
|
141
|
-
type: "image",
|
|
142
|
-
originalContentUrl,
|
|
143
|
-
previewImageUrl: previewImageUrl ?? originalContentUrl
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function createVideoMessage(originalContentUrl, previewImageUrl, trackingId) {
|
|
147
|
-
return {
|
|
148
|
-
type: "video",
|
|
149
|
-
originalContentUrl,
|
|
150
|
-
previewImageUrl,
|
|
151
|
-
...trackingId ? { trackingId } : {}
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
function createAudioMessage(originalContentUrl, durationMs) {
|
|
155
|
-
return {
|
|
156
|
-
type: "audio",
|
|
157
|
-
originalContentUrl,
|
|
158
|
-
duration: durationMs
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
172
|
function isValidLineLocation(location) {
|
|
162
173
|
return location.title.trim().length > 0 && location.address.trim().length > 0;
|
|
163
174
|
}
|
|
@@ -183,6 +194,7 @@ function logLineHttpError(err, context) {
|
|
|
183
194
|
if (typeof body === "string") logVerbose(`line: ${context} failed (${status ? `${status} ${statusText ?? ""}`.trim() : "unknown status"}): ${body}`);
|
|
184
195
|
}
|
|
185
196
|
function recordLineOutboundActivity(accountId, delivery) {
|
|
197
|
+
recordLineSentMessages(accountId, delivery.messageIds);
|
|
186
198
|
try {
|
|
187
199
|
recordChannelActivity({
|
|
188
200
|
channel: "line",
|
|
@@ -253,29 +265,12 @@ async function sendMessageLine(to, text, opts) {
|
|
|
253
265
|
const chatId = normalizeTarget(to);
|
|
254
266
|
const messages = [];
|
|
255
267
|
const mediaUrl = opts.mediaUrl?.trim();
|
|
256
|
-
if (mediaUrl) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
await validateLineMediaUrl(previewImageUrl);
|
|
263
|
-
const trackingId = isLineUserChatId(chatId) ? opts.trackingId : void 0;
|
|
264
|
-
messages.push(createVideoMessage(mediaUrl, previewImageUrl, trackingId));
|
|
265
|
-
break;
|
|
266
|
-
}
|
|
267
|
-
case "audio":
|
|
268
|
-
messages.push(createAudioMessage(mediaUrl, opts.durationMs ?? 6e4));
|
|
269
|
-
break;
|
|
270
|
-
default:
|
|
271
|
-
{
|
|
272
|
-
const previewImageUrl = opts.previewImageUrl?.trim() || mediaUrl;
|
|
273
|
-
await validateLineMediaUrl(previewImageUrl);
|
|
274
|
-
messages.push(createImageMessage(mediaUrl, previewImageUrl));
|
|
275
|
-
}
|
|
276
|
-
break;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
268
|
+
if (mediaUrl) messages.push(await buildLineMediaMessage(mediaUrl, {
|
|
269
|
+
mediaKind: opts.mediaKind,
|
|
270
|
+
previewImageUrl: opts.previewImageUrl,
|
|
271
|
+
durationMs: opts.durationMs,
|
|
272
|
+
trackingId: opts.trackingId
|
|
273
|
+
}, chatId));
|
|
279
274
|
if (text?.trim()) messages.push(createTextMessage(text.trim()));
|
|
280
275
|
if (messages.length === 0) throw new Error("Message must be non-empty for LINE sends");
|
|
281
276
|
if (opts.replyToken) {
|
|
@@ -322,9 +317,10 @@ function createFlexMessage(altText, contents) {
|
|
|
322
317
|
};
|
|
323
318
|
}
|
|
324
319
|
async function pushImageMessage(to, originalContentUrl, previewImageUrl, opts) {
|
|
325
|
-
await
|
|
326
|
-
|
|
327
|
-
|
|
320
|
+
return pushLineMessages(to, [await buildLineMediaMessage(originalContentUrl, {
|
|
321
|
+
mediaKind: "image",
|
|
322
|
+
previewImageUrl
|
|
323
|
+
}, to)], opts, { verboseMessage: (chatId) => `line: pushed image to ${chatId}` });
|
|
328
324
|
}
|
|
329
325
|
async function pushLocationMessage(to, location, opts) {
|
|
330
326
|
return pushLineMessages(to, [createLocationMessage(location)], opts, { verboseMessage: (chatId) => `line: pushed location to ${chatId}` });
|
|
@@ -366,26 +362,43 @@ async function showLoadingAnimation(chatId, opts) {
|
|
|
366
362
|
logVerbose(`line: loading animation failed (non-fatal): ${String(err)}`);
|
|
367
363
|
}
|
|
368
364
|
}
|
|
365
|
+
function lineProfileCacheKey(accountId, userId, scope) {
|
|
366
|
+
const conversation = scope.groupId ? ["group", scope.groupId] : scope.roomId ? ["room", scope.roomId] : ["direct"];
|
|
367
|
+
return JSON.stringify([
|
|
368
|
+
accountId,
|
|
369
|
+
"profile",
|
|
370
|
+
...conversation,
|
|
371
|
+
userId
|
|
372
|
+
]);
|
|
373
|
+
}
|
|
374
|
+
function fetchLineMemberProfile(client, userId, scope) {
|
|
375
|
+
if (scope.groupId) return client.getGroupMemberProfile(scope.groupId, userId);
|
|
376
|
+
if (scope.roomId) return client.getRoomMemberProfile(scope.roomId, userId);
|
|
377
|
+
return client.getProfile(userId);
|
|
378
|
+
}
|
|
369
379
|
async function getUserProfile(userId, opts) {
|
|
370
|
-
|
|
371
|
-
const cached = userProfileCache.get(userId);
|
|
372
|
-
if (cached && Date.now() - cached.fetchedAt < PROFILE_CACHE_TTL_MS) return {
|
|
373
|
-
displayName: cached.displayName,
|
|
374
|
-
pictureUrl: cached.pictureUrl
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
const { client } = createLineMessagingClient(opts);
|
|
380
|
+
const useCache = opts.useCache ?? true;
|
|
378
381
|
try {
|
|
379
|
-
const
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
382
|
+
const { account, token } = resolveLineMessagingAccount(opts);
|
|
383
|
+
const cacheKey = lineProfileCacheKey(account.accountId, userId, opts);
|
|
384
|
+
const load = async () => {
|
|
385
|
+
try {
|
|
386
|
+
const profile = await fetchLineMemberProfile(new messagingApi.MessagingApiClient({ channelAccessToken: token }), userId, opts);
|
|
387
|
+
return {
|
|
388
|
+
displayName: profile.displayName,
|
|
389
|
+
pictureUrl: profile.pictureUrl
|
|
390
|
+
};
|
|
391
|
+
} catch (err) {
|
|
392
|
+
logVerbose(`line: failed to fetch profile for ${userId}: ${String(err)}`);
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
383
395
|
};
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
396
|
+
if (!useCache) {
|
|
397
|
+
const profile = await load();
|
|
398
|
+
rememberLineIdentity(profileCache, cacheKey, profile);
|
|
399
|
+
return profile;
|
|
400
|
+
}
|
|
401
|
+
return await loadLineIdentity(profileCache, cacheKey, load);
|
|
389
402
|
} catch (err) {
|
|
390
403
|
logVerbose(`line: failed to fetch profile for ${userId}: ${String(err)}`);
|
|
391
404
|
return null;
|
|
@@ -394,5 +407,26 @@ async function getUserProfile(userId, opts) {
|
|
|
394
407
|
async function getUserDisplayName(userId, opts) {
|
|
395
408
|
return (await getUserProfile(userId, opts))?.displayName ?? userId;
|
|
396
409
|
}
|
|
410
|
+
async function getLineGroupName(groupId, opts) {
|
|
411
|
+
try {
|
|
412
|
+
const { account, token } = resolveLineMessagingAccount(opts);
|
|
413
|
+
const cacheKey = JSON.stringify([
|
|
414
|
+
account.accountId,
|
|
415
|
+
"group",
|
|
416
|
+
groupId
|
|
417
|
+
]);
|
|
418
|
+
return await loadLineIdentity(groupNameCache, cacheKey, async () => {
|
|
419
|
+
try {
|
|
420
|
+
return (await new messagingApi.MessagingApiClient({ channelAccessToken: token }).getGroupSummary(groupId)).groupName.trim() || void 0;
|
|
421
|
+
} catch (err) {
|
|
422
|
+
logVerbose(`line: failed to fetch group summary for ${groupId}: ${String(err)}`);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
} catch (err) {
|
|
427
|
+
logVerbose(`line: failed to fetch group summary for ${groupId}: ${String(err)}`);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
397
431
|
//#endregion
|
|
398
|
-
export {
|
|
432
|
+
export { showLoadingAnimation as _, getLineGroupName as a, pushFlexMessage as c, pushMessageLine as d, pushMessagesLine as f, sendMessageLine as g, replyMessageLine as h, createTextMessageWithQuickReplies as i, pushImageMessage as l, pushTextMessageWithQuickReplies as m, createLocationMessage as n, getUserDisplayName as o, pushTemplateMessage as p, createQuickReplyItems as r, getUserProfile as s, createFlexMessage as t, pushLocationMessage as u, quotesLineBotMessage as v, resolveLineChannelAccessToken as y };
|