@openclaw/nextcloud-talk 2026.10.10-beta.5 → 2026.11.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.
- package/dist/.setup/api-BvrRSilb.mjs +2 -0
- package/dist/.setup/{channel-B8-CvvK1.mjs → channel-BA1-OoqO.mjs} +1724 -994
- package/dist/.setup/{doctor-contract-DwH950tH.mjs → doctor-contract-CkWQa5uZ.mjs} +6 -12
- package/dist/.setup/outbound-media-CpFe1Xgz.mjs +303 -0
- package/dist/.setup/reply-BEkv387l.mjs +64 -0
- package/dist/.setup/{runtime-api-DVkVOUSo.mjs → runtime-api-CGy_KpdV.mjs} +2 -4
- package/dist/.setup/{secret-contract-api-DoyAH9bS.mjs → secret-contract-api-QMihLdr1.mjs} +1 -1
- package/dist/.setup/secret-contract-yjCLewtg.mjs +19 -0
- package/dist/.source-module-urls/3332e832383d54fca83a3cfe8961ecdecf361c1eec0972c99f00a876d9481d98.json +1 -1
- package/dist/api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/configured-state.js +3 -7
- package/dist/doctor-contract-api.js +1 -1
- package/dist/index.js +1 -2
- package/dist/runtime-api.js +1 -1
- package/dist/secret-contract-api.js +1 -1
- package/dist/setup-entry.js +3 -4
- package/node_modules/saxes/README.md +323 -0
- package/node_modules/saxes/node_modules/xmlchars/LICENSE +18 -0
- package/node_modules/saxes/node_modules/xmlchars/README.md +33 -0
- package/node_modules/saxes/node_modules/xmlchars/package.json +51 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.0/ed4.d.ts +31 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.0/ed4.js +44 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.0/ed4.js.map +1 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.0/ed5.d.ts +51 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.0/ed5.js +105 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.0/ed5.js.map +1 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.1/ed2.d.ts +73 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.1/ed2.js +145 -0
- package/node_modules/saxes/node_modules/xmlchars/xml/1.1/ed2.js.map +1 -0
- package/node_modules/saxes/node_modules/xmlchars/xmlchars.d.ts +170 -0
- package/node_modules/saxes/node_modules/xmlchars/xmlchars.js +191 -0
- package/node_modules/saxes/node_modules/xmlchars/xmlchars.js.map +1 -0
- package/node_modules/saxes/node_modules/xmlchars/xmlns/1.0/ed3.d.ts +28 -0
- package/node_modules/saxes/node_modules/xmlchars/xmlns/1.0/ed3.js +65 -0
- package/node_modules/saxes/node_modules/xmlchars/xmlns/1.0/ed3.js.map +1 -0
- package/node_modules/saxes/package.json +71 -0
- package/node_modules/saxes/saxes.d.ts +635 -0
- package/node_modules/saxes/saxes.js +2053 -0
- package/node_modules/saxes/saxes.js.map +1 -0
- package/node_modules/zod/package.json +1 -1
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/zod/v4/core/versions.js +1 -1
- package/openclaw.plugin.json +23 -1
- package/package.json +8 -6
- package/dist/.setup/api-BmNQoi-o.mjs +0 -2
- package/dist/.setup/secret-contract-Bvm0PmP3.mjs +0 -15
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hasConfiguredNextcloudTalkChannelState, listNextcloudTalkAccountIds, mergeNextcloudTalkAccountConfig } from "../configured-state.js";
|
|
2
|
-
|
|
2
|
+
// \0rolldown/runtime.js
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -24,8 +24,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
24
24
|
return to;
|
|
25
25
|
};
|
|
26
26
|
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
27
|
-
|
|
28
|
-
//#region packages/normalization-core/src/record-coerce.ts
|
|
27
|
+
// packages/normalization-core/src/record-coerce.ts
|
|
29
28
|
/** Type guard for non-array object records at browser-safe boundaries. */
|
|
30
29
|
function isRecord(value) {
|
|
31
30
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -34,8 +33,7 @@ function isRecord(value) {
|
|
|
34
33
|
function asNullableRecord(value) {
|
|
35
34
|
return isRecord(value) ? value : null;
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
//#region src/config/channel-config-normalization.ts
|
|
36
|
+
// src/config/channel-config-normalization.ts
|
|
39
37
|
/** Applies one channel-specific doctor migration to every object-shaped account. */
|
|
40
38
|
function normalizeChannelAccounts(params) {
|
|
41
39
|
const rawAccounts = asNullableRecord(params.entry.accounts);
|
|
@@ -111,8 +109,7 @@ function normalizeChannelConfigEntries(params) {
|
|
|
111
109
|
changes
|
|
112
110
|
};
|
|
113
111
|
}
|
|
114
|
-
|
|
115
|
-
//#region src/plugin-sdk/legacy-webhook-listener-migration.ts
|
|
112
|
+
// src/plugin-sdk/legacy-webhook-listener-migration.ts
|
|
116
113
|
/** Preserve explicitly configured webhook listeners while moving ingress onto Gateway routes. */
|
|
117
114
|
function createLegacyWebhookListenerDoctorContract(params) {
|
|
118
115
|
const portKey = params.portKey ?? "webhookPort";
|
|
@@ -182,13 +179,11 @@ function createLegacyWebhookListenerDoctorContract(params) {
|
|
|
182
179
|
}
|
|
183
180
|
};
|
|
184
181
|
}
|
|
185
|
-
|
|
186
|
-
//#region \0openclaw:bundled-sdk:openclaw/plugin-sdk/runtime-doctor-migrations
|
|
182
|
+
// \0openclaw:bundled-sdk:openclaw/plugin-sdk/runtime-doctor-migrations
|
|
187
183
|
var runtime_doctor_migrations_exports = /* @__PURE__ */ __exportAll({ createLegacyWebhookListenerDoctorContract: () => createLegacyWebhookListenerDoctorContract });
|
|
188
184
|
import * as import_openclaw_plugin_sdk_runtime_doctor_migrations from "openclaw/plugin-sdk/runtime-doctor-migrations";
|
|
189
185
|
__reExport(runtime_doctor_migrations_exports, import_openclaw_plugin_sdk_runtime_doctor_migrations);
|
|
190
|
-
|
|
191
|
-
//#region extensions/nextcloud-talk/src/doctor-contract.ts
|
|
186
|
+
// extensions/nextcloud-talk/src/doctor-contract.ts
|
|
192
187
|
const webhookContract = createLegacyWebhookListenerDoctorContract({
|
|
193
188
|
channelKey: "nextcloud-talk",
|
|
194
189
|
defaultHost: "0.0.0.0",
|
|
@@ -220,5 +215,4 @@ function normalizeCompatibilityConfig({ cfg }) {
|
|
|
220
215
|
historicalWebhookAccountIds: webhook.historicalWebhookAccountIds
|
|
221
216
|
};
|
|
222
217
|
}
|
|
223
|
-
//#endregion
|
|
224
218
|
export { __exportAll as a, normalizeHistoricalWebhookConfig as i, legacyConfigRules as n, __reExport as o, normalizeCompatibilityConfig as r, historicalWebhookListener as t };
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { a as resolveNextcloudTalkAccount, i as releaseNextcloudTalkGuardedResponse, n as stripNextcloudTalkTargetPrefix, o as resolveNextcloudTalkApiCredentialsResult, r as parseWebDavFileId } from "./channel-BA1-OoqO.mjs";
|
|
2
|
+
import { l as getOptionalNextcloudTalkRuntime, r as fetchWithSsrFGuard } from "./runtime-api-CGy_KpdV.mjs";
|
|
3
|
+
import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/account-helpers";
|
|
4
|
+
import { createMessageReceiptFromOutboundResults, isRecentOutboundMessageIdentity, recordOutboundMessageIdentity } from "openclaw/plugin-sdk/channel-outbound";
|
|
5
|
+
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
+
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
|
|
7
|
+
import { readProviderJsonResponse, readProviderTextResponse } from "openclaw/plugin-sdk/provider-http";
|
|
8
|
+
import { ssrfPolicyFromPrivateNetworkOptIn } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { sanitizeUntrustedFileName } from "openclaw/plugin-sdk/security-runtime";
|
|
11
|
+
import { truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
12
|
+
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
13
|
+
import { createHmac, randomUUID } from "node:crypto";
|
|
14
|
+
import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
|
15
|
+
// extensions/nextcloud-talk/src/outbound-media.ts
|
|
16
|
+
const OUTBOUND_FILE_PREFIX = /^openclaw-([0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12})-/u;
|
|
17
|
+
const FILE_ID_REQUEST = "<d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\"><d:prop><oc:fileid/></d:prop></d:propfind>";
|
|
18
|
+
function createFileClient(account) {
|
|
19
|
+
const credentials = resolveNextcloudTalkApiCredentialsResult(account.config);
|
|
20
|
+
if (credentials.status !== "available") throw new Error("Nextcloud Talk attachments require available apiUser and apiPassword/apiPasswordFile credentials.");
|
|
21
|
+
const base = new URL(account.baseUrl);
|
|
22
|
+
if (!/^https?:$/u.test(base.protocol) || base.username || base.password || base.search || base.hash) throw new Error("Nextcloud Talk attachment baseUrl must be an HTTP(S) URL without credentials, query, or fragment.");
|
|
23
|
+
const authorization = `Basic ${Buffer.from(`${credentials.value.apiUser}:${credentials.value.apiPassword}`).toString("base64")}`;
|
|
24
|
+
const url = (pathname) => `${base.origin}${base.pathname.replace(/\/+$/u, "")}${pathname}`;
|
|
25
|
+
async function request(pathname, init, read, options = {}) {
|
|
26
|
+
options.signal?.throwIfAborted();
|
|
27
|
+
const headers = new Headers(init.headers);
|
|
28
|
+
headers.set("Authorization", authorization);
|
|
29
|
+
headers.set("OCS-APIRequest", "true");
|
|
30
|
+
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
31
|
+
const guarded = await fetchWithSsrFGuard({
|
|
32
|
+
url: url(pathname),
|
|
33
|
+
init: {
|
|
34
|
+
...init,
|
|
35
|
+
headers
|
|
36
|
+
},
|
|
37
|
+
maxRedirects: 0,
|
|
38
|
+
requireHttps: base.protocol === "https:",
|
|
39
|
+
policy: {
|
|
40
|
+
...ssrfPolicyFromPrivateNetworkOptIn(account.config.network?.dangerouslyAllowPrivateNetwork),
|
|
41
|
+
hostnameAllowlist: [base.hostname]
|
|
42
|
+
},
|
|
43
|
+
timeoutMs: 12e4,
|
|
44
|
+
signal: options.signal,
|
|
45
|
+
beforeRequest: options.beforeRequest,
|
|
46
|
+
auditContext: "nextcloud-talk-outbound-file"
|
|
47
|
+
});
|
|
48
|
+
try {
|
|
49
|
+
return await read(guarded.response);
|
|
50
|
+
} finally {
|
|
51
|
+
await releaseNextcloudTalkGuardedResponse(guarded);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function json(pathname, init, options) {
|
|
55
|
+
return await request(pathname, init, async (response) => {
|
|
56
|
+
if (!response.ok) throw new Error(`Nextcloud Talk attachment API failed (${response.status}).`);
|
|
57
|
+
const payload = await readProviderJsonResponse(response, "Nextcloud Talk attachment API");
|
|
58
|
+
if (!isRecord(payload) || !isRecord(payload.ocs)) throw new Error("Nextcloud Talk attachment API returned an invalid response.");
|
|
59
|
+
return payload.ocs.data;
|
|
60
|
+
}, options);
|
|
61
|
+
}
|
|
62
|
+
async function user(options) {
|
|
63
|
+
const data = await json("/ocs/v1.php/cloud/user?format=json", {}, options);
|
|
64
|
+
if (!isRecord(data) || typeof data.id !== "string" || !data.id || data.id === "." || data.id === ".." || data.id.includes("/") || data.id.includes("\\") || Array.from(data.id).some((character) => {
|
|
65
|
+
const code = character.charCodeAt(0);
|
|
66
|
+
return code <= 31 || code === 127;
|
|
67
|
+
})) throw new Error("Nextcloud Talk API account has no valid canonical user ID.");
|
|
68
|
+
return data.id;
|
|
69
|
+
}
|
|
70
|
+
async function history(roomToken, messageId, options) {
|
|
71
|
+
const query = new URLSearchParams({
|
|
72
|
+
lookIntoFuture: "0",
|
|
73
|
+
limit: messageId ? "1" : "200",
|
|
74
|
+
setReadMarker: "0",
|
|
75
|
+
noStatusUpdate: "1",
|
|
76
|
+
markNotificationsAsRead: "0"
|
|
77
|
+
});
|
|
78
|
+
if (messageId) {
|
|
79
|
+
query.set("lastKnownMessageId", messageId);
|
|
80
|
+
query.set("includeLastKnown", "1");
|
|
81
|
+
}
|
|
82
|
+
const data = await json(`/ocs/v2.php/apps/spreed/api/v1/chat/${encodeURIComponent(roomToken)}?${query}`, {}, options);
|
|
83
|
+
return Array.isArray(data) ? data : [];
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
request,
|
|
87
|
+
json,
|
|
88
|
+
user,
|
|
89
|
+
history
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function fileReference(account, roomToken, uid, fileId) {
|
|
93
|
+
return createHmac("sha256", account.secret).update(JSON.stringify([
|
|
94
|
+
"nextcloud-talk-outbound-file",
|
|
95
|
+
account.accountId,
|
|
96
|
+
roomToken,
|
|
97
|
+
uid,
|
|
98
|
+
fileId
|
|
99
|
+
])).digest("hex");
|
|
100
|
+
}
|
|
101
|
+
function echoIdentity(accountId, roomToken, actor, fileId) {
|
|
102
|
+
return {
|
|
103
|
+
channel: "nextcloud-talk",
|
|
104
|
+
accountId,
|
|
105
|
+
conversationId: roomToken,
|
|
106
|
+
sourceId: `file:${actor.toLowerCase()}:${fileId}`
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** The bounded cache handles webhook-before-ack; exact history handles restart/backlog. */
|
|
110
|
+
async function isNextcloudTalkOutboundFileEcho(params) {
|
|
111
|
+
params.signal?.throwIfAborted();
|
|
112
|
+
const { account, message } = params;
|
|
113
|
+
const file = message.attachment;
|
|
114
|
+
if (!file?.fileId) return false;
|
|
115
|
+
if (isRecentOutboundMessageIdentity(echoIdentity(account.accountId, message.roomToken, message.senderId, file.fileId))) return true;
|
|
116
|
+
if (!OUTBOUND_FILE_PREFIX.test(file.name)) return false;
|
|
117
|
+
if (!account.secret || resolveNextcloudTalkApiCredentialsResult(account.config).status !== "available") return false;
|
|
118
|
+
try {
|
|
119
|
+
const client = createFileClient(account);
|
|
120
|
+
const uid = await client.user({ signal: params.signal });
|
|
121
|
+
if (message.senderId !== `users/${uid}`) return false;
|
|
122
|
+
const referenceId = fileReference(account, message.roomToken, uid, file.fileId);
|
|
123
|
+
const history = await client.history(message.roomToken, message.messageId, { signal: params.signal });
|
|
124
|
+
params.signal?.throwIfAborted();
|
|
125
|
+
return history.some((entry) => isRecord(entry) && String(entry.id) === message.messageId && entry.token === message.roomToken && entry.actorType === "users" && entry.actorId === uid && entry.referenceId === referenceId && isRecord(entry.messageParameters) && isRecord(entry.messageParameters.file) && String(entry.messageParameters.file.id) === file.fileId);
|
|
126
|
+
} catch {
|
|
127
|
+
params.signal?.throwIfAborted();
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function sendMediaNextcloudTalk(ctx) {
|
|
132
|
+
const account = resolveNextcloudTalkAccount({
|
|
133
|
+
cfg: ctx.cfg,
|
|
134
|
+
accountId: ctx.accountId
|
|
135
|
+
});
|
|
136
|
+
if (!account.enabled || !account.baseUrl || !account.secret) throw new Error("Nextcloud Talk account is disabled or not configured.");
|
|
137
|
+
const roomToken = stripNextcloudTalkTargetPrefix(ctx.to);
|
|
138
|
+
if (!roomToken) throw new Error("Room token is required for Nextcloud Talk attachments.");
|
|
139
|
+
if (ctx.replyToId && !/^[1-9]\d*$/u.test(ctx.replyToId)) throw new Error("Nextcloud Talk attachment replyTo must be a positive message ID.");
|
|
140
|
+
const client = createFileClient(account);
|
|
141
|
+
const assertCurrent = () => {
|
|
142
|
+
ctx.signal?.throwIfAborted();
|
|
143
|
+
ctx.assertDirectAdapterHandoff?.();
|
|
144
|
+
};
|
|
145
|
+
const options = {
|
|
146
|
+
signal: ctx.signal,
|
|
147
|
+
beforeRequest: assertCurrent
|
|
148
|
+
};
|
|
149
|
+
assertCurrent();
|
|
150
|
+
if (ctx.silent) {
|
|
151
|
+
const data = await client.json("/ocs/v2.php/cloud/capabilities?format=json", {}, options);
|
|
152
|
+
assertCurrent();
|
|
153
|
+
const spreed = isRecord(data) && isRecord(data.capabilities) ? data.capabilities.spreed : void 0;
|
|
154
|
+
if (!isRecord(spreed) || !Array.isArray(spreed.features) || !spreed.features.includes("media-caption")) throw new Error("Nextcloud Talk silent attachments require the server's media-caption capability. Upgrade Talk before retrying.");
|
|
155
|
+
}
|
|
156
|
+
const maxBytes = resolveChannelMediaMaxBytes({
|
|
157
|
+
cfg: ctx.cfg,
|
|
158
|
+
accountId: account.accountId,
|
|
159
|
+
resolveChannelLimitMb: () => account.config.mediaMaxMb
|
|
160
|
+
}) ?? 20971520;
|
|
161
|
+
const media = await loadOutboundMediaFromUrl(ctx.mediaUrl, {
|
|
162
|
+
maxBytes,
|
|
163
|
+
mediaAccess: ctx.mediaAccess,
|
|
164
|
+
mediaLocalRoots: ctx.mediaLocalRoots,
|
|
165
|
+
mediaReadFile: ctx.mediaReadFile,
|
|
166
|
+
optimizeImages: false
|
|
167
|
+
});
|
|
168
|
+
assertCurrent();
|
|
169
|
+
const asVoice = ctx.audioAsVoice === true && (media.contentType === "audio/mpeg" || media.contentType === "audio/wav");
|
|
170
|
+
const uid = await client.user(options);
|
|
171
|
+
const uploadId = randomUUID();
|
|
172
|
+
const prefix = `openclaw-${uploadId}-`;
|
|
173
|
+
const filename = sanitizeUntrustedFileName(media.fileName ?? "attachment.bin", "attachment.bin");
|
|
174
|
+
const nameBudget = 250 - Buffer.byteLength(prefix);
|
|
175
|
+
const extension = truncateUtf8Prefix(path.extname(filename), nameBudget - 4);
|
|
176
|
+
const stem = truncateUtf8Prefix(filename.slice(0, filename.length - path.extname(filename).length), nameBudget - Buffer.byteLength(extension));
|
|
177
|
+
const uploadFolderPath = `/OpenClaw/openclaw-${uploadId}`;
|
|
178
|
+
const filePath = `${uploadFolderPath}/${prefix}${stem}${extension}`;
|
|
179
|
+
const davRoot = `/remote.php/dav/files/${encodeURIComponent(uid)}`;
|
|
180
|
+
const uploadFolder = `${davRoot}${uploadFolderPath}`;
|
|
181
|
+
const davPath = `${davRoot}${filePath.split("/").map(encodeURIComponent).join("/")}`;
|
|
182
|
+
let uploadFolderOwned = false;
|
|
183
|
+
let publicationAttempted = false;
|
|
184
|
+
try {
|
|
185
|
+
await client.request(`${davRoot}/OpenClaw`, { method: "MKCOL" }, async (response) => {
|
|
186
|
+
if (response.status !== 201 && response.status !== 405) throw new Error(`Nextcloud Talk attachment folder creation failed (${response.status}).`);
|
|
187
|
+
}, options);
|
|
188
|
+
await client.request(uploadFolder, { method: "MKCOL" }, async (response) => {
|
|
189
|
+
if (response.status !== 201) throw new Error(`Nextcloud Talk private upload folder creation failed (${response.status}).`);
|
|
190
|
+
uploadFolderOwned = true;
|
|
191
|
+
}, options);
|
|
192
|
+
await client.request(davPath, {
|
|
193
|
+
method: "PUT",
|
|
194
|
+
headers: {
|
|
195
|
+
"If-None-Match": "*",
|
|
196
|
+
"Content-Type": media.contentType ?? "application/octet-stream"
|
|
197
|
+
},
|
|
198
|
+
body: new Uint8Array(media.buffer)
|
|
199
|
+
}, async (response) => {
|
|
200
|
+
if (response.status !== 201) {
|
|
201
|
+
if (response.status === 412) uploadFolderOwned = false;
|
|
202
|
+
const recovery = response.status === 401 ? "Check apiUser and update its app password (apiPassword/apiPasswordFile) before retrying." : response.status === 507 ? "Free Files storage or increase the API user's quota before retrying." : "Check Nextcloud server logs and the API user's Files write access.";
|
|
203
|
+
throw new Error(`Nextcloud Talk attachment upload failed (${response.status}). ${recovery}`);
|
|
204
|
+
}
|
|
205
|
+
}, options);
|
|
206
|
+
const fileId = await client.request(davPath, {
|
|
207
|
+
method: "PROPFIND",
|
|
208
|
+
headers: {
|
|
209
|
+
Depth: "0",
|
|
210
|
+
"Content-Type": "application/xml"
|
|
211
|
+
},
|
|
212
|
+
body: FILE_ID_REQUEST
|
|
213
|
+
}, async (response) => {
|
|
214
|
+
if (response.status !== 207) throw new Error("Nextcloud Talk uploaded file identity unavailable.");
|
|
215
|
+
const id = parseWebDavFileId(await readProviderTextResponse(response, "Nextcloud Talk uploaded file identity", { maxBytes: 65536 }));
|
|
216
|
+
if (!id) throw new Error("Nextcloud Talk uploaded file identity invalid.");
|
|
217
|
+
return id;
|
|
218
|
+
}, options);
|
|
219
|
+
const referenceId = fileReference(account, roomToken, uid, fileId);
|
|
220
|
+
const caption = convertMarkdownTables(ctx.text.trim(), resolveMarkdownTableMode({
|
|
221
|
+
cfg: ctx.cfg,
|
|
222
|
+
channel: "nextcloud-talk",
|
|
223
|
+
accountId: account.accountId
|
|
224
|
+
}));
|
|
225
|
+
const body = new URLSearchParams({
|
|
226
|
+
path: filePath,
|
|
227
|
+
shareType: "10",
|
|
228
|
+
shareWith: roomToken,
|
|
229
|
+
permissions: "1",
|
|
230
|
+
referenceId,
|
|
231
|
+
talkMetaData: JSON.stringify({
|
|
232
|
+
caption,
|
|
233
|
+
...asVoice ? { messageType: "voice-message" } : {},
|
|
234
|
+
...ctx.silent ? { silent: true } : {},
|
|
235
|
+
...ctx.replyToId ? { replyTo: Number(ctx.replyToId) } : {}
|
|
236
|
+
})
|
|
237
|
+
});
|
|
238
|
+
await ctx.onPlatformSendDispatch?.();
|
|
239
|
+
assertCurrent();
|
|
240
|
+
recordOutboundMessageIdentity(echoIdentity(account.accountId, roomToken, `users/${uid}`, fileId));
|
|
241
|
+
let publicationError;
|
|
242
|
+
try {
|
|
243
|
+
await client.json("/ocs/v2.php/apps/files_sharing/api/v1/shares?format=json", {
|
|
244
|
+
method: "POST",
|
|
245
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
246
|
+
body
|
|
247
|
+
}, {
|
|
248
|
+
...options,
|
|
249
|
+
beforeRequest: () => {
|
|
250
|
+
assertCurrent();
|
|
251
|
+
publicationAttempted = true;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
} catch (error) {
|
|
255
|
+
if (!publicationAttempted) throw error;
|
|
256
|
+
publicationError = error;
|
|
257
|
+
}
|
|
258
|
+
let history;
|
|
259
|
+
try {
|
|
260
|
+
history = await client.history(roomToken);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
throw new Error("Nextcloud Talk attachment delivery not confirmed; uploaded file retained. Do not blindly retry.", { cause: error });
|
|
263
|
+
}
|
|
264
|
+
const message = history.find((entry) => isRecord(entry) && entry.token === roomToken && entry.actorType === "users" && entry.actorId === uid && entry.referenceId === referenceId && /^[1-9]\d*$/u.test(String(entry.id)) && isRecord(entry.messageParameters) && isRecord(entry.messageParameters.file) && String(entry.messageParameters.file.id) === fileId);
|
|
265
|
+
if (!isRecord(message)) throw new Error("Nextcloud Talk attachment delivery not confirmed; uploaded file retained. Do not blindly retry.", { cause: publicationError });
|
|
266
|
+
const messageId = String(message.id);
|
|
267
|
+
const replyToId = isRecord(message.parent) && String(message.parent.id) === ctx.replyToId ? ctx.replyToId : void 0;
|
|
268
|
+
recordOutboundMessageIdentity({
|
|
269
|
+
channel: "nextcloud-talk",
|
|
270
|
+
accountId: account.accountId,
|
|
271
|
+
conversationId: roomToken,
|
|
272
|
+
messageId
|
|
273
|
+
});
|
|
274
|
+
getOptionalNextcloudTalkRuntime()?.channel.activity.record({
|
|
275
|
+
channel: "nextcloud-talk",
|
|
276
|
+
accountId: account.accountId,
|
|
277
|
+
direction: "outbound"
|
|
278
|
+
});
|
|
279
|
+
return {
|
|
280
|
+
messageId,
|
|
281
|
+
roomToken,
|
|
282
|
+
receipt: createMessageReceiptFromOutboundResults({
|
|
283
|
+
results: [{
|
|
284
|
+
channel: "nextcloud-talk",
|
|
285
|
+
conversationId: roomToken,
|
|
286
|
+
messageId
|
|
287
|
+
}],
|
|
288
|
+
kind: asVoice && message.messageType === "voice-message" ? "voice" : "media",
|
|
289
|
+
...replyToId ? { replyToId } : {}
|
|
290
|
+
})
|
|
291
|
+
};
|
|
292
|
+
} catch (error) {
|
|
293
|
+
if (uploadFolderOwned && !publicationAttempted) try {
|
|
294
|
+
await client.request(uploadFolder, { method: "DELETE" }, async (response) => {
|
|
295
|
+
if (!response.ok && response.status !== 404) throw new Error("cleanup rejected", { cause: error });
|
|
296
|
+
});
|
|
297
|
+
} catch {
|
|
298
|
+
throw new Error("Nextcloud Talk attachment failed before sharing; unshared upload cleanup also failed.", { cause: error });
|
|
299
|
+
}
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
export { isNextcloudTalkOutboundFileEcho, sendMediaNextcloudTalk };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { buildOutboundSessionContext, deliverInboundReplyWithMessageSendContext, sendDurableMessageBatch } from "openclaw/plugin-sdk/channel-outbound";
|
|
2
|
+
import { createAcceptedChannelDeliveryResult, createChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
|
|
3
|
+
// extensions/nextcloud-talk/src/reply.ts
|
|
4
|
+
/** Keep final runtime handoff and all payload planning with the shared owners. */
|
|
5
|
+
async function deliverNextcloudTalkReply(params) {
|
|
6
|
+
const { cfg, accountId, agentId, ctxPayload, payload, info, to } = params;
|
|
7
|
+
const final = await deliverInboundReplyWithMessageSendContext({
|
|
8
|
+
cfg,
|
|
9
|
+
channel: "nextcloud-talk",
|
|
10
|
+
accountId,
|
|
11
|
+
agentId,
|
|
12
|
+
ctxPayload,
|
|
13
|
+
payload,
|
|
14
|
+
info,
|
|
15
|
+
to
|
|
16
|
+
});
|
|
17
|
+
if (final.status === "handled_visible" || final.status === "handled_no_send") return final.delivery;
|
|
18
|
+
if (final.status === "failed") throw final.error;
|
|
19
|
+
const send = await sendDurableMessageBatch({
|
|
20
|
+
cfg,
|
|
21
|
+
channel: "nextcloud-talk",
|
|
22
|
+
accountId,
|
|
23
|
+
to,
|
|
24
|
+
payloads: [payload],
|
|
25
|
+
replyToId: payload.replyToId,
|
|
26
|
+
session: buildOutboundSessionContext({
|
|
27
|
+
cfg,
|
|
28
|
+
agentId,
|
|
29
|
+
sessionKey: ctxPayload.SessionKey,
|
|
30
|
+
policySessionKey: ctxPayload.RuntimePolicySessionKey,
|
|
31
|
+
conversationType: ctxPayload.ChatType,
|
|
32
|
+
requesterAccountId: accountId ?? ctxPayload.AccountId,
|
|
33
|
+
requesterSenderId: ctxPayload.SenderId ?? ctxPayload.From,
|
|
34
|
+
requesterSenderName: ctxPayload.SenderName,
|
|
35
|
+
requesterSenderUsername: ctxPayload.SenderUsername,
|
|
36
|
+
requesterSenderE164: ctxPayload.SenderE164
|
|
37
|
+
}),
|
|
38
|
+
gatewayClientScopes: ctxPayload.GatewayClientScopes ?? [],
|
|
39
|
+
signal: params.signal,
|
|
40
|
+
onPlatformSendDispatch: info.onPlatformSendDispatch,
|
|
41
|
+
assertDirectAdapterHandoff: info.assertPlatformSendAuthorized,
|
|
42
|
+
skipQueue: true,
|
|
43
|
+
durability: "best_effort"
|
|
44
|
+
});
|
|
45
|
+
if (send.status === "failed") throw send.error;
|
|
46
|
+
const deliveryIntent = send.deliveryIntent ? {
|
|
47
|
+
id: send.deliveryIntent.id,
|
|
48
|
+
kind: "outbound_queue",
|
|
49
|
+
queuePolicy: send.deliveryIntent.queuePolicy
|
|
50
|
+
} : void 0;
|
|
51
|
+
if (send.status === "suppressed") return {
|
|
52
|
+
visibleReplySent: false,
|
|
53
|
+
receipt: send.receipt,
|
|
54
|
+
suppression: { reason: send.reason },
|
|
55
|
+
...deliveryIntent ? { deliveryIntent } : {}
|
|
56
|
+
};
|
|
57
|
+
const result = {
|
|
58
|
+
...createAcceptedChannelDeliveryResult({ results: [{ receipt: send.receipt }] }),
|
|
59
|
+
...deliveryIntent ? { deliveryIntent } : {}
|
|
60
|
+
};
|
|
61
|
+
if (send.status === "partial_failed") throw createChannelPartialDeliveryError(send.error, result);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
export { deliverNextcloudTalkReply };
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
|
2
2
|
import { logInboundDrop } from "openclaw/plugin-sdk/channel-inbound";
|
|
3
3
|
import { GROUP_POLICY_BLOCKED_LABEL, resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
4
|
-
import { deliverFormattedTextWithAttachments } from "openclaw/plugin-sdk/reply-payload";
|
|
5
4
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
6
5
|
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
7
|
-
|
|
6
|
+
// extensions/nextcloud-talk/src/runtime.ts
|
|
8
7
|
const { setRuntime: setNextcloudTalkRuntime, getRuntime: getNextcloudTalkRuntime, tryGetRuntime: getOptionalNextcloudTalkRuntime } = createPluginRuntimeStore({
|
|
9
8
|
pluginId: "nextcloud-talk",
|
|
10
9
|
errorMessage: "Nextcloud Talk runtime not initialized"
|
|
11
10
|
});
|
|
12
|
-
|
|
13
|
-
export { logInboundDrop as a, warnMissingProviderGroupPolicyFallbackOnce as c, setNextcloudTalkRuntime as d, fetchWithSsrFGuard as i, getNextcloudTalkRuntime as l, createChannelPairingController as n, resolveAllowlistProviderRuntimeGroupPolicy as o, deliverFormattedTextWithAttachments as r, resolveDefaultGroupPolicy as s, GROUP_POLICY_BLOCKED_LABEL as t, getOptionalNextcloudTalkRuntime as u };
|
|
11
|
+
export { resolveAllowlistProviderRuntimeGroupPolicy as a, getNextcloudTalkRuntime as c, logInboundDrop as i, getOptionalNextcloudTalkRuntime as l, createChannelPairingController as n, resolveDefaultGroupPolicy as o, fetchWithSsrFGuard as r, warnMissingProviderGroupPolicyFallbackOnce as s, GROUP_POLICY_BLOCKED_LABEL as t, setNextcloudTalkRuntime as u };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { t as channelSecrets, n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
1
|
+
export { t as channelSecrets, n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-yjCLewtg.mjs";
|
|
2
2
|
import "../secret-contract-api.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { hasConfiguredNextcloudAccount } from "../configured-state.js";
|
|
2
|
+
import { collectSimpleChannelFieldAssignments, createChannelSecretContract } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
3
|
+
// extensions/nextcloud-talk/src/secret-contract.ts
|
|
4
|
+
const channelSecrets = createChannelSecretContract({
|
|
5
|
+
channelKey: "nextcloud-talk",
|
|
6
|
+
account: ["apiPassword", "botSecret"],
|
|
7
|
+
channel: ["apiPassword", "botSecret"],
|
|
8
|
+
hasImplicitDefaultAccount: ({ context }) => hasConfiguredNextcloudAccount(context.sourceConfig.channels?.["nextcloud-talk"], context.env),
|
|
9
|
+
collect(params) {
|
|
10
|
+
for (const field of ["botSecret", "apiPassword"]) collectSimpleChannelFieldAssignments({
|
|
11
|
+
...params,
|
|
12
|
+
field,
|
|
13
|
+
topInactiveReason: `no enabled Nextcloud Talk surface inherits this top-level ${field}.`,
|
|
14
|
+
accountInactiveReason: "Nextcloud Talk account is disabled."
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const { secretTargetRegistryEntries, collectRuntimeConfigAssignments } = channelSecrets;
|
|
19
|
+
export { collectRuntimeConfigAssignments as n, secretTargetRegistryEntries as r, channelSecrets as t };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"entries":[{"output":"api.js","source":"extensions/nextcloud-talk/api.ts"},{"output":"channel-plugin-api.js","source":"extensions/nextcloud-talk/channel-plugin-api.ts"},{"output":"configured-state.js","source":"extensions/nextcloud-talk/configured-state.ts"},{"output":"doctor-contract-api.js","source":"extensions/nextcloud-talk/doctor-contract-api.ts"},{"output":"index.js","source":"extensions/nextcloud-talk/index.ts"},{"output":"runtime-api.js","source":"extensions/nextcloud-talk/runtime-api.ts"},{"output":"secret-contract-api.js","source":"extensions/nextcloud-talk/secret-contract-api.ts"},{"output":"setup-entry.js","source":"extensions/nextcloud-talk/setup-entry.ts"}],"chunks":[{"output":".setup/api-
|
|
1
|
+
{"version":3,"entries":[{"output":"api.js","source":"extensions/nextcloud-talk/api.ts"},{"output":"channel-plugin-api.js","source":"extensions/nextcloud-talk/channel-plugin-api.ts"},{"output":"configured-state.js","source":"extensions/nextcloud-talk/configured-state.ts"},{"output":"doctor-contract-api.js","source":"extensions/nextcloud-talk/doctor-contract-api.ts"},{"output":"index.js","source":"extensions/nextcloud-talk/index.ts"},{"output":"runtime-api.js","source":"extensions/nextcloud-talk/runtime-api.ts"},{"output":"secret-contract-api.js","source":"extensions/nextcloud-talk/secret-contract-api.ts"},{"output":"setup-entry.js","source":"extensions/nextcloud-talk/setup-entry.ts"}],"chunks":[{"output":".setup/api-BvrRSilb.mjs","sha256":"b25f39344c117b809520b3961b58f661adee93617654525cf980397c3567f61c","facadeSource":"extensions/nextcloud-talk/api.ts","sources":[]},{"output":".setup/channel-BA1-OoqO.mjs","sha256":"7332d213f8ca1e37bfa7a913f295bbef288630ddb9739c5f4032aa558c2e4057","facadeSource":null,"sources":["extensions/nextcloud-talk/src/accounts.ts","extensions/nextcloud-talk/src/api-credentials.ts","extensions/nextcloud-talk/src/bot-preflight.ts","extensions/nextcloud-talk/src/channel.ts","extensions/nextcloud-talk/src/config-schema.ts","extensions/nextcloud-talk/src/doctor.ts","extensions/nextcloud-talk/src/guarded-response.ts","extensions/nextcloud-talk/src/inbound-media.ts","extensions/nextcloud-talk/src/inbound.ts","extensions/nextcloud-talk/src/message-actions.ts","extensions/nextcloud-talk/src/monitor.ts","extensions/nextcloud-talk/src/normalize.ts","extensions/nextcloud-talk/src/policy.ts","extensions/nextcloud-talk/src/replay-migration-contract.ts","extensions/nextcloud-talk/src/room-info.ts","extensions/nextcloud-talk/src/send.ts","extensions/nextcloud-talk/src/setup-core.ts","extensions/nextcloud-talk/src/setup-surface.ts","extensions/nextcloud-talk/src/signature.ts","extensions/nextcloud-talk/src/voice-media.ts","extensions/nextcloud-talk/src/webdav.ts","extensions/nextcloud-talk/src/webhook-route.ts","extensions/nextcloud-talk/src/webhook-spool-state.ts","extensions/nextcloud-talk/src/webhook-spool.ts","packages/normalization-core/src/string-coerce.ts","src/gateway/gateway-http-route-contracts.ts","src/gateway/security-path.ts","src/gateway/server/plugins-http/path-context.ts","src/plugins/http-path-prefix.ts"]},{"output":".setup/doctor-contract-CkWQa5uZ.mjs","sha256":"b580887eb445ab10c67ee1a057982cd3be79d68e2c3440b3f2a46f2a8852c55b","facadeSource":null,"sources":["extensions/nextcloud-talk/src/doctor-contract.ts","packages/normalization-core/src/record-coerce.ts","src/config/channel-config-normalization.ts","src/plugin-sdk/legacy-webhook-listener-migration.ts"]},{"output":".setup/outbound-media-CpFe1Xgz.mjs","sha256":"bef81da85203f92dc6478aa3f00d11112e3f8aad10191dbf0a0678c07049ab61","facadeSource":"extensions/nextcloud-talk/src/outbound-media.ts","sources":["extensions/nextcloud-talk/src/outbound-media.ts"]},{"output":".setup/reply-BEkv387l.mjs","sha256":"e2c5093c05fcdbbe57a1693ea81de165c8280573ad3706f244dbd152dcd895ca","facadeSource":"extensions/nextcloud-talk/src/reply.ts","sources":["extensions/nextcloud-talk/src/reply.ts"]},{"output":".setup/runtime-api-CGy_KpdV.mjs","sha256":"344accb3739f831215489e33d0ca4dbaa5062fad8a0c98b7e356ee2bd0bb8228","facadeSource":null,"sources":["extensions/nextcloud-talk/src/runtime.ts"]},{"output":".setup/secret-contract-api-QMihLdr1.mjs","sha256":"0a2531895db3b16212c29ea87314c04021173a1bde49b58fbfd29fed181b4f15","facadeSource":"extensions/nextcloud-talk/secret-contract-api.ts","sources":[]},{"output":".setup/secret-contract-yjCLewtg.mjs","sha256":"183e7de729d242a63a7b607f3d353a5712f19eaea4ca24525cd96cc93bb63ffc","facadeSource":null,"sources":["extensions/nextcloud-talk/src/secret-contract.ts"]},{"output":"api.js","sha256":"e6a136ec30af9d685b3b1724ac335bc48534867c9c553e6a04f47d1ae22444d8","facadeSource":"extensions/nextcloud-talk/api.ts","sources":[]},{"output":"channel-plugin-api.js","sha256":"e6a136ec30af9d685b3b1724ac335bc48534867c9c553e6a04f47d1ae22444d8","facadeSource":"extensions/nextcloud-talk/channel-plugin-api.ts","sources":[]},{"output":"configured-state.js","sha256":"a45a34efe4339d78b7fcc92b8d09f8ad60d19c4a4e3a9754104c7f658be278d0","facadeSource":"extensions/nextcloud-talk/configured-state.ts","sources":["extensions/nextcloud-talk/configured-state.ts"]},{"output":"doctor-contract-api.js","sha256":"71237fb5c510be1302851b9fb7b264dd4e0d0095be206e50ffce4b5890ace54f","facadeSource":"extensions/nextcloud-talk/doctor-contract-api.ts","sources":[]},{"output":"index.js","sha256":"16bcc875626f7dd3bc4c1195210f856deaa9c3757abe5cea2a1d90cb2877cd22","facadeSource":"extensions/nextcloud-talk/index.ts","sources":["extensions/nextcloud-talk/index.ts"]},{"output":"runtime-api.js","sha256":"9306402515a553c1fe195fc8be8d6436a41abca338ae6cd4254434422e6f4cb3","facadeSource":"extensions/nextcloud-talk/runtime-api.ts","sources":[]},{"output":"secret-contract-api.js","sha256":"34c4d2c917c364f14b73bb8f51db22a8f24d047246358f543ab3aa0abfa78202","facadeSource":"extensions/nextcloud-talk/secret-contract-api.ts","sources":[]},{"output":"setup-entry.js","sha256":"7dba8b8fb26185b57bcabe7aab548d7e956deb37c46142110413ff4cab7cf80a","facadeSource":"extensions/nextcloud-talk/setup-entry.ts","sources":["extensions/nextcloud-talk/setup-entry.ts"]}],"unrenderedSources":["extensions/nextcloud-talk/api.ts","extensions/nextcloud-talk/channel-plugin-api.ts","extensions/nextcloud-talk/config-doctor-api.ts","extensions/nextcloud-talk/doctor-contract-api.ts","extensions/nextcloud-talk/runtime-api.ts","extensions/nextcloud-talk/secret-contract-api.ts"]}
|
package/dist/api.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as nextcloudTalkPlugin } from "./.setup/channel-
|
|
1
|
+
export { t as nextcloudTalkPlugin } from "./.setup/channel-BA1-OoqO.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as nextcloudTalkPlugin } from "./.setup/channel-
|
|
1
|
+
export { t as nextcloudTalkPlugin } from "./.setup/channel-BA1-OoqO.mjs";
|
package/dist/configured-state.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, hasConfiguredAccountValue, normalizeAccountId } from "openclaw/plugin-sdk/account-core";
|
|
2
|
-
|
|
2
|
+
// extensions/nextcloud-talk/configured-state.ts
|
|
3
3
|
const { listAccountIds: listNextcloudTalkAccountIds, resolveDefaultAccountId: resolveDefaultNextcloudTalkAccountId, resolveAccountConfig: mergeNextcloudTalkAccountConfig } = createAccountListHelpers("nextcloud-talk", {
|
|
4
4
|
normalizeAccountId,
|
|
5
5
|
omitKeys: ["defaultAccount"],
|
|
6
|
-
hasImplicitDefaultAccount: (cfg) =>
|
|
7
|
-
const channel = cfg.channels?.["nextcloud-talk"];
|
|
8
|
-
return Boolean(channel?.baseUrl?.trim() && (hasConfiguredAccountValue(channel.botSecret) || channel.botSecretFile?.trim() || process.env.NEXTCLOUD_TALK_BOT_SECRET?.trim()));
|
|
9
|
-
}
|
|
6
|
+
hasImplicitDefaultAccount: (cfg) => hasConfiguredNextcloudAccount(cfg.channels?.["nextcloud-talk"], process.env)
|
|
10
7
|
});
|
|
11
8
|
function hasConfiguredNextcloudAccount(account, env) {
|
|
12
9
|
return Boolean(account?.baseUrl?.trim() && (hasConfiguredAccountValue(account.botSecret) || hasConfiguredAccountValue(account.botSecretFile) || hasConfiguredAccountValue(env.NEXTCLOUD_TALK_BOT_SECRET)));
|
|
@@ -20,5 +17,4 @@ function hasConfiguredNextcloudTalkChannelState(params) {
|
|
|
20
17
|
}
|
|
21
18
|
return Object.entries(channel?.accounts ?? {}).some(([accountId, account]) => accountId !== DEFAULT_ACCOUNT_ID && account.enabled !== false && hasConfiguredNextcloudAccount(mergeNextcloudTalkAccountConfig(params.cfg, accountId), {}));
|
|
22
19
|
}
|
|
23
|
-
|
|
24
|
-
export { hasConfiguredNextcloudTalkChannelState, listNextcloudTalkAccountIds, mergeNextcloudTalkAccountConfig, resolveDefaultNextcloudTalkAccountId };
|
|
20
|
+
export { hasConfiguredNextcloudAccount, hasConfiguredNextcloudTalkChannelState, listNextcloudTalkAccountIds, mergeNextcloudTalkAccountConfig, resolveDefaultNextcloudTalkAccountId };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as historicalWebhookListener, n as legacyConfigRules, r as normalizeCompatibilityConfig, i as normalizeHistoricalWebhookConfig } from "./.setup/doctor-contract-
|
|
1
|
+
export { t as historicalWebhookListener, n as legacyConfigRules, r as normalizeCompatibilityConfig, i as normalizeHistoricalWebhookConfig } from "./.setup/doctor-contract-CkWQa5uZ.mjs";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
|
2
|
-
|
|
2
|
+
// extensions/nextcloud-talk/index.ts
|
|
3
3
|
var nextcloud_talk_default = defineBundledChannelEntry({
|
|
4
4
|
id: "nextcloud-talk",
|
|
5
5
|
name: "Nextcloud Talk",
|
|
@@ -18,5 +18,4 @@ var nextcloud_talk_default = defineBundledChannelEntry({
|
|
|
18
18
|
exportName: "setNextcloudTalkRuntime"
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
|
-
//#endregion
|
|
22
21
|
export { nextcloud_talk_default as default };
|
package/dist/runtime-api.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as GROUP_POLICY_BLOCKED_LABEL, n as createChannelPairingController, r as
|
|
1
|
+
export { t as GROUP_POLICY_BLOCKED_LABEL, n as createChannelPairingController, r as fetchWithSsrFGuard, i as logInboundDrop, a as resolveAllowlistProviderRuntimeGroupPolicy, o as resolveDefaultGroupPolicy, u as setNextcloudTalkRuntime, s as warnMissingProviderGroupPolicyFallbackOnce } from "./.setup/runtime-api-CGy_KpdV.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as channelSecrets, n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./.setup/secret-contract-
|
|
1
|
+
export { t as channelSecrets, n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./.setup/secret-contract-yjCLewtg.mjs";
|
package/dist/setup-entry.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
|
|
3
|
+
// extensions/nextcloud-talk/setup-entry.ts
|
|
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-BvrRSilb.mjs", import.meta.url).href),
|
|
8
8
|
exportName: "nextcloudTalkPlugin"
|
|
9
9
|
},
|
|
10
10
|
secrets: {
|
|
11
|
-
specifier: fileURLToPath(new URL(".setup/secret-contract-api-
|
|
11
|
+
specifier: fileURLToPath(new URL(".setup/secret-contract-api-QMihLdr1.mjs", import.meta.url).href),
|
|
12
12
|
exportName: "channelSecrets"
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
|
-
//#endregion
|
|
16
15
|
export { setup_entry_default as default };
|