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>
This commit is contained in:
38
apps/api/src/metadata/adapters/bnf.provider.ts
Normal file
38
apps/api/src/metadata/adapters/bnf.provider.ts
Normal file
@ -0,0 +1,38 @@
|
||||
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];
|
||||
}
|
||||
Reference in New Issue
Block a user