@openclaw/nextcloud-talk 2026.10.1 → 2026.10.5-beta.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __exportAll, n as legacyConfigRules, o as __reExport, r as normalizeCompatibilityConfig } from "./doctor-contract-DwH950tH.mjs";
|
|
2
|
-
import { listNextcloudTalkAccountIds
|
|
2
|
+
import { listNextcloudTalkAccountIds, mergeNextcloudTalkAccountConfig, resolveDefaultNextcloudTalkAccountId } from "../configured-state.js";
|
|
3
3
|
import { a as logInboundDrop, c as warnMissingProviderGroupPolicyFallbackOnce, i as fetchWithSsrFGuard, l as getNextcloudTalkRuntime, n as createChannelPairingController, o as resolveAllowlistProviderRuntimeGroupPolicy, r as deliverFormattedTextWithAttachments, s as resolveDefaultGroupPolicy, t as GROUP_POLICY_BLOCKED_LABEL, u as getOptionalNextcloudTalkRuntime } from "./runtime-api-DVkVOUSo.mjs";
|
|
4
4
|
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-Bvm0PmP3.mjs";
|
|
5
5
|
import { describeWebhookAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
@@ -9,7 +9,6 @@ import { createAllowlistProviderRouteAllowlistWarningCollector, createConditiona
|
|
|
9
9
|
import { buildWebhookChannelStatusSummary, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
|
|
10
10
|
import { convertMarkdownTables, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
11
11
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId, resolveAccountWithDefaultFallback } from "openclaw/plugin-sdk/account-core";
|
|
12
|
-
import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
|
|
13
12
|
import { tryReadSecretFileSync } from "openclaw/plugin-sdk/secret-file-runtime";
|
|
14
13
|
import { buildSecretInputSchema, hasConfiguredSecretInput, resolveSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
15
14
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, readNonEmptyStringPreservingWhitespace } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -17,7 +16,7 @@ import { createChannelApprovalAuth } from "openclaw/plugin-sdk/approval-auth-run
|
|
|
17
16
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
18
17
|
import { parseStrictNonNegativeInteger, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
19
18
|
import { readProviderJsonResponse, readProviderTextResponse } from "openclaw/plugin-sdk/provider-http";
|
|
20
|
-
import {
|
|
19
|
+
import { createChannelInboundEnvelopeBuilderAsync } from "openclaw/plugin-sdk/channel-inbound";
|
|
21
20
|
import { SsrFBlockedError, ssrfPolicyFromPrivateNetworkOptIn, ssrfPolicyFromPrivateNetworkOptIn as ssrfPolicyFromPrivateNetworkOptIn$1 } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
22
21
|
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
23
22
|
import { redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
@@ -38,6 +37,7 @@ import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
|
|
|
38
37
|
import { bindIngressLifecycleToReplyOptions, createAccountStatusSink, createChannelIngressMonitor, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, resolveChannelStreamingBlockEnabled, runPassiveAccountLifecycle } from "openclaw/plugin-sdk/channel-outbound";
|
|
39
38
|
import { channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
|
|
40
39
|
import { channelIngressRoutes } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
40
|
+
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
|
41
41
|
import { safeParseJson, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
42
42
|
import { buildChannelKeyCandidates, normalizeChannelSlug, resolveChannelEntryMatchWithFallback } from "openclaw/plugin-sdk/channel-targets";
|
|
43
43
|
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
@@ -49,7 +49,6 @@ import { resolvePersistentDedupePluginStateNamespace } from "openclaw/plugin-sdk
|
|
|
49
49
|
import { jsonResult, readStringParam, resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
|
|
50
50
|
import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
|
|
51
51
|
import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
|
|
52
|
-
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1 } from "openclaw/plugin-sdk/routing";
|
|
53
52
|
import { applyAccountNameToChannelSection, baseUrlTextInput, createPromptParsedAllowFromForAccount, createSetupTranslator, createStandardChannelSetupStatus, defineTokenCredential, formatDocsLink, patchScopedAccountConfig, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
|
54
53
|
import { createSetupInputPresenceValidator, createSetupTranslator as createSetupTranslator$1, mergeAllowFromEntries } from "openclaw/plugin-sdk/setup-runtime";
|
|
55
54
|
import { formatDocsLink as formatDocsLink$1 } from "openclaw/plugin-sdk/setup-tools";
|
|
@@ -87,14 +86,6 @@ function resolveNextcloudTalkApiCredentials(params) {
|
|
|
87
86
|
}
|
|
88
87
|
//#endregion
|
|
89
88
|
//#region extensions/nextcloud-talk/src/accounts.ts
|
|
90
|
-
const debugAccounts = (...args) => {
|
|
91
|
-
if (isTruthyEnvValue(process.env.OPENCLAW_DEBUG_NEXTCLOUD_TALK_ACCOUNTS)) console.warn("[nextcloud-talk:accounts]", ...args);
|
|
92
|
-
};
|
|
93
|
-
function listNextcloudTalkAccountIds(cfg) {
|
|
94
|
-
const ids = listNextcloudTalkAccountIds$1(cfg);
|
|
95
|
-
debugAccounts("listNextcloudTalkAccountIds", ids);
|
|
96
|
-
return ids;
|
|
97
|
-
}
|
|
98
89
|
function resolveNextcloudTalkSecret(accountId, merged) {
|
|
99
90
|
const configuredSecret = resolveSecretInputString({
|
|
100
91
|
value: merged.botSecret,
|
|
@@ -146,12 +137,6 @@ function resolveNextcloudTalkAccount(params) {
|
|
|
146
137
|
const enabled = baseEnabled && accountEnabled;
|
|
147
138
|
const secretResolution = resolveNextcloudTalkSecret(accountId, merged);
|
|
148
139
|
const baseUrl = merged.baseUrl?.trim()?.replace(/\/$/, "") ?? "";
|
|
149
|
-
debugAccounts("resolve", {
|
|
150
|
-
accountId,
|
|
151
|
-
enabled,
|
|
152
|
-
secretSource: secretResolution.source,
|
|
153
|
-
baseUrl: baseUrl ? "[set]" : "[missing]"
|
|
154
|
-
});
|
|
155
140
|
return {
|
|
156
141
|
accountId,
|
|
157
142
|
enabled,
|
|
@@ -252,9 +237,6 @@ function extractNextcloudTalkHeaders(headers) {
|
|
|
252
237
|
backend
|
|
253
238
|
};
|
|
254
239
|
}
|
|
255
|
-
/**
|
|
256
|
-
* Generate signature headers for an outbound request to Nextcloud Talk.
|
|
257
|
-
*/
|
|
258
240
|
function generateNextcloudTalkSignature(params) {
|
|
259
241
|
const { body, secret } = params;
|
|
260
242
|
const random = randomBytes(32).toString("hex");
|
|
@@ -267,14 +249,10 @@ function generateNextcloudTalkSignature(params) {
|
|
|
267
249
|
//#region extensions/nextcloud-talk/src/bot-preflight.ts
|
|
268
250
|
const BOT_FEATURE_RESPONSE = 2;
|
|
269
251
|
function normalizeUrlForMatch(value) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
return url.toString().replace(/\/$/, "");
|
|
275
|
-
} catch {
|
|
276
|
-
return value.trim().replace(/\/$/, "");
|
|
277
|
-
}
|
|
252
|
+
const trimmed = value?.trim() ?? "";
|
|
253
|
+
const url = URL.parse(trimmed);
|
|
254
|
+
if (url) url.hash = "";
|
|
255
|
+
return (url?.toString() ?? trimmed).replace(/\/$/, "");
|
|
278
256
|
}
|
|
279
257
|
function formatMissingResponseFeatureMessage(bot, features) {
|
|
280
258
|
const id = bot.id == null ? "unknown" : String(bot.id);
|
|
@@ -287,14 +265,14 @@ async function probeNextcloudTalkBotResponseFeature(params) {
|
|
|
287
265
|
ok: true,
|
|
288
266
|
skipped: true,
|
|
289
267
|
code: "missing_base_url",
|
|
290
|
-
message: "Nextcloud Talk bot response feature
|
|
268
|
+
message: "Nextcloud Talk bot response feature check skipped: baseUrl is not configured."
|
|
291
269
|
};
|
|
292
270
|
const webhookUrl = normalizeUrlForMatch(account.config.webhookPublicUrl);
|
|
293
271
|
if (!webhookUrl) return {
|
|
294
272
|
ok: true,
|
|
295
273
|
skipped: true,
|
|
296
274
|
code: "missing_webhook_url",
|
|
297
|
-
message: "Nextcloud Talk bot response feature
|
|
275
|
+
message: "Nextcloud Talk bot response feature check skipped: webhookPublicUrl is not configured."
|
|
298
276
|
};
|
|
299
277
|
const credentials = resolveNextcloudTalkApiCredentials({
|
|
300
278
|
apiUser: account.config.apiUser,
|
|
@@ -305,7 +283,7 @@ async function probeNextcloudTalkBotResponseFeature(params) {
|
|
|
305
283
|
ok: true,
|
|
306
284
|
skipped: true,
|
|
307
285
|
code: "missing_api_credentials",
|
|
308
|
-
message: "Nextcloud Talk bot response feature
|
|
286
|
+
message: "Nextcloud Talk bot response feature check skipped: apiUser/apiPassword are not configured."
|
|
309
287
|
};
|
|
310
288
|
const url = `${baseUrl}/ocs/v2.php/apps/spreed/api/v1/bot/admin`;
|
|
311
289
|
const auth = Buffer.from(`${credentials.apiUser}:${credentials.apiPassword}`, "utf-8").toString("base64");
|
|
@@ -321,7 +299,7 @@ async function probeNextcloudTalkBotResponseFeature(params) {
|
|
|
321
299
|
}
|
|
322
300
|
},
|
|
323
301
|
auditContext: "nextcloud-talk.bot-response-preflight",
|
|
324
|
-
policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config),
|
|
302
|
+
policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config.network?.dangerouslyAllowPrivateNetwork),
|
|
325
303
|
timeoutMs
|
|
326
304
|
});
|
|
327
305
|
try {
|
|
@@ -331,15 +309,15 @@ async function probeNextcloudTalkBotResponseFeature(params) {
|
|
|
331
309
|
ok: false,
|
|
332
310
|
code: "api_error",
|
|
333
311
|
status: response.status,
|
|
334
|
-
message: `Nextcloud Talk bot response feature
|
|
312
|
+
message: `Nextcloud Talk bot response feature check failed (${response.status})${body ? `: ${body}` : ""}`
|
|
335
313
|
};
|
|
336
314
|
}
|
|
337
|
-
const payload = await readProviderJsonResponse(response, "Nextcloud Talk bot response feature
|
|
315
|
+
const payload = await readProviderJsonResponse(response, "Nextcloud Talk bot response feature check failed");
|
|
338
316
|
const bot = (Array.isArray(payload.ocs?.data) ? payload.ocs.data : []).find((entry) => normalizeUrlForMatch(entry.url) === webhookUrl);
|
|
339
317
|
if (!bot) return {
|
|
340
318
|
ok: false,
|
|
341
319
|
code: "bot_not_found",
|
|
342
|
-
message: `Nextcloud Talk bot response feature
|
|
320
|
+
message: `Nextcloud Talk bot response feature check could not find a bot with webhook URL ${webhookUrl}.`
|
|
343
321
|
};
|
|
344
322
|
const features = parseStrictNonNegativeInteger(bot.features);
|
|
345
323
|
if (features == null || (features & BOT_FEATURE_RESPONSE) !== BOT_FEATURE_RESPONSE) return {
|
|
@@ -365,7 +343,7 @@ async function probeNextcloudTalkBotResponseFeature(params) {
|
|
|
365
343
|
return {
|
|
366
344
|
ok: false,
|
|
367
345
|
code: "request_failed",
|
|
368
|
-
message: `Nextcloud Talk bot response feature
|
|
346
|
+
message: `Nextcloud Talk bot response feature check failed: ${error instanceof Error ? error.message : formatErrorMessage(error)}`
|
|
369
347
|
};
|
|
370
348
|
}
|
|
371
349
|
}
|
|
@@ -505,22 +483,15 @@ function normalizePathSeparators(pathname) {
|
|
|
505
483
|
if (collapsed.length <= 1) return collapsed;
|
|
506
484
|
return collapsed.replace(/\/+$/, "");
|
|
507
485
|
}
|
|
508
|
-
function resolveDotSegments(pathname) {
|
|
509
|
-
try {
|
|
510
|
-
return new URL(pathname, "http://localhost").pathname;
|
|
511
|
-
} catch {
|
|
512
|
-
return pathname;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
486
|
function normalizePathForSecurity(pathname) {
|
|
516
|
-
return normalizePathSeparators(normalizeLowercaseStringOrEmpty$1(
|
|
487
|
+
return normalizePathSeparators(normalizeLowercaseStringOrEmpty$1(URL.parse(pathname, "http://localhost")?.pathname ?? pathname)) || "/";
|
|
517
488
|
}
|
|
518
|
-
function buildCanonicalPathCandidates(pathname
|
|
489
|
+
function buildCanonicalPathCandidates(pathname) {
|
|
519
490
|
const candidates = /* @__PURE__ */ new Set([normalizePathForSecurity(pathname)]);
|
|
520
491
|
let decoded = pathname;
|
|
521
492
|
let malformedEncoding = false;
|
|
522
493
|
let decodePasses = 0;
|
|
523
|
-
for (let pass = 0; pass <
|
|
494
|
+
for (let pass = 0; pass < MAX_PATH_DECODE_PASSES; pass++) {
|
|
524
495
|
let nextDecoded;
|
|
525
496
|
try {
|
|
526
497
|
nextDecoded = decodeURIComponent(decoded);
|
|
@@ -607,7 +578,7 @@ function resolveNextcloudTalkLegacyWebhook(config) {
|
|
|
607
578
|
function describeNextcloudTalkWebhookRouteConflict(path, gatewayPort) {
|
|
608
579
|
const pathname = URL.parse(path, "http://localhost")?.pathname ?? path;
|
|
609
580
|
const probe = classifyGatewayProbePath(pathname);
|
|
610
|
-
const reason = probe !== "outside" && probe !== "namespace" ? "is reserved for Gateway
|
|
581
|
+
const reason = probe !== "outside" && probe !== "namespace" ? "is reserved for Gateway checks" : isProtectedPluginRoutePathFromContext(resolvePluginRoutePathContext(pathname)) ? "requires Gateway authentication" : void 0;
|
|
611
582
|
if (!reason) return;
|
|
612
583
|
return `Webhook path "${path}" ${reason} and cannot receive Nextcloud callbacks on the Gateway port. Set webhookPath to "${DEFAULT_NEXTCLOUD_TALK_WEBHOOK_PATH}" and update the Nextcloud bot callback and reverse-proxy upstream to Gateway port ${gatewayPort}${DEFAULT_NEXTCLOUD_TALK_WEBHOOK_PATH}.`;
|
|
613
584
|
}
|
|
@@ -808,7 +779,7 @@ async function resolveNextcloudTalkRoomKind(params) {
|
|
|
808
779
|
}
|
|
809
780
|
},
|
|
810
781
|
auditContext: "nextcloud-talk.room-info",
|
|
811
|
-
policy: ssrfPolicyFromPrivateNetworkOptIn(account.config),
|
|
782
|
+
policy: ssrfPolicyFromPrivateNetworkOptIn(account.config.network?.dangerouslyAllowPrivateNetwork),
|
|
812
783
|
timeoutMs: params.timeoutMs ?? NEXTCLOUD_TALK_ROOM_INFO_TIMEOUT_MS
|
|
813
784
|
});
|
|
814
785
|
} catch (error) {
|
|
@@ -865,7 +836,7 @@ function resolveNextcloudTalkSendContext(opts) {
|
|
|
865
836
|
cfg,
|
|
866
837
|
accountId: opts.accountId
|
|
867
838
|
});
|
|
868
|
-
const baseUrl =
|
|
839
|
+
const baseUrl = account.baseUrl;
|
|
869
840
|
const secret = opts.secret?.trim() ?? account.secret;
|
|
870
841
|
if (!baseUrl) throw new Error(`Nextcloud Talk baseUrl missing for account "${account.accountId}" (set channels.nextcloud-talk.baseUrl).`);
|
|
871
842
|
if (!secret) throw new Error(account.tokenStatus === "configured_unavailable" ? `Nextcloud Talk bot secret is configured but unavailable for account "${account.accountId}" (check the configured channels.nextcloud-talk.botSecret/botSecretFile).` : `Nextcloud Talk bot secret missing for account "${account.accountId}" (set channels.nextcloud-talk.botSecret/botSecretFile or NEXTCLOUD_TALK_BOT_SECRET for default).`);
|
|
@@ -891,9 +862,10 @@ async function sendMessageNextcloudTalk(to, text, opts) {
|
|
|
891
862
|
accountId: account.accountId
|
|
892
863
|
});
|
|
893
864
|
const message = convertMarkdownTables(text.trim(), tableMode);
|
|
894
|
-
const body = {
|
|
895
|
-
|
|
896
|
-
|
|
865
|
+
const body = JSON.stringify({
|
|
866
|
+
message,
|
|
867
|
+
replyTo: opts.replyTo || void 0
|
|
868
|
+
});
|
|
897
869
|
const { random, signature } = generateNextcloudTalkSignature({
|
|
898
870
|
body: message,
|
|
899
871
|
secret
|
|
@@ -911,10 +883,10 @@ async function sendMessageNextcloudTalk(to, text, opts) {
|
|
|
911
883
|
"X-Nextcloud-Talk-Bot-Random": random,
|
|
912
884
|
"X-Nextcloud-Talk-Bot-Signature": signature
|
|
913
885
|
},
|
|
914
|
-
body
|
|
886
|
+
body
|
|
915
887
|
},
|
|
916
888
|
auditContext: "nextcloud-talk-send",
|
|
917
|
-
policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config),
|
|
889
|
+
policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config.network?.dangerouslyAllowPrivateNetwork),
|
|
918
890
|
timeoutMs: opts.timeoutMs ?? NEXTCLOUD_TALK_SEND_TIMEOUT_MS
|
|
919
891
|
});
|
|
920
892
|
try {
|
|
@@ -936,7 +908,6 @@ async function sendMessageNextcloudTalk(to, text, opts) {
|
|
|
936
908
|
if (data.ocs?.data?.id != null) messageId = String(data.ocs.data.id);
|
|
937
909
|
if (typeof data.ocs?.data?.timestamp === "number") timestamp = data.ocs.data.timestamp;
|
|
938
910
|
} catch {}
|
|
939
|
-
if (opts.verbose) console.log(`[nextcloud-talk] Sent message ${messageId} to room ${roomToken}`);
|
|
940
911
|
getOptionalNextcloudTalkRuntime()?.channel.activity.record({
|
|
941
912
|
channel: "nextcloud-talk",
|
|
942
913
|
accountId: account.accountId,
|
|
@@ -983,7 +954,7 @@ async function sendReactionNextcloudTalk(roomToken, messageId, reaction, opts) {
|
|
|
983
954
|
body
|
|
984
955
|
},
|
|
985
956
|
auditContext: "nextcloud-talk-reaction",
|
|
986
|
-
policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config),
|
|
957
|
+
policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config.network?.dangerouslyAllowPrivateNetwork),
|
|
987
958
|
timeoutMs: opts.timeoutMs ?? NEXTCLOUD_TALK_SEND_TIMEOUT_MS
|
|
988
959
|
});
|
|
989
960
|
try {
|
|
@@ -1002,37 +973,6 @@ const CHANNEL_ID = "nextcloud-talk";
|
|
|
1002
973
|
function hasAllowEntries(entries) {
|
|
1003
974
|
return normalizeNextcloudTalkAllowlist(entries).length > 0;
|
|
1004
975
|
}
|
|
1005
|
-
function roomRoutes(params) {
|
|
1006
|
-
if (!params.isGroup) return [];
|
|
1007
|
-
const roomSenderConfigured = params.groupPolicy === "allowlist" && hasAllowEntries(params.roomAllowFrom);
|
|
1008
|
-
return channelIngressRoutes(params.roomMatch.allowlistConfigured && {
|
|
1009
|
-
id: "nextcloud-talk:room",
|
|
1010
|
-
allowed: params.roomMatch.allowed,
|
|
1011
|
-
precedence: 0,
|
|
1012
|
-
matchId: "nextcloud-talk-room",
|
|
1013
|
-
blockReason: "room_not_allowlisted"
|
|
1014
|
-
}, params.roomConfig?.enabled === false && {
|
|
1015
|
-
id: "nextcloud-talk:room-enabled",
|
|
1016
|
-
enabled: false,
|
|
1017
|
-
precedence: 10,
|
|
1018
|
-
blockReason: "room_disabled"
|
|
1019
|
-
}, roomSenderConfigured && {
|
|
1020
|
-
id: "nextcloud-talk:room-sender",
|
|
1021
|
-
kind: "nestedAllowlist",
|
|
1022
|
-
precedence: 20,
|
|
1023
|
-
blockReason: "room_sender_not_allowlisted",
|
|
1024
|
-
...!hasAllowEntries(params.outerGroupAllowFrom) ? {
|
|
1025
|
-
senderPolicy: "replace",
|
|
1026
|
-
senderAllowFrom: params.roomAllowFrom
|
|
1027
|
-
} : {
|
|
1028
|
-
allowed: resolveNextcloudTalkAllowlistMatch({
|
|
1029
|
-
allowFrom: params.roomAllowFrom,
|
|
1030
|
-
senderId: params.senderId
|
|
1031
|
-
}).allowed,
|
|
1032
|
-
matchId: "nextcloud-talk-room-sender"
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
976
|
async function handleNextcloudTalkInbound(params) {
|
|
1037
977
|
const { message, account, config, runtime, statusSink } = params;
|
|
1038
978
|
const core = getNextcloudTalkRuntime();
|
|
@@ -1105,15 +1045,33 @@ async function handleNextcloudTalkInbound(params) {
|
|
|
1105
1045
|
id: isGroup ? roomToken : senderId
|
|
1106
1046
|
},
|
|
1107
1047
|
contextBinding,
|
|
1108
|
-
route:
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1048
|
+
route: isGroup ? channelIngressRoutes(roomMatch.allowlistConfigured && {
|
|
1049
|
+
id: "nextcloud-talk:room",
|
|
1050
|
+
allowed: roomMatch.allowed,
|
|
1051
|
+
precedence: 0,
|
|
1052
|
+
matchId: "nextcloud-talk-room",
|
|
1053
|
+
blockReason: "room_not_allowlisted"
|
|
1054
|
+
}, roomConfig?.enabled === false && {
|
|
1055
|
+
id: "nextcloud-talk:room-enabled",
|
|
1056
|
+
enabled: false,
|
|
1057
|
+
precedence: 10,
|
|
1058
|
+
blockReason: "room_disabled"
|
|
1059
|
+
}, groupPolicy === "allowlist" && hasAllowEntries(roomAllowFrom) && {
|
|
1060
|
+
id: "nextcloud-talk:room-sender",
|
|
1061
|
+
kind: "nestedAllowlist",
|
|
1062
|
+
precedence: 20,
|
|
1063
|
+
blockReason: "room_sender_not_allowlisted",
|
|
1064
|
+
...!hasAllowEntries(outerGroupAllowFrom) ? {
|
|
1065
|
+
senderPolicy: "replace",
|
|
1066
|
+
senderAllowFrom: roomAllowFrom
|
|
1067
|
+
} : {
|
|
1068
|
+
allowed: resolveNextcloudTalkAllowlistMatch({
|
|
1069
|
+
allowFrom: roomAllowFrom,
|
|
1070
|
+
senderId
|
|
1071
|
+
}).allowed,
|
|
1072
|
+
matchId: "nextcloud-talk-room-sender"
|
|
1073
|
+
}
|
|
1074
|
+
}) : [],
|
|
1117
1075
|
dmPolicy: account.config.dmPolicy ?? "pairing",
|
|
1118
1076
|
groupPolicy,
|
|
1119
1077
|
policy: {
|
|
@@ -1192,7 +1150,7 @@ async function handleNextcloudTalkInbound(params) {
|
|
|
1192
1150
|
}
|
|
1193
1151
|
const mentionRegexes = core.channel.mentions.buildMentionRegexes(config);
|
|
1194
1152
|
const wasMentioned = mentionRegexes.length ? core.channel.mentions.matchesMentionPatterns(rawBody, mentionRegexes) : false;
|
|
1195
|
-
const
|
|
1153
|
+
const route = resolveAgentRoute({
|
|
1196
1154
|
cfg: config,
|
|
1197
1155
|
channel: CHANNEL_ID,
|
|
1198
1156
|
accountId: account.accountId,
|
|
@@ -1212,7 +1170,10 @@ async function handleNextcloudTalkInbound(params) {
|
|
|
1212
1170
|
return;
|
|
1213
1171
|
}
|
|
1214
1172
|
const fromLabel = isGroup ? `room:${roomName || roomToken}` : senderName || `user:${senderId}`;
|
|
1215
|
-
const body =
|
|
1173
|
+
const body = (await createChannelInboundEnvelopeBuilderAsync({
|
|
1174
|
+
cfg: config,
|
|
1175
|
+
route
|
|
1176
|
+
}))({
|
|
1216
1177
|
channel: "Nextcloud Talk",
|
|
1217
1178
|
from: fromLabel,
|
|
1218
1179
|
timestamp: message.timestamp,
|
|
@@ -1757,15 +1718,11 @@ function createNextcloudTalkWebhookSpool(options) {
|
|
|
1757
1718
|
//#endregion
|
|
1758
1719
|
//#region extensions/nextcloud-talk/src/monitor-runtime.ts
|
|
1759
1720
|
function normalizeOrigin(value) {
|
|
1760
|
-
|
|
1761
|
-
return normalizeLowercaseStringOrEmpty(new URL(value).origin);
|
|
1762
|
-
} catch {
|
|
1763
|
-
return null;
|
|
1764
|
-
}
|
|
1721
|
+
return URL.parse(value)?.origin.toLowerCase() ?? null;
|
|
1765
1722
|
}
|
|
1766
1723
|
async function monitorNextcloudTalkProvider(opts) {
|
|
1767
1724
|
const core = getNextcloudTalkRuntime();
|
|
1768
|
-
const cfg = opts.config
|
|
1725
|
+
const cfg = opts.config;
|
|
1769
1726
|
const account = resolveNextcloudTalkAccount({
|
|
1770
1727
|
cfg,
|
|
1771
1728
|
accountId: opts.accountId
|
|
@@ -1782,7 +1739,7 @@ async function monitorNextcloudTalkProvider(opts) {
|
|
|
1782
1739
|
accountId: account.accountId
|
|
1783
1740
|
});
|
|
1784
1741
|
const expectedBackendOrigin = normalizeOrigin(account.baseUrl);
|
|
1785
|
-
const spool =
|
|
1742
|
+
const spool = createNextcloudTalkWebhookSpool({
|
|
1786
1743
|
accountId: account.accountId,
|
|
1787
1744
|
runtime,
|
|
1788
1745
|
abortSignal: opts.abortSignal,
|
|
@@ -1793,8 +1750,7 @@ async function monitorNextcloudTalkProvider(opts) {
|
|
|
1793
1750
|
direction: "inbound",
|
|
1794
1751
|
at: message.timestamp
|
|
1795
1752
|
});
|
|
1796
|
-
|
|
1797
|
-
else await handleNextcloudTalkInbound({
|
|
1753
|
+
await handleNextcloudTalkInbound({
|
|
1798
1754
|
message,
|
|
1799
1755
|
account,
|
|
1800
1756
|
config: cfg,
|
package/dist/api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as nextcloudTalkPlugin } from "./.setup/channel-
|
|
1
|
+
import { t as nextcloudTalkPlugin } from "./.setup/channel-DTKYMnlK.mjs";
|
|
2
2
|
export { nextcloudTalkPlugin };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as nextcloudTalkPlugin } from "./.setup/channel-
|
|
1
|
+
import { t as nextcloudTalkPlugin } from "./.setup/channel-DTKYMnlK.mjs";
|
|
2
2
|
export { nextcloudTalkPlugin };
|
package/dist/setup-entry.js
CHANGED
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
var setup_entry_default = defineBundledChannelSetupEntry({
|
|
5
5
|
importMetaUrl: import.meta.url,
|
|
6
6
|
plugin: {
|
|
7
|
-
specifier: fileURLToPath(new URL(".setup/api-
|
|
7
|
+
specifier: fileURLToPath(new URL(".setup/api-DbUH-yZ4.mjs", import.meta.url).href),
|
|
8
8
|
exportName: "nextcloudTalkPlugin"
|
|
9
9
|
},
|
|
10
10
|
secrets: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/nextcloud-talk",
|
|
3
|
-
"version": "2026.10.1",
|
|
3
|
+
"version": "2026.10.5-beta.1",
|
|
4
4
|
"description": "OpenClaw Nextcloud Talk channel plugin for conversations.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"openclaw": ">=2026.10.1"
|
|
11
|
+
"openclaw": ">=2026.10.5-beta.1"
|
|
12
12
|
},
|
|
13
13
|
"peerDependenciesMeta": {
|
|
14
14
|
"openclaw": {
|
|
@@ -130,10 +130,10 @@
|
|
|
130
130
|
"minHostVersion": ">=2026.4.10"
|
|
131
131
|
},
|
|
132
132
|
"compat": {
|
|
133
|
-
"pluginApi": ">=2026.10.1"
|
|
133
|
+
"pluginApi": ">=2026.10.5-beta.1"
|
|
134
134
|
},
|
|
135
135
|
"build": {
|
|
136
|
-
"openclawVersion": "2026.10.1"
|
|
136
|
+
"openclawVersion": "2026.10.5-beta.1"
|
|
137
137
|
},
|
|
138
138
|
"release": {
|
|
139
139
|
"publishToClawHub": true,
|