feat(channels): add Nextcloud Talk config compatibility

This commit is contained in:
晴天
2026-05-23 08:25:34 +08:00
parent 579d706075
commit 8623efd49c
7 changed files with 510 additions and 14 deletions

View File

@@ -20,6 +20,7 @@ export const CHANNEL_LABELS = {
nostr: 'Nostr',
mattermost: 'Mattermost',
clickclack: 'ClickClack',
'nextcloud-talk': 'Nextcloud Talk',
'openclaw-weixin': '微信',
weixin: '微信',
}

View File

@@ -144,6 +144,23 @@ export default {
clickclackSenderIsOwnerHint: _('开启后将 ClickClack 消息发送者视为 owner 身份,适合可信内部工作区。', 'Treat the ClickClack sender as owner when enabled; use only in trusted internal workspaces.'),
clickclackDefaultToHint: _('默认发送目标,例如 channel:general、thread:123 或 dm:alice。', 'Default target, e.g. channel:general, thread:123, or dm:alice.'),
clickclackAllowFromHint: _('可选,逗号分隔允许来源;留空按上游默认处理,* 表示允许全部。', 'Optional comma-separated allowed sources; leave empty for upstream defaults, * allows all.'),
nextcloudTalkDesc: _('接入自托管 Nextcloud Talk支持私聊、房间消息和 webhook 回调', 'Connect self-hosted Nextcloud Talk with DMs, rooms, and webhook callbacks'),
nextcloudTalkGuide1: _('在 Nextcloud Talk 管理端创建 Bot并复制 Bot Secret', 'Create a bot in Nextcloud Talk administration and copy the Bot Secret'),
nextcloudTalkGuide2: _('填写 Nextcloud 站点 Base URL例如 <code>https://cloud.example.com</code>', 'Fill the Nextcloud site Base URL, for example <code>https://cloud.example.com</code>'),
nextcloudTalkGuide3: _('如需面板主动探测 Bot 能力,可填写 API User 与应用密码或密码文件', 'To let the panel probe bot capabilities, provide API User plus an app password or password file'),
nextcloudTalkGuide4: _('保存后面板会启用 bundled Nextcloud Talk 插件并重载 Gateway连通性以 Gateway 日志或 channels status 为准', 'After saving, the panel enables the bundled Nextcloud Talk plugin and reloads Gateway; verify connectivity through Gateway logs or channels status'),
nextcloudTalkGuideFooter: _('<div style="margin-top:8px;font-size:var(--font-size-xs);color:var(--text-tertiary)">Nextcloud Talk 最小配置需要 Base URL以及 Bot Secret 或 Secret File 其中一项。</div>', '<div style="margin-top:8px;font-size:var(--font-size-xs);color:var(--text-tertiary)">Nextcloud Talk minimally requires Base URL plus either Bot Secret or Secret File.</div>'),
nextcloudTalkBaseUrlHint: _('填写 Nextcloud 站点根地址,不要包含 Talk API 路径;末尾斜杠会由上游归一化。', 'Use the Nextcloud site root URL without Talk API paths; upstream normalizes trailing slashes.'),
nextcloudTalkBotSecretPh: _('Nextcloud Talk Bot Secret', 'Nextcloud Talk Bot Secret'),
nextcloudTalkBotSecretHint: _('生产环境建议改用 Secret File 或 SecretRef避免明文写入配置。', 'For production, prefer Secret File or SecretRef to avoid plain-text config secrets.'),
nextcloudTalkBotSecretFileHint: _('Bot Secret 文件路径;与 Bot Secret 二选一。', 'Path to the Bot Secret file; use this or Bot Secret.'),
nextcloudTalkApiPasswordPh: _('Nextcloud 应用密码', 'Nextcloud app password'),
nextcloudTalkApiPasswordHint: _('可选;用于管理接口探测 Bot response feature。', 'Optional; used for admin API probes of the bot response feature.'),
nextcloudTalkWebhookPublicUrlHint: _('Nextcloud 能访问的公网或反代地址,通常为面板/Gateway 的 webhook URL。', 'Public or reverse-proxy URL reachable by Nextcloud, usually the panel/Gateway webhook URL.'),
nextcloudTalkAllowFromHint: _('可选,逗号分隔允许私聊的用户 ID选择“允许所有私信”时会自动加入 *。', 'Optional comma-separated user IDs allowed for DMs; choosing Allow all DMs automatically adds *.'),
nextcloudTalkGroupAllowFromHint: _('可选,逗号分隔允许的 room token。', 'Optional comma-separated room tokens.'),
nextcloudTalkPrivateNetworkHint: _('仅在 Nextcloud 部署于可信内网且 Gateway 可以访问时开启。', 'Enable only when Nextcloud runs on a trusted private network reachable by Gateway.'),
nextcloudTalkSecretOrFile: _('Bot Secret 或 Secret File', 'Bot Secret or Secret File'),
synologyChatDesc: _('接入群晖 Synology Chat适合 NAS 内网团队协作', 'Connect Synology Chat for NAS-hosted team messaging'),
synologyChatGuide1: _('在 Synology Chat 管理后台创建 Bot并复制 Token', 'Create a bot in Synology Chat administration and copy its Token'),
synologyChatGuide2: _('配置 Incoming Webhook 或机器人发消息 URL填入 Incoming URL', 'Configure an Incoming Webhook or bot post URL, then paste it as Incoming URL'),

View File

@@ -310,6 +310,52 @@ const PLATFORM_REGISTRY = {
pairingChannel: 'clickclack',
pluginId: 'clickclack',
},
'nextcloud-talk': {
label: 'Nextcloud Talk',
iconName: 'message-square',
desc: t('channels.nextcloudTalkDesc'),
guide: [
t('channels.nextcloudTalkGuide1'),
t('channels.nextcloudTalkGuide2'),
t('channels.nextcloudTalkGuide3'),
t('channels.nextcloudTalkGuide4'),
],
guideFooter: t('channels.nextcloudTalkGuideFooter'),
fields: [
{ key: 'baseUrl', label: 'Base URL', placeholder: 'https://cloud.example.com', required: true, hint: t('channels.nextcloudTalkBaseUrlHint') },
{ key: 'botSecret', label: 'Bot Secret', placeholder: t('channels.nextcloudTalkBotSecretPh'), secret: true, required: false, hint: t('channels.nextcloudTalkBotSecretHint') },
{ key: 'botSecretFile', label: 'Secret File', placeholder: '/run/secrets/nextcloud-talk-bot-secret', required: false, hint: t('channels.nextcloudTalkBotSecretFileHint') },
{ key: 'apiUser', label: 'API User', placeholder: t('channels.optionalEg', { example: 'openclaw-bot' }), required: false },
{ key: 'apiPassword', label: 'API Password', placeholder: t('channels.nextcloudTalkApiPasswordPh'), secret: true, required: false, hint: t('channels.nextcloudTalkApiPasswordHint') },
{ key: 'apiPasswordFile', label: 'API Password File', placeholder: '/run/secrets/nextcloud-talk-api-password', required: false },
{ key: 'name', label: t('channels.accountName'), placeholder: t('channels.optionalEg', { example: 'work' }), required: false },
{ key: 'webhookPort', label: 'Webhook Port', placeholder: '8788', required: false },
{ key: 'webhookHost', label: 'Webhook Host', placeholder: '0.0.0.0', required: false },
{ key: 'webhookPath', label: 'Webhook Path', placeholder: '/nextcloud-talk-webhook', required: false },
{ key: 'webhookPublicUrl', label: 'Webhook Public URL', placeholder: 'https://panel.example.com/nextcloud-talk-webhook', required: false, hint: t('channels.nextcloudTalkWebhookPublicUrlHint') },
{ key: 'dmPolicy', label: t('channels.dmPolicy'), type: 'select', options: DM_POLICY_OPTIONS, required: false },
{ key: 'groupPolicy', label: t('channels.groupPolicy'), type: 'select', options: GROUP_POLICY_OPTIONS(t('channels.groupAllRooms'), { mention: true }), required: false },
{ key: 'allowFrom', label: 'Allow From', placeholder: 'alice, bob', required: false, hint: t('channels.nextcloudTalkAllowFromHint') },
{ key: 'groupAllowFrom', label: 'Group Allow From', placeholder: 'room-token-1, room-token-2', required: false, hint: t('channels.nextcloudTalkGroupAllowFromHint') },
{ key: 'historyLimit', label: 'History Limit', placeholder: '80', required: false },
{ key: 'dmHistoryLimit', label: 'DM History Limit', placeholder: '20', required: false },
{ key: 'mediaMaxMb', label: 'Media Max MB', placeholder: '50', required: false },
{ key: 'textChunkLimit', label: 'Text Chunk Limit', placeholder: '4000', required: false },
{ key: 'chunkMode', label: 'Chunk Mode', type: 'select', options: [
{ value: '', label: t('channels.policyDefault') },
{ value: 'length', label: 'Length' },
{ value: 'newline', label: 'Newline' },
], required: false },
{ key: 'blockStreaming', label: t('channels.signalBlockStreaming'), type: 'select', options: BOOLEAN_OPTIONS, required: false },
{ key: 'dangerouslyAllowPrivateNetwork', label: t('channels.mattermostPrivateNetwork'), type: 'select', options: BOOLEAN_OPTIONS, required: false, hint: t('channels.nextcloudTalkPrivateNetworkHint') },
{ key: 'responsePrefix', label: 'Response Prefix', placeholder: t('channels.optionalEg', { example: '[Talk]' }), required: false },
],
requiredAny: [{ keys: ['botSecret', 'botSecretFile'], label: t('channels.nextcloudTalkSecretOrFile') }],
configKey: 'nextcloud-talk',
pairingChannel: 'nextcloud-talk',
pluginRequired: '@openclaw/nextcloud-talk@latest',
pluginId: 'nextcloud-talk',
},
'synology-chat': {
label: 'Synology Chat',
iconName: 'message-square',
@@ -832,7 +878,7 @@ function applyRouteIntent(page, state) {
// ── 已配置平台渲染 ──
// ── 多账号支持的平台:与 OpenClaw 的 accounts/defaultAccount 配置模型保持一致 ──
const MULTI_INSTANCE_PLATFORMS = ['telegram', 'discord', 'slack', 'feishu', 'dingtalk', 'dingtalk-connector', 'qqbot', 'zalo', 'zalouser', 'line', 'mattermost', 'clickclack', 'synology-chat', 'googlechat', 'signal']
const MULTI_INSTANCE_PLATFORMS = ['telegram', 'discord', 'slack', 'feishu', 'dingtalk', 'dingtalk-connector', 'qqbot', 'zalo', 'zalouser', 'line', 'mattermost', 'clickclack', 'nextcloud-talk', 'synology-chat', 'googlechat', 'signal']
function supportsMessagingMultiAccount(pid) {
return MULTI_INSTANCE_PLATFORMS.includes(pid)