feat: añadir IdentityService para mapear alias a números
Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>pull/1/head
parent
f4b0e4433e
commit
67caca8b26
@ -0,0 +1,65 @@
|
|||||||
|
import type { Database } from 'bun:sqlite';
|
||||||
|
import { db } from '../db';
|
||||||
|
import { normalizeWhatsAppId } from '../utils/whatsapp';
|
||||||
|
import { Metrics } from './metrics';
|
||||||
|
|
||||||
|
export class IdentityService {
|
||||||
|
static dbInstance: Database = db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registra o actualiza un alias (LID u otro identificador) apuntando al user_id real (número).
|
||||||
|
* Devuelve true si se insertó/actualizó, false si no se pudo o no era necesario.
|
||||||
|
*/
|
||||||
|
static upsertAlias(alias: string | null | undefined, userId: string | null | undefined, source?: string | null): boolean {
|
||||||
|
const a = normalizeWhatsAppId(alias || '');
|
||||||
|
const u = normalizeWhatsAppId(userId || '');
|
||||||
|
if (!a || !u || a === u) return false;
|
||||||
|
try {
|
||||||
|
this.dbInstance.prepare(`
|
||||||
|
INSERT INTO user_aliases (alias, user_id, source, created_at, updated_at)
|
||||||
|
VALUES (?, ?, ?, strftime('%Y-%m-%d %H:%M:%f', 'now'), strftime('%Y-%m-%d %H:%M:%f', 'now'))
|
||||||
|
ON CONFLICT(alias) DO UPDATE SET
|
||||||
|
user_id = excluded.user_id,
|
||||||
|
source = COALESCE(excluded.source, source),
|
||||||
|
updated_at = excluded.updated_at
|
||||||
|
`).run(a, u, source ?? null);
|
||||||
|
try { Metrics.inc('identity_alias_upserts_total'); } catch {}
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resuelve un alias a su número real. Devuelve null si no hay mapeo.
|
||||||
|
*/
|
||||||
|
static resolveAliasOrNull(id: string | null | undefined): string | null {
|
||||||
|
const n = normalizeWhatsAppId(id || '');
|
||||||
|
if (!n) return null;
|
||||||
|
try {
|
||||||
|
const row = this.dbInstance.prepare(`SELECT user_id FROM user_aliases WHERE alias = ?`).get(n) as any;
|
||||||
|
if (row?.user_id) {
|
||||||
|
try { Metrics.inc('identity_alias_resolved_total'); } catch {}
|
||||||
|
return String(row.user_id);
|
||||||
|
}
|
||||||
|
try { Metrics.inc('identity_alias_unresolved_total'); } catch {}
|
||||||
|
return null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resuelve en lote varios ids (devuelve solo los que tengan mapeo).
|
||||||
|
*/
|
||||||
|
static resolveMany(ids: Array<string | null | undefined>): Map<string, string> {
|
||||||
|
const map = new Map<string, string>();
|
||||||
|
for (const id of ids) {
|
||||||
|
const n = normalizeWhatsAppId(id || '');
|
||||||
|
if (!n) continue;
|
||||||
|
const r = this.resolveAliasOrNull(n);
|
||||||
|
if (r) map.set(n, r);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue