Spaces:
Running
Running
| export type TlonTarget = | |
| | { kind: "dm"; ship: string } | |
| | { kind: "group"; nest: string; hostShip: string; channelName: string }; | |
| const SHIP_RE = /^~?[a-z-]+$/i; | |
| const NEST_RE = /^chat\/([^/]+)\/([^/]+)$/i; | |
| export function normalizeShip(raw: string): string { | |
| const trimmed = raw.trim(); | |
| if (!trimmed) { | |
| return trimmed; | |
| } | |
| return trimmed.startsWith("~") ? trimmed : `~${trimmed}`; | |
| } | |
| export function parseChannelNest(raw: string): { hostShip: string; channelName: string } | null { | |
| const match = NEST_RE.exec(raw.trim()); | |
| if (!match) { | |
| return null; | |
| } | |
| const hostShip = normalizeShip(match[1]); | |
| const channelName = match[2]; | |
| return { hostShip, channelName }; | |
| } | |
| export function parseTlonTarget(raw?: string | null): TlonTarget | null { | |
| const trimmed = raw?.trim(); | |
| if (!trimmed) { | |
| return null; | |
| } | |
| const withoutPrefix = trimmed.replace(/^tlon:/i, ""); | |
| const dmPrefix = withoutPrefix.match(/^dm[/:](.+)$/i); | |
| if (dmPrefix) { | |
| return { kind: "dm", ship: normalizeShip(dmPrefix[1]) }; | |
| } | |
| const groupPrefix = withoutPrefix.match(/^(group|room)[/:](.+)$/i); | |
| if (groupPrefix) { | |
| const groupTarget = groupPrefix[2].trim(); | |
| if (groupTarget.startsWith("chat/")) { | |
| const parsed = parseChannelNest(groupTarget); | |
| if (!parsed) { | |
| return null; | |
| } | |
| return { | |
| kind: "group", | |
| nest: `chat/${parsed.hostShip}/${parsed.channelName}`, | |
| hostShip: parsed.hostShip, | |
| channelName: parsed.channelName, | |
| }; | |
| } | |
| const parts = groupTarget.split("/"); | |
| if (parts.length === 2) { | |
| const hostShip = normalizeShip(parts[0]); | |
| const channelName = parts[1]; | |
| return { | |
| kind: "group", | |
| nest: `chat/${hostShip}/${channelName}`, | |
| hostShip, | |
| channelName, | |
| }; | |
| } | |
| return null; | |
| } | |
| if (withoutPrefix.startsWith("chat/")) { | |
| const parsed = parseChannelNest(withoutPrefix); | |
| if (!parsed) { | |
| return null; | |
| } | |
| return { | |
| kind: "group", | |
| nest: `chat/${parsed.hostShip}/${parsed.channelName}`, | |
| hostShip: parsed.hostShip, | |
| channelName: parsed.channelName, | |
| }; | |
| } | |
| if (SHIP_RE.test(withoutPrefix)) { | |
| return { kind: "dm", ship: normalizeShip(withoutPrefix) }; | |
| } | |
| return null; | |
| } | |
| export function formatTargetHint(): string { | |
| return "dm/~sampel-palnet | ~sampel-palnet | chat/~host-ship/channel | group:~host-ship/channel"; | |
| } | |