@openclaw/nextcloud-talk 2026.2.21 → 2026.2.23
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/package.json +1 -1
- package/src/channel.ts +9 -2
- package/src/config-schema.ts +2 -9
- package/src/inbound.ts +40 -38
- package/src/monitor.ts +7 -7
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
deleteAccountFromConfigSection,
|
|
6
6
|
formatPairingApproveHint,
|
|
7
7
|
normalizeAccountId,
|
|
8
|
+
resolveAllowlistProviderRuntimeGroupPolicy,
|
|
9
|
+
resolveDefaultGroupPolicy,
|
|
8
10
|
setAccountEnabledInConfigSection,
|
|
9
11
|
type ChannelPlugin,
|
|
10
12
|
type OpenClawConfig,
|
|
@@ -128,8 +130,13 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
|
|
128
130
|
};
|
|
129
131
|
},
|
|
130
132
|
collectWarnings: ({ account, cfg }) => {
|
|
131
|
-
const defaultGroupPolicy = cfg
|
|
132
|
-
const
|
|
133
|
+
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
|
|
134
|
+
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
|
|
135
|
+
providerConfigPresent:
|
|
136
|
+
(cfg.channels as Record<string, unknown> | undefined)?.["nextcloud-talk"] !== undefined,
|
|
137
|
+
groupPolicy: account.config.groupPolicy,
|
|
138
|
+
defaultGroupPolicy,
|
|
139
|
+
});
|
|
133
140
|
if (groupPolicy !== "open") {
|
|
134
141
|
return [];
|
|
135
142
|
}
|
package/src/config-schema.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
DmPolicySchema,
|
|
5
5
|
GroupPolicySchema,
|
|
6
6
|
MarkdownConfigSchema,
|
|
7
|
+
ReplyRuntimeConfigSchemaShape,
|
|
7
8
|
ToolPolicySchema,
|
|
8
9
|
requireOpenAllowFrom,
|
|
9
10
|
} from "openclaw/plugin-sdk";
|
|
@@ -40,15 +41,7 @@ export const NextcloudTalkAccountSchemaBase = z
|
|
|
40
41
|
groupAllowFrom: z.array(z.string()).optional(),
|
|
41
42
|
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
|
42
43
|
rooms: z.record(z.string(), NextcloudTalkRoomSchema.optional()).optional(),
|
|
43
|
-
|
|
44
|
-
dmHistoryLimit: z.number().int().min(0).optional(),
|
|
45
|
-
dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
|
|
46
|
-
textChunkLimit: z.number().int().positive().optional(),
|
|
47
|
-
chunkMode: z.enum(["length", "newline"]).optional(),
|
|
48
|
-
blockStreaming: z.boolean().optional(),
|
|
49
|
-
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
|
50
|
-
responsePrefix: z.string().optional(),
|
|
51
|
-
mediaMaxMb: z.number().positive().optional(),
|
|
44
|
+
...ReplyRuntimeConfigSchemaShape,
|
|
52
45
|
})
|
|
53
46
|
.strict();
|
|
54
47
|
|
package/src/inbound.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
+
GROUP_POLICY_BLOCKED_LABEL,
|
|
3
|
+
createNormalizedOutboundDeliverer,
|
|
2
4
|
createReplyPrefixOptions,
|
|
5
|
+
formatTextWithAttachmentLinks,
|
|
3
6
|
logInboundDrop,
|
|
4
7
|
resolveControlCommandGate,
|
|
8
|
+
resolveOutboundMediaUrls,
|
|
9
|
+
resolveAllowlistProviderRuntimeGroupPolicy,
|
|
10
|
+
resolveDefaultGroupPolicy,
|
|
11
|
+
warnMissingProviderGroupPolicyFallbackOnce,
|
|
12
|
+
type OutboundReplyPayload,
|
|
5
13
|
type OpenClawConfig,
|
|
6
14
|
type RuntimeEnv,
|
|
7
15
|
} from "openclaw/plugin-sdk";
|
|
@@ -22,32 +30,17 @@ import type { CoreConfig, GroupPolicy, NextcloudTalkInboundMessage } from "./typ
|
|
|
22
30
|
const CHANNEL_ID = "nextcloud-talk" as const;
|
|
23
31
|
|
|
24
32
|
async function deliverNextcloudTalkReply(params: {
|
|
25
|
-
payload:
|
|
33
|
+
payload: OutboundReplyPayload;
|
|
26
34
|
roomToken: string;
|
|
27
35
|
accountId: string;
|
|
28
36
|
statusSink?: (patch: { lastOutboundAt?: number }) => void;
|
|
29
37
|
}): Promise<void> {
|
|
30
38
|
const { payload, roomToken, accountId, statusSink } = params;
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
? payload.mediaUrls
|
|
34
|
-
: payload.mediaUrl
|
|
35
|
-
? [payload.mediaUrl]
|
|
36
|
-
: [];
|
|
37
|
-
|
|
38
|
-
if (!text.trim() && mediaList.length === 0) {
|
|
39
|
+
const combined = formatTextWithAttachmentLinks(payload.text, resolveOutboundMediaUrls(payload));
|
|
40
|
+
if (!combined) {
|
|
39
41
|
return;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
const mediaBlock = mediaList.length
|
|
43
|
-
? mediaList.map((url) => `Attachment: ${url}`).join("\n")
|
|
44
|
-
: "";
|
|
45
|
-
const combined = text.trim()
|
|
46
|
-
? mediaBlock
|
|
47
|
-
? `${text.trim()}\n\n${mediaBlock}`
|
|
48
|
-
: text.trim()
|
|
49
|
-
: mediaBlock;
|
|
50
|
-
|
|
51
44
|
await sendMessageNextcloudTalk(roomToken, combined, {
|
|
52
45
|
accountId,
|
|
53
46
|
replyTo: payload.replyToId,
|
|
@@ -84,16 +77,29 @@ export async function handleNextcloudTalkInbound(params: {
|
|
|
84
77
|
statusSink?.({ lastInboundAt: message.timestamp });
|
|
85
78
|
|
|
86
79
|
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
|
87
|
-
const defaultGroupPolicy = (config
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
80
|
+
const defaultGroupPolicy = resolveDefaultGroupPolicy(config as OpenClawConfig);
|
|
81
|
+
const { groupPolicy, providerMissingFallbackApplied } =
|
|
82
|
+
resolveAllowlistProviderRuntimeGroupPolicy({
|
|
83
|
+
providerConfigPresent:
|
|
84
|
+
((config.channels as Record<string, unknown> | undefined)?.["nextcloud-talk"] ??
|
|
85
|
+
undefined) !== undefined,
|
|
86
|
+
groupPolicy: account.config.groupPolicy as GroupPolicy | undefined,
|
|
87
|
+
defaultGroupPolicy,
|
|
88
|
+
});
|
|
89
|
+
warnMissingProviderGroupPolicyFallbackOnce({
|
|
90
|
+
providerMissingFallbackApplied,
|
|
91
|
+
providerKey: "nextcloud-talk",
|
|
92
|
+
accountId: account.accountId,
|
|
93
|
+
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.room,
|
|
94
|
+
log: (message) => runtime.log?.(message),
|
|
95
|
+
});
|
|
93
96
|
|
|
94
97
|
const configAllowFrom = normalizeNextcloudTalkAllowlist(account.config.allowFrom);
|
|
95
98
|
const configGroupAllowFrom = normalizeNextcloudTalkAllowlist(account.config.groupAllowFrom);
|
|
96
|
-
const storeAllowFrom =
|
|
99
|
+
const storeAllowFrom =
|
|
100
|
+
dmPolicy === "allowlist"
|
|
101
|
+
? []
|
|
102
|
+
: await core.channel.pairing.readAllowFromStore(CHANNEL_ID).catch(() => []);
|
|
97
103
|
const storeAllowList = normalizeNextcloudTalkAllowlist(storeAllowFrom);
|
|
98
104
|
|
|
99
105
|
const roomMatch = resolveNextcloudTalkRoomMatch({
|
|
@@ -301,25 +307,21 @@ export async function handleNextcloudTalkInbound(params: {
|
|
|
301
307
|
channel: CHANNEL_ID,
|
|
302
308
|
accountId: account.accountId,
|
|
303
309
|
});
|
|
310
|
+
const deliverReply = createNormalizedOutboundDeliverer(async (payload) => {
|
|
311
|
+
await deliverNextcloudTalkReply({
|
|
312
|
+
payload,
|
|
313
|
+
roomToken,
|
|
314
|
+
accountId: account.accountId,
|
|
315
|
+
statusSink,
|
|
316
|
+
});
|
|
317
|
+
});
|
|
304
318
|
|
|
305
319
|
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
306
320
|
ctx: ctxPayload,
|
|
307
321
|
cfg: config as OpenClawConfig,
|
|
308
322
|
dispatcherOptions: {
|
|
309
323
|
...prefixOptions,
|
|
310
|
-
deliver:
|
|
311
|
-
await deliverNextcloudTalkReply({
|
|
312
|
-
payload: payload as {
|
|
313
|
-
text?: string;
|
|
314
|
-
mediaUrls?: string[];
|
|
315
|
-
mediaUrl?: string;
|
|
316
|
-
replyToId?: string;
|
|
317
|
-
},
|
|
318
|
-
roomToken,
|
|
319
|
-
accountId: account.accountId,
|
|
320
|
-
statusSink,
|
|
321
|
-
});
|
|
322
|
-
},
|
|
324
|
+
deliver: deliverReply,
|
|
323
325
|
onError: (err, info) => {
|
|
324
326
|
runtime.error?.(`nextcloud-talk ${info.kind} reply failed: ${String(err)}`);
|
|
325
327
|
},
|
package/src/monitor.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createServer, type IncomingMessage, type Server, type ServerResponse } from "node:http";
|
|
2
2
|
import {
|
|
3
|
+
createLoggerBackedRuntime,
|
|
3
4
|
type RuntimeEnv,
|
|
4
5
|
isRequestBodyLimitError,
|
|
5
6
|
readRequestBodyWithLimit,
|
|
@@ -212,13 +213,12 @@ export async function monitorNextcloudTalkProvider(
|
|
|
212
213
|
cfg,
|
|
213
214
|
accountId: opts.accountId,
|
|
214
215
|
});
|
|
215
|
-
const runtime: RuntimeEnv =
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
};
|
|
216
|
+
const runtime: RuntimeEnv =
|
|
217
|
+
opts.runtime ??
|
|
218
|
+
createLoggerBackedRuntime({
|
|
219
|
+
logger: core.logging.getChildLogger(),
|
|
220
|
+
exitError: () => new Error("Runtime exit not available"),
|
|
221
|
+
});
|
|
222
222
|
|
|
223
223
|
if (!account.secret) {
|
|
224
224
|
throw new Error(`Nextcloud Talk bot secret not configured for account "${account.accountId}"`);
|