feat(guild): translate <@user.name:NAME> -> <@userId>

Before persist/parse, resolve <@user.name:NAME> (outside backticks) via
Center and rewrite to <@userId>; unresolved tokens left as-is. Translated
ids then flow into the existing mention/wakeup/sub-frame logic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
h z
2026-05-15 15:47:01 +01:00
parent 02b7c72e70
commit 22fd834ed0
3 changed files with 92 additions and 5 deletions

View File

@@ -25,3 +25,25 @@ export async function introspectGuildToken(token: string): Promise<{ active: boo
user: data.user,
};
}
// Resolve <@user.name:NAME> names to userIds within this guild node via
// Center. Unresolved names are simply absent from the returned map.
export async function resolveUserNames(names: string[]): Promise<Record<string, string>> {
const centerBaseUrl = process.env.FABRIC_BACKEND_GUILD_CENTER_BASE_URL;
const guildNodeId = process.env.FABRIC_BACKEND_GUILD_NODE_ID;
const centerApiKey = process.env.FABRIC_BACKEND_GUILD_CENTER_API_KEY;
if (!centerBaseUrl || !guildNodeId || !centerApiKey || !names.length) return {};
try {
const res = await fetch(`${centerBaseUrl}/api/auth/resolve-names`, {
method: 'POST',
headers: { 'content-type': 'application/json', 'x-api-key': centerApiKey },
body: JSON.stringify({ guildNodeId, names }),
});
if (!res.ok) return {};
const data = (await res.json()) as { resolved?: Record<string, string> };
return data.resolved ?? {};
} catch {
return {};
}
}