fix(api): robustesse des providers de métadonnées
Recherche ISBN directe sur Open Library avec repli titre/auteur, normalisation des réponses, timeouts et User-Agent explicites sur les trois providers distants, abandon de l'extraction de jaquette CBR en échec silencieux (fallback métadonnées seules), tests des providers et garde du test de migration si better-sqlite3 est indisponible. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1,17 +1,20 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { MetadataLookup, MetadataMatch, MetadataProvider, MetadataProviderConfig } from "../metadata.types.js";
|
||||
import { toIsbn13 } from "../use-cases/extract-identifiers.js";
|
||||
|
||||
@Injectable()
|
||||
export class GoogleBooksProvider implements MetadataProvider {
|
||||
readonly id = "googlebooks" as const;
|
||||
|
||||
async lookup(lookup: MetadataLookup, config: MetadataProviderConfig): Promise<MetadataMatch | null> {
|
||||
const query = lookup.identifiers.isbn13
|
||||
? `isbn:${lookup.identifiers.isbn13}`
|
||||
const isbn = lookup.identifiers.isbn13 ?? lookup.identifiers.isbn10;
|
||||
const query = isbn
|
||||
? `isbn:${isbn}`
|
||||
: `intitle:${lookup.title}${lookup.author ? `+inauthor:${lookup.author}` : ""}`;
|
||||
const url = new URL("https://www.googleapis.com/books/v1/volumes");
|
||||
url.searchParams.set("q", query);
|
||||
url.searchParams.set("maxResults", "1");
|
||||
url.searchParams.set("printType", "books");
|
||||
if (config.apiKey) url.searchParams.set("key", config.apiKey);
|
||||
|
||||
const response = await fetch(url, { signal: AbortSignal.timeout(4000) });
|
||||
@ -26,7 +29,7 @@ export class GoogleBooksProvider implements MetadataProvider {
|
||||
language: stringValue(info.language),
|
||||
publisher: stringValue(info.publisher),
|
||||
publishedDate: stringValue(info.publishedDate),
|
||||
isbn: isbnFromIndustryIdentifiers(info.industryIdentifiers)
|
||||
isbn: isbnFromIndustryIdentifiers(info.industryIdentifiers, lookup.identifiers.isbn13)
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -39,9 +42,12 @@ function arrayJoin(value: unknown): string | null {
|
||||
return Array.isArray(value) && value.length ? value.map(String).join(", ") : null;
|
||||
}
|
||||
|
||||
function isbnFromIndustryIdentifiers(value: unknown): string | null {
|
||||
function isbnFromIndustryIdentifiers(value: unknown, expectedIsbn13: string | null): string | null {
|
||||
if (!Array.isArray(value)) return null;
|
||||
const isbn13 = value.find((entry) => entry?.type === "ISBN_13")?.identifier;
|
||||
const isbn10 = value.find((entry) => entry?.type === "ISBN_10")?.identifier;
|
||||
const entries = value as Array<{ type?: unknown; identifier?: unknown }>;
|
||||
const matching = entries.find((entry) => toIsbn13(stringValue(entry.identifier) ?? "") === expectedIsbn13)?.identifier;
|
||||
if (matching) return stringValue(matching);
|
||||
const isbn13 = entries.find((entry) => entry.type === "ISBN_13")?.identifier;
|
||||
const isbn10 = entries.find((entry) => entry.type === "ISBN_10")?.identifier;
|
||||
return stringValue(isbn13) ?? stringValue(isbn10);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user