Files
ReadaBook/apps/api/src/metadata/adapters/bnf.provider.ts
Git Agent 48e9459cf3 feat(api,shared): métadonnées multi-providers et automatisation des scans/enrichissements
Chaîne de résolution metadata (local, Open Library, Google Books, BNF)
avec activation/priorité/clé API par provider, colonnes isbn13 et
identifiers sur les livres, et intégration au scanner pour compléter
métadonnées et jaquettes manquantes. Module automation: réglages
persistés, planifications scan/enrichissement et déclenchement manuel,
exposés via des endpoints admin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-23 13:10:45 +02:00

39 lines
1.6 KiB
TypeScript

import { Injectable } from "@nestjs/common";
import { XMLParser } from "fast-xml-parser";
import { MetadataLookup, MetadataMatch, MetadataProvider, MetadataProviderConfig } from "../metadata.types.js";
const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: "@_" });
@Injectable()
export class BnfProvider implements MetadataProvider {
readonly id = "bnf" as const;
async lookup(lookup: MetadataLookup, _config: MetadataProviderConfig): Promise<MetadataMatch | null> {
const query = lookup.identifiers.isbn13
? `bib.isbn all "${lookup.identifiers.isbn13}"`
: `bib.title all "${lookup.title.replace(/"/g, " ")}"`;
const url = new URL("https://catalogue.bnf.fr/api/SRU");
url.searchParams.set("version", "1.2");
url.searchParams.set("operation", "searchRetrieve");
url.searchParams.set("query", query);
url.searchParams.set("maximumRecords", "1");
const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
if (!response.ok) return null;
const parsed = parser.parse(await response.text());
const record = parsed?.searchRetrieveResponse?.records?.record?.recordData;
if (!record) return null;
const text = JSON.stringify(record);
return {
title: match(text, /"titleInfo"[^}]*"title":"([^"]+)"/),
author: match(text, /"namePart":"([^"]+)"/),
publisher: match(text, /"publisher":"([^"]+)"/),
publishedDate: match(text, /"dateIssued":"([^"]+)"/)
};
}
}
function match(value: string, pattern: RegExp): string | undefined {
return value.match(pattern)?.[1];
}