diff --git a/src/channels/targets.ts b/src/channels/targets.ts index 7c9d9cf60f..dcf9012fdc 100644 --- a/src/channels/targets.ts +++ b/src/channels/targets.ts @@ -43,6 +43,30 @@ export function ensureTargetId(params: { return params.candidate; } +export function parseTargetMention(params: { + raw: string; + mentionPattern: RegExp; + kind: MessagingTargetKind; +}): MessagingTarget | undefined { + const match = params.raw.match(params.mentionPattern); + if (!match?.[1]) { + return undefined; + } + return buildMessagingTarget(params.kind, match[1], params.raw); +} + +export function parseTargetPrefix(params: { + raw: string; + prefix: string; + kind: MessagingTargetKind; +}): MessagingTarget | undefined { + if (!params.raw.startsWith(params.prefix)) { + return undefined; + } + const id = params.raw.slice(params.prefix.length).trim(); + return id ? buildMessagingTarget(params.kind, id, params.raw) : undefined; +} + export function requireTargetKind(params: { platform: string; target: MessagingTarget | undefined; diff --git a/src/discord/targets.ts b/src/discord/targets.ts index 4807bec50b..eabed546a2 100644 --- a/src/discord/targets.ts +++ b/src/discord/targets.ts @@ -2,6 +2,8 @@ import type { DirectoryConfigParams } from "../channels/plugins/directory-config import { buildMessagingTarget, ensureTargetId, + parseTargetMention, + parseTargetPrefix, requireTargetKind, type MessagingTarget, type MessagingTargetKind, @@ -23,21 +25,32 @@ export function parseDiscordTarget( if (!trimmed) { return undefined; } - const mentionMatch = trimmed.match(/^<@!?(\d+)>$/); - if (mentionMatch) { - return buildMessagingTarget("user", mentionMatch[1], trimmed); + const mentionTarget = parseTargetMention({ + raw: trimmed, + mentionPattern: /^<@!?(\d+)>$/, + kind: "user", + }); + if (mentionTarget) { + return mentionTarget; } - if (trimmed.startsWith("user:")) { - const id = trimmed.slice("user:".length).trim(); - return id ? buildMessagingTarget("user", id, trimmed) : undefined; - } - if (trimmed.startsWith("channel:")) { - const id = trimmed.slice("channel:".length).trim(); - return id ? buildMessagingTarget("channel", id, trimmed) : undefined; - } - if (trimmed.startsWith("discord:")) { - const id = trimmed.slice("discord:".length).trim(); - return id ? buildMessagingTarget("user", id, trimmed) : undefined; + const prefixedTarget = + parseTargetPrefix({ + raw: trimmed, + prefix: "user:", + kind: "user", + }) ?? + parseTargetPrefix({ + raw: trimmed, + prefix: "channel:", + kind: "channel", + }) ?? + parseTargetPrefix({ + raw: trimmed, + prefix: "discord:", + kind: "user", + }); + if (prefixedTarget) { + return prefixedTarget; } if (trimmed.startsWith("@")) { const candidate = trimmed.slice(1).trim(); diff --git a/src/slack/targets.ts b/src/slack/targets.ts index 7f66a1d5c8..2d93198493 100644 --- a/src/slack/targets.ts +++ b/src/slack/targets.ts @@ -1,6 +1,8 @@ import { buildMessagingTarget, ensureTargetId, + parseTargetMention, + parseTargetPrefix, requireTargetKind, type MessagingTarget, type MessagingTargetKind, @@ -21,21 +23,32 @@ export function parseSlackTarget( if (!trimmed) { return undefined; } - const mentionMatch = trimmed.match(/^<@([A-Z0-9]+)>$/i); - if (mentionMatch) { - return buildMessagingTarget("user", mentionMatch[1], trimmed); + const mentionTarget = parseTargetMention({ + raw: trimmed, + mentionPattern: /^<@([A-Z0-9]+)>$/i, + kind: "user", + }); + if (mentionTarget) { + return mentionTarget; } - if (trimmed.startsWith("user:")) { - const id = trimmed.slice("user:".length).trim(); - return id ? buildMessagingTarget("user", id, trimmed) : undefined; - } - if (trimmed.startsWith("channel:")) { - const id = trimmed.slice("channel:".length).trim(); - return id ? buildMessagingTarget("channel", id, trimmed) : undefined; - } - if (trimmed.startsWith("slack:")) { - const id = trimmed.slice("slack:".length).trim(); - return id ? buildMessagingTarget("user", id, trimmed) : undefined; + const prefixedTarget = + parseTargetPrefix({ + raw: trimmed, + prefix: "user:", + kind: "user", + }) ?? + parseTargetPrefix({ + raw: trimmed, + prefix: "channel:", + kind: "channel", + }) ?? + parseTargetPrefix({ + raw: trimmed, + prefix: "slack:", + kind: "user", + }); + if (prefixedTarget) { + return prefixedTarget; } if (trimmed.startsWith("@")) { const candidate = trimmed.slice(1).trim();