Ajoute ISBN, tris et nouveautés d'auteur

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
LIMONIER Mathieu
2026-08-20 13:49:08 +02:00
co-authored by Copilot
parent 359f4f59c6
commit 6b8f08ef26
10 changed files with 441 additions and 13 deletions
+62 -1
View File
@@ -45,10 +45,19 @@ public interface IBnfClient
string titre, string? auteur, CancellationToken ct = default);
}
/// <summary>
/// Extension de la recherche par auteur utilisée uniquement pour les nouveautés.
/// </summary>
public interface IBnfClientNouveautes
{
Task<(ResultatBibliographie Resultat, string? Avertissement)>
RechercherParAuteurNouveautesAsync(string auteur, CancellationToken ct = default);
}
/// <summary>
/// Client de l'API SRU du catalogue général de la BnF (gratuite, sans clé).
/// </summary>
public sealed class BnfClient(HttpClient http, ILogger<BnfClient> logger) : IBnfClient
public sealed class BnfClient(HttpClient http, ILogger<BnfClient> logger) : IBnfClient, IBnfClientNouveautes
{
/// <summary>Nom du client typé enregistré dans <c>IHttpClientFactory</c>.</summary>
public const string NomHttpClient = "bnf";
@@ -211,6 +220,12 @@ public sealed class BnfClient(HttpClient http, ILogger<BnfClient> logger) : IBnf
public const int NoticesParPage = 100;
public const int PagesMaximum = 2;
public const int PagesMaximumNouveautes = 10;
public static int NombrePagesNouveautes(int nombreAnnonce) =>
Math.Min(
PagesMaximumNouveautes,
Math.Max(1, (nombreAnnonce + NoticesParPage - 1) / NoticesParPage));
public async Task<(ResultatBibliographie Resultat, string? Avertissement)> RechercherParAuteurAsync(
string auteur, CancellationToken ct = default)
@@ -257,6 +272,52 @@ public sealed class BnfClient(HttpClient http, ILogger<BnfClient> logger) : IBnf
}
}
public async Task<(ResultatBibliographie Resultat, string? Avertissement)>
RechercherParAuteurNouveautesAsync(string auteur, CancellationToken ct = default)
{
if (string.IsNullOrWhiteSpace(auteur))
{
return (new ResultatBibliographie(), null);
}
try
{
var premiere = await LirePageAsync(auteur, 1, ct);
if (premiere is null)
{
return Echec(EtatSourceBibliographie.Injoignable, auteur);
}
var nombrePages = NombrePagesNouveautes(premiere.NombreAnnonce);
var pages = new List<ResultatBibliographie> { premiere };
if (nombrePages > 1)
{
var suivantes = await Task.WhenAll(
Enumerable.Range(1, nombrePages - 1)
.Select(i => LirePageAsync(auteur, (i * NoticesParPage) + 1, ct)));
pages.AddRange(suivantes.Where(p => p is not null).Select(p => p!));
}
return (Fusionner(pages), null);
}
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
logger.LogWarning(ex, "Délai dépassé par la BnF pour les nouveautés de {Auteur}", auteur);
return Echec(EtatSourceBibliographie.DelaiDepasse, auteur);
}
catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException)
{
logger.LogWarning(ex, "BnF injoignable pour les nouveautés de {Auteur}", auteur);
return Echec(EtatSourceBibliographie.Injoignable, auteur);
}
catch (System.Xml.XmlException ex)
{
logger.LogWarning(ex, "Réponse BnF illisible pour les nouveautés de {Auteur}", auteur);
return Echec(EtatSourceBibliographie.ReponseIllisible, auteur);
}
}
/// <summary>
/// Motif <b>lisible</b> d'une bibliographie que la BnF n'a pas pu fournir.
/// </summary>