Refactored some apis to the new KavitaPlusApiService.
This commit is contained in:
parent
09d9edd828
commit
224e839dad
6 changed files with 75 additions and 40 deletions
|
|
@ -6,7 +6,7 @@ namespace API.DTOs.KavitaPlus.ExternalMetadata;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for matching and fetching metadata on a series
|
/// Used for matching and fetching metadata on a series
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed record ExternalMetadataIdsDto
|
public sealed record ExternalMetadataIdsDto
|
||||||
{
|
{
|
||||||
public long? MalId { get; set; }
|
public long? MalId { get; set; }
|
||||||
public int? AniListId { get; set; }
|
public int? AniListId { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace API.DTOs.KavitaPlus.ExternalMetadata;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a request to match some series from Kavita to an external id which K+ uses.
|
/// Represents a request to match some series from Kavita to an external id which K+ uses.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed record MatchSeriesRequestDto
|
public sealed record MatchSeriesRequestDto
|
||||||
{
|
{
|
||||||
public required string SeriesName { get; set; }
|
public required string SeriesName { get; set; }
|
||||||
public ICollection<string> AlternativeNames { get; set; } = [];
|
public ICollection<string> AlternativeNames { get; set; } = [];
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ using API.DTOs.SeriesDetail;
|
||||||
|
|
||||||
namespace API.DTOs.KavitaPlus.ExternalMetadata;
|
namespace API.DTOs.KavitaPlus.ExternalMetadata;
|
||||||
|
|
||||||
internal sealed record SeriesDetailPlusApiDto
|
public sealed record SeriesDetailPlusApiDto
|
||||||
{
|
{
|
||||||
public IEnumerable<MediaRecommendationDto> Recommendations { get; set; }
|
public IEnumerable<MediaRecommendationDto> Recommendations { get; set; }
|
||||||
public IEnumerable<UserReviewDto> Reviews { get; set; }
|
public IEnumerable<UserReviewDto> Reviews { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
private readonly IScrobblingService _scrobblingService;
|
private readonly IScrobblingService _scrobblingService;
|
||||||
private readonly IEventHub _eventHub;
|
private readonly IEventHub _eventHub;
|
||||||
private readonly ICoverDbService _coverDbService;
|
private readonly ICoverDbService _coverDbService;
|
||||||
|
private readonly IKavitaPlusApiService _kavitaPlusApiService;
|
||||||
private readonly TimeSpan _externalSeriesMetadataCache = TimeSpan.FromDays(30);
|
private readonly TimeSpan _externalSeriesMetadataCache = TimeSpan.FromDays(30);
|
||||||
public static readonly HashSet<LibraryType> NonEligibleLibraryTypes =
|
public static readonly HashSet<LibraryType> NonEligibleLibraryTypes =
|
||||||
[LibraryType.Comic, LibraryType.Book, LibraryType.Image];
|
[LibraryType.Comic, LibraryType.Book, LibraryType.Image];
|
||||||
|
|
@ -82,7 +83,8 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
private static bool IsRomanCharacters(string input) => Regex.IsMatch(input, @"^[\p{IsBasicLatin}\p{IsLatin-1Supplement}]+$");
|
private static bool IsRomanCharacters(string input) => Regex.IsMatch(input, @"^[\p{IsBasicLatin}\p{IsLatin-1Supplement}]+$");
|
||||||
|
|
||||||
public ExternalMetadataService(IUnitOfWork unitOfWork, ILogger<ExternalMetadataService> logger, IMapper mapper,
|
public ExternalMetadataService(IUnitOfWork unitOfWork, ILogger<ExternalMetadataService> logger, IMapper mapper,
|
||||||
ILicenseService licenseService, IScrobblingService scrobblingService, IEventHub eventHub, ICoverDbService coverDbService)
|
ILicenseService licenseService, IScrobblingService scrobblingService, IEventHub eventHub, ICoverDbService coverDbService,
|
||||||
|
IKavitaPlusApiService kavitaPlusApiService)
|
||||||
{
|
{
|
||||||
_unitOfWork = unitOfWork;
|
_unitOfWork = unitOfWork;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
@ -91,6 +93,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
_scrobblingService = scrobblingService;
|
_scrobblingService = scrobblingService;
|
||||||
_eventHub = eventHub;
|
_eventHub = eventHub;
|
||||||
_coverDbService = coverDbService;
|
_coverDbService = coverDbService;
|
||||||
|
_kavitaPlusApiService = kavitaPlusApiService;
|
||||||
|
|
||||||
FlurlConfiguration.ConfigureClientForUrl(Configuration.KavitaPlusApiUrl);
|
FlurlConfiguration.ConfigureClientForUrl(Configuration.KavitaPlusApiUrl);
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +182,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
_logger.LogDebug("Fetching Kavita+ for MAL Stacks for user {UserName}", user.MalUserName);
|
_logger.LogDebug("Fetching Kavita+ for MAL Stacks for user {UserName}", user.MalUserName);
|
||||||
|
|
||||||
var license = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
var license = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
||||||
var result = await ($"{Configuration.KavitaPlusApiUrl}/api/metadata/v2/stacks?username={user.MalUserName}")
|
var result = await _kavitaPlusApiService.GetMalStacks(user.MalUserName, license);
|
||||||
.WithKavitaPlusHeaders(license)
|
|
||||||
.GetJsonAsync<IList<MalStackDto>>();
|
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
|
|
@ -207,7 +208,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<IList<ExternalSeriesMatchDto>> MatchSeries(MatchSeriesDto dto)
|
public async Task<IList<ExternalSeriesMatchDto>> MatchSeries(MatchSeriesDto dto)
|
||||||
{
|
{
|
||||||
var license = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
|
||||||
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(dto.SeriesId,
|
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(dto.SeriesId,
|
||||||
SeriesIncludes.Metadata | SeriesIncludes.ExternalMetadata | SeriesIncludes.Library);
|
SeriesIncludes.Metadata | SeriesIncludes.ExternalMetadata | SeriesIncludes.Library);
|
||||||
if (series == null) return [];
|
if (series == null) return [];
|
||||||
|
|
@ -239,14 +240,9 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
MalId = potentialMalId ?? ScrobblingService.GetMalId(series)
|
MalId = potentialMalId ?? ScrobblingService.GetMalId(series)
|
||||||
};
|
};
|
||||||
|
|
||||||
var token = (await _unitOfWork.UserRepository.GetDefaultAdminUser()).AniListAccessToken;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var results = await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/match-series")
|
var results = await _kavitaPlusApiService.MatchSeries(matchRequest);
|
||||||
.WithKavitaPlusHeaders(license, token)
|
|
||||||
.PostJsonAsync(matchRequest)
|
|
||||||
.ReceiveJson<IList<ExternalSeriesMatchDto>>();
|
|
||||||
|
|
||||||
// Some summaries can contain multiple <br/>s, we need to ensure it's only 1
|
// Some summaries can contain multiple <br/>s, we need to ensure it's only 1
|
||||||
foreach (var result in results)
|
foreach (var result in results)
|
||||||
|
|
@ -287,9 +283,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is for the Series drawer. We can get this extra information during the initial SeriesDetail call so it's all coming from the DB
|
// This is for the Series drawer. We can get this extra information during the initial SeriesDetail call so it's all coming from the DB
|
||||||
|
var details = await GetSeriesDetail(aniListId, malId, seriesId);
|
||||||
var license = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
|
||||||
var details = await GetSeriesDetail(license, aniListId, malId, seriesId);
|
|
||||||
|
|
||||||
return details;
|
return details;
|
||||||
|
|
||||||
|
|
@ -442,16 +436,12 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Fetching Kavita+ Series Detail data for {SeriesName}", string.IsNullOrEmpty(data.SeriesName) ? data.AniListId : data.SeriesName);
|
_logger.LogDebug("Fetching Kavita+ Series Detail data for {SeriesName}", string.IsNullOrEmpty(data.SeriesName) ? data.AniListId : data.SeriesName);
|
||||||
var license = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
|
||||||
var token = (await _unitOfWork.UserRepository.GetDefaultAdminUser()).AniListAccessToken;
|
|
||||||
SeriesDetailPlusApiDto? result = null;
|
SeriesDetailPlusApiDto? result = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/series-detail")
|
// This returns an AniListSeries and Match returns ExternalSeriesDto
|
||||||
.WithKavitaPlusHeaders(license, token)
|
result = await _kavitaPlusApiService .GetSeriesDetail(data);
|
||||||
.PostJsonAsync(data)
|
|
||||||
.ReceiveJson<SeriesDetailPlusApiDto>(); // This returns an AniListSeries and Match returns ExternalSeriesDto
|
|
||||||
}
|
}
|
||||||
catch (FlurlHttpException ex)
|
catch (FlurlHttpException ex)
|
||||||
{
|
{
|
||||||
|
|
@ -466,11 +456,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
_logger.LogDebug("Hit rate limit, will retry in 3 seconds");
|
_logger.LogDebug("Hit rate limit, will retry in 3 seconds");
|
||||||
await Task.Delay(3000);
|
await Task.Delay(3000);
|
||||||
|
|
||||||
result = await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/series-detail")
|
result = await _kavitaPlusApiService.GetSeriesDetail(data);
|
||||||
.WithKavitaPlusHeaders(license, token)
|
|
||||||
.PostJsonAsync(data)
|
|
||||||
.ReceiveJson<
|
|
||||||
SeriesDetailPlusApiDto>();
|
|
||||||
}
|
}
|
||||||
else if (errorMessage.Contains("Unknown Series"))
|
else if (errorMessage.Contains("Unknown Series"))
|
||||||
{
|
{
|
||||||
|
|
@ -1777,7 +1763,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
/// <param name="malId"></param>
|
/// <param name="malId"></param>
|
||||||
/// <param name="seriesId"></param>
|
/// <param name="seriesId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<ExternalSeriesDetailDto?> GetSeriesDetail(string license, int? aniListId, long? malId, int? seriesId)
|
private async Task<ExternalSeriesDetailDto?> GetSeriesDetail(int? aniListId, long? malId, int? seriesId)
|
||||||
{
|
{
|
||||||
var payload = new ExternalMetadataIdsDto()
|
var payload = new ExternalMetadataIdsDto()
|
||||||
{
|
{
|
||||||
|
|
@ -1809,11 +1795,7 @@ public class ExternalMetadataService : IExternalMetadataService
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var token = (await _unitOfWork.UserRepository.GetDefaultAdminUser()).AniListAccessToken;
|
var ret = await _kavitaPlusApiService.GetSeriesDetailById(payload);
|
||||||
var ret = await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/series-by-ids")
|
|
||||||
.WithKavitaPlusHeaders(license, token)
|
|
||||||
.PostJsonAsync(payload)
|
|
||||||
.ReceiveJson<ExternalSeriesDetailDto>();
|
|
||||||
|
|
||||||
ret.Summary = StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(ret.Summary));
|
ret.Summary = StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(ret.Summary));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using API.Data;
|
||||||
|
using API.DTOs.Collection;
|
||||||
|
using API.DTOs.KavitaPlus.ExternalMetadata;
|
||||||
|
using API.DTOs.KavitaPlus.Metadata;
|
||||||
|
using API.DTOs.Metadata.Matching;
|
||||||
using API.DTOs.Scrobbling;
|
using API.DTOs.Scrobbling;
|
||||||
|
using API.Entities.Enums;
|
||||||
using API.Extensions;
|
using API.Extensions;
|
||||||
using Flurl.Http;
|
using Flurl.Http;
|
||||||
using Kavita.Common;
|
using Kavita.Common;
|
||||||
|
|
@ -17,9 +24,13 @@ public interface IKavitaPlusApiService
|
||||||
Task<bool> HasTokenExpired(string license, string token, ScrobbleProvider provider);
|
Task<bool> HasTokenExpired(string license, string token, ScrobbleProvider provider);
|
||||||
Task<int> GetRateLimit(string license, string token);
|
Task<int> GetRateLimit(string license, string token);
|
||||||
Task<ScrobbleResponseDto> PostScrobbleUpdate(ScrobbleDto data, string license);
|
Task<ScrobbleResponseDto> PostScrobbleUpdate(ScrobbleDto data, string license);
|
||||||
|
Task<IList<MalStackDto>> GetMalStacks(string malUsername, string license);
|
||||||
|
Task<IList<ExternalSeriesMatchDto>> MatchSeries(MatchSeriesRequestDto request);
|
||||||
|
Task<SeriesDetailPlusApiDto> GetSeriesDetail(PlusSeriesRequestDto request);
|
||||||
|
Task<ExternalSeriesDetailDto> GetSeriesDetailById(ExternalMetadataIdsDto request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KavitaPlusApiService(ILogger<KavitaPlusApiService> logger): IKavitaPlusApiService
|
public class KavitaPlusApiService(ILogger<KavitaPlusApiService> logger, IUnitOfWork unitOfWork): IKavitaPlusApiService
|
||||||
{
|
{
|
||||||
private const string ScrobblingPath = "/api/scrobbling/";
|
private const string ScrobblingPath = "/api/scrobbling/";
|
||||||
|
|
||||||
|
|
@ -42,6 +53,46 @@ public class KavitaPlusApiService(ILogger<KavitaPlusApiService> logger): IKavita
|
||||||
return await PostAndReceive<ScrobbleResponseDto>(ScrobblingPath + "update", data, license);
|
return await PostAndReceive<ScrobbleResponseDto>(ScrobblingPath + "update", data, license);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IList<MalStackDto>> GetMalStacks(string malUsername, string license)
|
||||||
|
{
|
||||||
|
return await $"{Configuration.KavitaPlusApiUrl}/api/metadata/v2/stacks?username={malUsername}"
|
||||||
|
.WithKavitaPlusHeaders(license)
|
||||||
|
.GetJsonAsync<IList<MalStackDto>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IList<ExternalSeriesMatchDto>> MatchSeries(MatchSeriesRequestDto request)
|
||||||
|
{
|
||||||
|
var license = (await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
||||||
|
var token = (await unitOfWork.UserRepository.GetDefaultAdminUser()).AniListAccessToken;
|
||||||
|
|
||||||
|
return await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/match-series")
|
||||||
|
.WithKavitaPlusHeaders(license, token)
|
||||||
|
.PostJsonAsync(request)
|
||||||
|
.ReceiveJson<IList<ExternalSeriesMatchDto>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SeriesDetailPlusApiDto> GetSeriesDetail(PlusSeriesRequestDto request)
|
||||||
|
{
|
||||||
|
var license = (await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
||||||
|
var token = (await unitOfWork.UserRepository.GetDefaultAdminUser()).AniListAccessToken;
|
||||||
|
|
||||||
|
return await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/series-detail")
|
||||||
|
.WithKavitaPlusHeaders(license, token)
|
||||||
|
.PostJsonAsync(request)
|
||||||
|
.ReceiveJson<SeriesDetailPlusApiDto>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ExternalSeriesDetailDto> GetSeriesDetailById(ExternalMetadataIdsDto request)
|
||||||
|
{
|
||||||
|
var license = (await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.LicenseKey)).Value;
|
||||||
|
var token = (await unitOfWork.UserRepository.GetDefaultAdminUser()).AniListAccessToken;
|
||||||
|
|
||||||
|
return await (Configuration.KavitaPlusApiUrl + "/api/metadata/v2/series-by-ids")
|
||||||
|
.WithKavitaPlusHeaders(license, token)
|
||||||
|
.PostJsonAsync(request)
|
||||||
|
.ReceiveJson<ExternalSeriesDetailDto>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a GET request to K+
|
/// Send a GET request to K+
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -74,12 +74,14 @@ export class ManageMatchedMetadataComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.messageHub.messages$.subscribe(message => {
|
this.messageHub.messages$.subscribe(message => {
|
||||||
if (message.event !== EVENTS.ScanSeries) return;
|
if (message.event == EVENTS.ScanSeries) {
|
||||||
|
const evt = message.payload as ScanSeriesEvent;
|
||||||
const evt = message.payload as ScanSeriesEvent;
|
if (this.data.filter(d => d.series.id === evt.seriesId).length > 0) {
|
||||||
if (this.data.filter(d => d.series.id === evt.seriesId).length > 0) {
|
this.loadData();
|
||||||
this.loadData();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.filterGroup.valueChanges.pipe(
|
this.filterGroup.valueChanges.pipe(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue