55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
"use server";
|
|
import { rawDb } from "@/lib/db/client";
|
|
import { reverseName } from "@/lib/jav/nameUtils";
|
|
|
|
export interface ActressLookupResult {
|
|
name: string;
|
|
match: { id: number; name: string; slug: string } | null;
|
|
}
|
|
|
|
/**
|
|
* For each input name, find an existing actress matching by:
|
|
* - canonical name (exact, case-insensitive)
|
|
* - any entry in alt_names (comma-separated)
|
|
* - the reversed-word-order form (e.g. "Atomi Shuri" matches "Shuri Atomi")
|
|
* Returns one row per input preserving order.
|
|
*/
|
|
export async function lookupActressesByNames(names: string[]): Promise<ActressLookupResult[]> {
|
|
const trimmed = names.map((n) => n.trim()).filter(Boolean);
|
|
if (trimmed.length === 0) return [];
|
|
const rows = rawDb.prepare(`SELECT id, name, slug, alt_names AS altNames FROM actresses`).all() as Array<{
|
|
id: number;
|
|
name: string;
|
|
slug: string;
|
|
altNames: string | null;
|
|
}>;
|
|
|
|
type Indexed = { id: number; name: string; slug: string; keys: Set<string> };
|
|
const indexed: Indexed[] = rows.map((r) => {
|
|
const keys = new Set<string>();
|
|
keys.add(r.name.toLowerCase());
|
|
const rev = reverseName(r.name);
|
|
if (rev) keys.add(rev.toLowerCase());
|
|
if (r.altNames) {
|
|
for (const part of r.altNames.split(/[,、,]/)) {
|
|
const t = part.trim().toLowerCase();
|
|
if (t) keys.add(t);
|
|
}
|
|
}
|
|
return { id: r.id, name: r.name, slug: r.slug, keys };
|
|
});
|
|
|
|
const findMatch = (q: string) => {
|
|
const lq = q.toLowerCase();
|
|
const lqRev = reverseName(q)?.toLowerCase() ?? null;
|
|
for (const r of indexed) {
|
|
if (r.keys.has(lq) || (lqRev && r.keys.has(lqRev))) {
|
|
return { id: r.id, name: r.name, slug: r.slug };
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
return trimmed.map((name) => ({ name, match: findMatch(name) }));
|
|
}
|