feat: enhance BlueBubbles channel integration with new messaging target normalization and typing indicator improvements
This commit is contained in:
committed by
Peter Steinberger
parent
61907ddf3e
commit
a5d89e6eb1
@@ -250,6 +250,7 @@ const FIELD_LABELS: Record<string, string> = {
|
||||
"channels.slack": "Slack",
|
||||
"channels.signal": "Signal",
|
||||
"channels.imessage": "iMessage",
|
||||
"channels.bluebubbles": "BlueBubbles",
|
||||
"channels.msteams": "MS Teams",
|
||||
"channels.telegram.botToken": "Telegram Bot Token",
|
||||
"channels.telegram.dmPolicy": "Telegram DM Policy",
|
||||
@@ -268,6 +269,7 @@ const FIELD_LABELS: Record<string, string> = {
|
||||
"channels.whatsapp.debounceMs": "WhatsApp Message Debounce (ms)",
|
||||
"channels.signal.dmPolicy": "Signal DM Policy",
|
||||
"channels.imessage.dmPolicy": "iMessage DM Policy",
|
||||
"channels.bluebubbles.dmPolicy": "BlueBubbles DM Policy",
|
||||
"channels.discord.dm.policy": "Discord DM Policy",
|
||||
"channels.discord.retry.attempts": "Discord Retry Attempts",
|
||||
"channels.discord.retry.minDelayMs": "Discord Retry Min Delay (ms)",
|
||||
@@ -540,6 +542,8 @@ const FIELD_HELP: Record<string, string> = {
|
||||
'Direct message access control ("pairing" recommended). "open" requires channels.signal.allowFrom=["*"].',
|
||||
"channels.imessage.dmPolicy":
|
||||
'Direct message access control ("pairing" recommended). "open" requires channels.imessage.allowFrom=["*"].',
|
||||
"channels.bluebubbles.dmPolicy":
|
||||
'Direct message access control ("pairing" recommended). "open" requires channels.bluebubbles.allowFrom=["*"].',
|
||||
"channels.discord.dm.policy":
|
||||
'Direct message access control ("pairing" recommended). "open" requires channels.discord.dm.allowFrom=["*"].',
|
||||
"channels.discord.retry.attempts":
|
||||
|
||||
@@ -482,6 +482,79 @@ export const IMessageConfigSchema = IMessageAccountSchemaBase.extend({
|
||||
});
|
||||
});
|
||||
|
||||
const BlueBubblesAllowFromEntry = z.union([z.string(), z.number()]);
|
||||
|
||||
const BlueBubblesActionSchema = z
|
||||
.object({
|
||||
reactions: z.boolean().optional(),
|
||||
edit: z.boolean().optional(),
|
||||
unsend: z.boolean().optional(),
|
||||
reply: z.boolean().optional(),
|
||||
sendWithEffect: z.boolean().optional(),
|
||||
renameGroup: z.boolean().optional(),
|
||||
addParticipant: z.boolean().optional(),
|
||||
removeParticipant: z.boolean().optional(),
|
||||
leaveGroup: z.boolean().optional(),
|
||||
sendAttachment: z.boolean().optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
const BlueBubblesGroupConfigSchema = z
|
||||
.object({
|
||||
requireMention: z.boolean().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const BlueBubblesAccountSchemaBase = z
|
||||
.object({
|
||||
name: z.string().optional(),
|
||||
capabilities: z.array(z.string()).optional(),
|
||||
configWrites: z.boolean().optional(),
|
||||
enabled: z.boolean().optional(),
|
||||
serverUrl: z.string().optional(),
|
||||
password: z.string().optional(),
|
||||
webhookPath: z.string().optional(),
|
||||
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
||||
allowFrom: z.array(BlueBubblesAllowFromEntry).optional(),
|
||||
groupAllowFrom: z.array(BlueBubblesAllowFromEntry).optional(),
|
||||
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
||||
historyLimit: z.number().int().min(0).optional(),
|
||||
dmHistoryLimit: z.number().int().min(0).optional(),
|
||||
dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
|
||||
textChunkLimit: z.number().int().positive().optional(),
|
||||
mediaMaxMb: z.number().int().positive().optional(),
|
||||
sendReadReceipts: z.boolean().optional(),
|
||||
blockStreaming: z.boolean().optional(),
|
||||
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
||||
groups: z.record(z.string(), BlueBubblesGroupConfigSchema.optional()).optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const BlueBubblesAccountSchema = BlueBubblesAccountSchemaBase.superRefine((value, ctx) => {
|
||||
requireOpenAllowFrom({
|
||||
policy: value.dmPolicy,
|
||||
allowFrom: value.allowFrom,
|
||||
ctx,
|
||||
path: ["allowFrom"],
|
||||
message: 'channels.bluebubbles.accounts.*.dmPolicy="open" requires allowFrom to include "*"',
|
||||
});
|
||||
});
|
||||
|
||||
export const BlueBubblesConfigSchema = BlueBubblesAccountSchemaBase.extend({
|
||||
accounts: z.record(z.string(), BlueBubblesAccountSchema.optional()).optional(),
|
||||
actions: BlueBubblesActionSchema,
|
||||
}).superRefine((value, ctx) => {
|
||||
requireOpenAllowFrom({
|
||||
policy: value.dmPolicy,
|
||||
allowFrom: value.allowFrom,
|
||||
ctx,
|
||||
path: ["allowFrom"],
|
||||
message:
|
||||
'channels.bluebubbles.dmPolicy="open" requires channels.bluebubbles.allowFrom to include "*"',
|
||||
});
|
||||
});
|
||||
|
||||
export const MSTeamsChannelSchema = z
|
||||
.object({
|
||||
requireMention: z.boolean().optional(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
BlueBubblesConfigSchema,
|
||||
DiscordConfigSchema,
|
||||
IMessageConfigSchema,
|
||||
MSTeamsConfigSchema,
|
||||
@@ -28,6 +29,7 @@ export const ChannelsSchema = z
|
||||
slack: SlackConfigSchema.optional(),
|
||||
signal: SignalConfigSchema.optional(),
|
||||
imessage: IMessageConfigSchema.optional(),
|
||||
bluebubbles: BlueBubblesConfigSchema.optional(),
|
||||
msteams: MSTeamsConfigSchema.optional(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
Reference in New Issue
Block a user