refactor: streamline target resolver helpers
This commit is contained in:
@@ -164,13 +164,15 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
||||
},
|
||||
messaging: {
|
||||
normalizeTarget: normalizeMatrixMessagingTarget,
|
||||
looksLikeTargetId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
if (/^(matrix:)?[!#@]/i.test(trimmed)) return true;
|
||||
return trimmed.includes(":");
|
||||
targetResolver: {
|
||||
looksLikeId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
if (/^(matrix:)?[!#@]/i.test(trimmed)) return true;
|
||||
return trimmed.includes(":");
|
||||
},
|
||||
hint: "<room|alias|user>",
|
||||
},
|
||||
targetHint: "<room|alias|user>",
|
||||
},
|
||||
directory: {
|
||||
self: async () => null,
|
||||
|
||||
@@ -133,13 +133,15 @@ export const msteamsPlugin: ChannelPlugin<ResolvedMSTeamsAccount> = {
|
||||
},
|
||||
messaging: {
|
||||
normalizeTarget: normalizeMSTeamsMessagingTarget,
|
||||
looksLikeTargetId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
if (/^(conversation:|user:)/i.test(trimmed)) return true;
|
||||
return trimmed.includes("@thread");
|
||||
targetResolver: {
|
||||
looksLikeId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
if (/^(conversation:|user:)/i.test(trimmed)) return true;
|
||||
return trimmed.includes("@thread");
|
||||
},
|
||||
hint: "<conversationId|user:ID|conversation:ID>",
|
||||
},
|
||||
targetHint: "<conversationId|user:ID|conversation:ID>",
|
||||
},
|
||||
directory: {
|
||||
self: async () => null,
|
||||
|
||||
@@ -150,12 +150,14 @@ export const zaloPlugin: ChannelPlugin<ResolvedZaloAccount> = {
|
||||
actions: zaloMessageActions,
|
||||
messaging: {
|
||||
normalizeTarget: normalizeZaloMessagingTarget,
|
||||
looksLikeTargetId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
return /^\d{3,}$/.test(trimmed);
|
||||
targetResolver: {
|
||||
looksLikeId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
return /^\d{3,}$/.test(trimmed);
|
||||
},
|
||||
hint: "<chatId>",
|
||||
},
|
||||
targetHint: "<chatId>",
|
||||
},
|
||||
directory: {
|
||||
self: async () => null,
|
||||
|
||||
@@ -218,12 +218,14 @@ export const zalouserPlugin: ChannelPlugin<ResolvedZalouserAccount> = {
|
||||
if (!trimmed) return undefined;
|
||||
return trimmed.replace(/^(zalouser|zlu):/i, "");
|
||||
},
|
||||
looksLikeTargetId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
return /^\d{3,}$/.test(trimmed);
|
||||
targetResolver: {
|
||||
looksLikeId: (raw) => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
return /^\d{3,}$/.test(trimmed);
|
||||
},
|
||||
hint: "<threadId>",
|
||||
},
|
||||
targetHint: "<threadId>",
|
||||
},
|
||||
directory: {
|
||||
self: async ({ cfg, accountId, runtime }) => {
|
||||
|
||||
@@ -74,4 +74,15 @@ export function normalizeChannelId(raw?: string | null): ChannelId | null {
|
||||
}
|
||||
|
||||
export { discordPlugin, imessagePlugin, signalPlugin, slackPlugin, telegramPlugin, whatsappPlugin };
|
||||
export {
|
||||
listDiscordDirectoryGroupsFromConfig,
|
||||
listDiscordDirectoryPeersFromConfig,
|
||||
listSlackDirectoryGroupsFromConfig,
|
||||
listSlackDirectoryPeersFromConfig,
|
||||
listTelegramDirectoryGroupsFromConfig,
|
||||
listTelegramDirectoryPeersFromConfig,
|
||||
listWhatsAppDirectoryGroupsFromConfig,
|
||||
listWhatsAppDirectoryPeersFromConfig,
|
||||
type DirectoryConfigParams,
|
||||
} from "./directory-config.js";
|
||||
export type { ChannelId, ChannelPlugin } from "./types.js";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { formatTargetHint } from "./target-format.js";
|
||||
|
||||
export function missingTargetMessage(provider: string, hint?: string): string {
|
||||
return `Delivering to ${provider} requires target${formatHint(hint)}`;
|
||||
return `Delivering to ${provider} requires target${formatTargetHint(hint)}`;
|
||||
}
|
||||
|
||||
export function missingTargetError(provider: string, hint?: string): Error {
|
||||
@@ -7,7 +9,7 @@ export function missingTargetError(provider: string, hint?: string): Error {
|
||||
}
|
||||
|
||||
export function ambiguousTargetMessage(provider: string, raw: string, hint?: string): string {
|
||||
return `Ambiguous target "${raw}" for ${provider}. Provide a unique name or an explicit id.${formatHint(hint, true)}`;
|
||||
return `Ambiguous target "${raw}" for ${provider}. Provide a unique name or an explicit id.${formatTargetHint(hint, true)}`;
|
||||
}
|
||||
|
||||
export function ambiguousTargetError(provider: string, raw: string, hint?: string): Error {
|
||||
@@ -15,14 +17,9 @@ export function ambiguousTargetError(provider: string, raw: string, hint?: strin
|
||||
}
|
||||
|
||||
export function unknownTargetMessage(provider: string, raw: string, hint?: string): string {
|
||||
return `Unknown target "${raw}" for ${provider}.${formatHint(hint, true)}`;
|
||||
return `Unknown target "${raw}" for ${provider}.${formatTargetHint(hint, true)}`;
|
||||
}
|
||||
|
||||
export function unknownTargetError(provider: string, raw: string, hint?: string): Error {
|
||||
return new Error(unknownTargetMessage(provider, raw, hint));
|
||||
}
|
||||
|
||||
function formatHint(hint?: string, withLabel = false): string {
|
||||
if (!hint) return "";
|
||||
return withLabel ? ` Hint: ${hint}` : ` ${hint}`;
|
||||
}
|
||||
|
||||
4
src/infra/outbound/target-format.ts
Normal file
4
src/infra/outbound/target-format.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export function formatTargetHint(hint?: string, withLabel = false): string {
|
||||
if (!hint) return "";
|
||||
return withLabel ? ` Hint: ${hint}` : ` ${hint}`;
|
||||
}
|
||||
@@ -164,24 +164,6 @@ function resolveMatch(params: {
|
||||
return { kind: "ambiguous" as const, entries: matches };
|
||||
}
|
||||
|
||||
function looksLikeTargetId(params: {
|
||||
channel: ChannelId;
|
||||
raw: string;
|
||||
normalized: string;
|
||||
}): boolean {
|
||||
const raw = params.raw.trim();
|
||||
if (!raw) return false;
|
||||
const plugin = getChannelPlugin(params.channel);
|
||||
const lookup = plugin?.messaging?.targetResolver?.looksLikeId;
|
||||
if (lookup) return lookup(raw, params.normalized);
|
||||
if (/^(channel|group|user):/i.test(raw)) return true;
|
||||
if (/^[@#]/.test(raw)) return true;
|
||||
if (/^\+?\d{6,}$/.test(raw)) return true;
|
||||
if (raw.includes("@thread")) return true;
|
||||
if (/^(conversation|user):/i.test(raw)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
async function listDirectoryEntries(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
channel: ChannelId;
|
||||
@@ -288,7 +270,19 @@ export async function resolveMessagingTarget(params: {
|
||||
const hint = plugin?.messaging?.targetResolver?.hint;
|
||||
const kind = detectTargetKind(raw, params.preferredKind);
|
||||
const normalized = normalizeTargetForProvider(params.channel, raw) ?? raw;
|
||||
if (looksLikeTargetId({ channel: params.channel, raw, normalized })) {
|
||||
const looksLikeTargetId = (): boolean => {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return false;
|
||||
const lookup = plugin?.messaging?.targetResolver?.looksLikeId;
|
||||
if (lookup) return lookup(trimmed, normalized);
|
||||
if (/^(channel|group|user):/i.test(trimmed)) return true;
|
||||
if (/^[@#]/.test(trimmed)) return true;
|
||||
if (/^\+?\d{6,}$/.test(trimmed)) return true;
|
||||
if (trimmed.includes("@thread")) return true;
|
||||
if (/^(conversation|user):/i.test(trimmed)) return true;
|
||||
return false;
|
||||
};
|
||||
if (looksLikeTargetId()) {
|
||||
const directTarget = preserveTargetCase(params.channel, raw, normalized);
|
||||
return {
|
||||
ok: true,
|
||||
|
||||
Reference in New Issue
Block a user