mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 21:24:31 +00:00
refactor: de-duplicate channel runtime and payload helpers
This commit is contained in:
@@ -10,9 +10,8 @@ import { resolveSignalAccount } from "../signal/accounts.js";
|
||||
import { resolveSlackAccount, resolveSlackReplyToMode } from "../slack/accounts.js";
|
||||
import { buildSlackThreadingToolContext } from "../slack/threading-tool-context.js";
|
||||
import { resolveTelegramAccount } from "../telegram/accounts.js";
|
||||
import { escapeRegExp, normalizeE164 } from "../utils.js";
|
||||
import { normalizeE164 } from "../utils.js";
|
||||
import { resolveWhatsAppAccount } from "../web/accounts.js";
|
||||
import { normalizeWhatsAppTarget } from "../whatsapp/normalize.js";
|
||||
import {
|
||||
resolveDiscordGroupRequireMention,
|
||||
resolveDiscordGroupToolPolicy,
|
||||
@@ -28,6 +27,7 @@ import {
|
||||
resolveWhatsAppGroupToolPolicy,
|
||||
} from "./plugins/group-mentions.js";
|
||||
import { normalizeSignalMessagingTarget } from "./plugins/normalize/signal.js";
|
||||
import { normalizeWhatsAppAllowFromEntries } from "./plugins/normalize/whatsapp.js";
|
||||
import type {
|
||||
ChannelCapabilities,
|
||||
ChannelCommandAdapter,
|
||||
@@ -42,6 +42,10 @@ import type {
|
||||
ChannelThreadingAdapter,
|
||||
ChannelThreadingToolContext,
|
||||
} from "./plugins/types.js";
|
||||
import {
|
||||
resolveWhatsAppGroupIntroHint,
|
||||
resolveWhatsAppMentionStripPatterns,
|
||||
} from "./plugins/whatsapp-shared.js";
|
||||
import { CHAT_CHANNEL_ORDER, type ChatChannelId, getChatChannelMeta } from "./registry.js";
|
||||
|
||||
export type ChannelDock = {
|
||||
@@ -287,12 +291,7 @@ const DOCKS: Record<ChatChannelId, ChannelDock> = {
|
||||
config: {
|
||||
resolveAllowFrom: ({ cfg, accountId }) =>
|
||||
resolveWhatsAppAccount({ cfg, accountId }).allowFrom ?? [],
|
||||
formatAllowFrom: ({ allowFrom }) =>
|
||||
allowFrom
|
||||
.map((entry) => String(entry).trim())
|
||||
.filter((entry): entry is string => Boolean(entry))
|
||||
.map((entry) => (entry === "*" ? entry : normalizeWhatsAppTarget(entry)))
|
||||
.filter((entry): entry is string => Boolean(entry)),
|
||||
formatAllowFrom: ({ allowFrom }) => normalizeWhatsAppAllowFromEntries(allowFrom),
|
||||
resolveDefaultTo: ({ cfg, accountId }) => {
|
||||
const root = cfg.channels?.whatsapp;
|
||||
const normalized = normalizeAccountId(accountId);
|
||||
@@ -303,18 +302,10 @@ const DOCKS: Record<ChatChannelId, ChannelDock> = {
|
||||
groups: {
|
||||
resolveRequireMention: resolveWhatsAppGroupRequireMention,
|
||||
resolveToolPolicy: resolveWhatsAppGroupToolPolicy,
|
||||
resolveGroupIntroHint: () =>
|
||||
"WhatsApp IDs: SenderId is the participant JID (group participant id).",
|
||||
resolveGroupIntroHint: resolveWhatsAppGroupIntroHint,
|
||||
},
|
||||
mentions: {
|
||||
stripPatterns: ({ ctx }) => {
|
||||
const selfE164 = (ctx.To ?? "").replace(/^whatsapp:/, "");
|
||||
if (!selfE164) {
|
||||
return [];
|
||||
}
|
||||
const escaped = escapeRegExp(selfE164);
|
||||
return [escaped, `@${escaped}`];
|
||||
},
|
||||
stripPatterns: ({ ctx }) => resolveWhatsAppMentionStripPatterns(ctx),
|
||||
},
|
||||
threading: {
|
||||
buildToolContext: ({ context, hasRepliedRef }) => {
|
||||
|
||||
33
src/channels/plugins/media-payload.ts
Normal file
33
src/channels/plugins/media-payload.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
export type MediaPayloadInput = {
|
||||
path: string;
|
||||
contentType?: string;
|
||||
};
|
||||
|
||||
export type MediaPayload = {
|
||||
MediaPath?: string;
|
||||
MediaType?: string;
|
||||
MediaUrl?: string;
|
||||
MediaPaths?: string[];
|
||||
MediaUrls?: string[];
|
||||
MediaTypes?: string[];
|
||||
};
|
||||
|
||||
export function buildMediaPayload(
|
||||
mediaList: MediaPayloadInput[],
|
||||
opts?: { preserveMediaTypeCardinality?: boolean },
|
||||
): MediaPayload {
|
||||
const first = mediaList[0];
|
||||
const mediaPaths = mediaList.map((media) => media.path);
|
||||
const rawMediaTypes = mediaList.map((media) => media.contentType ?? "");
|
||||
const mediaTypes = opts?.preserveMediaTypeCardinality
|
||||
? rawMediaTypes
|
||||
: rawMediaTypes.filter((value): value is string => Boolean(value));
|
||||
return {
|
||||
MediaPath: first?.path,
|
||||
MediaType: first?.contentType,
|
||||
MediaUrl: first?.path,
|
||||
MediaPaths: mediaPaths.length > 0 ? mediaPaths : undefined,
|
||||
MediaUrls: mediaPaths.length > 0 ? mediaPaths : undefined,
|
||||
MediaTypes: mediaTypes.length > 0 ? mediaTypes : undefined,
|
||||
};
|
||||
}
|
||||
@@ -9,6 +9,14 @@ export function normalizeWhatsAppMessagingTarget(raw: string): string | undefine
|
||||
return normalizeWhatsAppTarget(trimmed) ?? undefined;
|
||||
}
|
||||
|
||||
export function normalizeWhatsAppAllowFromEntries(allowFrom: Array<string | number>): string[] {
|
||||
return allowFrom
|
||||
.map((entry) => String(entry).trim())
|
||||
.filter((entry): entry is string => Boolean(entry))
|
||||
.map((entry) => (entry === "*" ? entry : normalizeWhatsAppTarget(entry)))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
}
|
||||
|
||||
export function looksLikeWhatsAppTargetId(raw: string): boolean {
|
||||
return looksLikeHandleOrPhoneTarget({
|
||||
raw,
|
||||
|
||||
17
src/channels/plugins/whatsapp-shared.ts
Normal file
17
src/channels/plugins/whatsapp-shared.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { escapeRegExp } from "../../utils.js";
|
||||
|
||||
export const WHATSAPP_GROUP_INTRO_HINT =
|
||||
"WhatsApp IDs: SenderId is the participant JID (group participant id).";
|
||||
|
||||
export function resolveWhatsAppGroupIntroHint(): string {
|
||||
return WHATSAPP_GROUP_INTRO_HINT;
|
||||
}
|
||||
|
||||
export function resolveWhatsAppMentionStripPatterns(ctx: { To?: string | null }): string[] {
|
||||
const selfE164 = (ctx.To ?? "").replace(/^whatsapp:/, "");
|
||||
if (!selfE164) {
|
||||
return [];
|
||||
}
|
||||
const escaped = escapeRegExp(selfE164);
|
||||
return [escaped, `@${escaped}`];
|
||||
}
|
||||
Reference in New Issue
Block a user