Reading List Detail Overhaul + More Bugfixes and Polish (#3687)

Co-authored-by: Yongun Seong <yseong.p@gmail.com>
This commit is contained in:
Joe Milazzo 2025-03-29 19:47:53 -05:00 committed by GitHub
parent b2ee651fb8
commit dad212bfb9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
71 changed files with 5056 additions and 729 deletions

View file

@ -222,6 +222,10 @@ public class MediaConversionService : IMediaConversionService
{
if (string.IsNullOrEmpty(series.CoverImage)) continue;
series.CoverImage = series.GetCoverImage();
if (series.CoverImage == null)
{
_logger.LogDebug("[SeriesCoverImageBug] Setting Series Cover Image to null: {SeriesId}", series.Id);
}
_unitOfWork.SeriesRepository.Update(series);
await _unitOfWork.CommitAsync();
}

View file

@ -199,6 +199,10 @@ public class MetadataService : IMetadataService
series.Volumes ??= [];
series.CoverImage = series.GetCoverImage();
if (series.CoverImage == null)
{
_logger.LogDebug("[SeriesCoverImageBug] Setting Series Cover Image to null: {SeriesId}", series.Id);
}
_imageService.UpdateColorScape(series);

View file

@ -76,7 +76,7 @@ public class ExternalMetadataService : IExternalMetadataService
};
// Allow 50 requests per 24 hours
private static readonly RateLimiter RateLimiter = new RateLimiter(50, TimeSpan.FromHours(24), false);
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,
ILicenseService licenseService, IScrobblingService scrobblingService, IEventHub eventHub, ICoverDbService coverDbService)
@ -115,18 +115,24 @@ public class ExternalMetadataService : IExternalMetadataService
// Find all Series that are eligible and limit
var ids = await _unitOfWork.ExternalSeriesMetadataRepository.GetSeriesThatNeedExternalMetadata(25, false);
if (ids.Count == 0) return;
ids = await _unitOfWork.ExternalSeriesMetadataRepository.GetSeriesThatNeedExternalMetadata(25, true);
_logger.LogInformation("[Kavita+ Data Refresh] Started Refreshing {Count} series data from Kavita+", ids.Count);
_logger.LogInformation("[Kavita+ Data Refresh] Started Refreshing {Count} series data from Kavita+: {Ids}", ids.Count, string.Join(',', ids));
var count = 0;
var successfulMatches = new List<int>();
var libTypes = await _unitOfWork.LibraryRepository.GetLibraryTypesBySeriesIdsAsync(ids);
foreach (var seriesId in ids)
{
var libraryType = libTypes[seriesId];
var success = await FetchSeriesMetadata(seriesId, libraryType);
if (success) count++;
if (success)
{
count++;
successfulMatches.Add(seriesId);
}
await Task.Delay(6000); // Currently AL is degraded and has 30 requests/min, give a little padding since this is a background request
}
_logger.LogInformation("[Kavita+ Data Refresh] Finished Refreshing {Count} series data from Kavita+", count);
_logger.LogInformation("[Kavita+ Data Refresh] Finished Refreshing {Count} / {Total} series data from Kavita+: {Ids}", count, ids.Count, string.Join(',', successfulMatches));
}
@ -146,7 +152,7 @@ public class ExternalMetadataService : IExternalMetadataService
if (!RateLimiter.TryAcquire(string.Empty))
{
// Request not allowed due to rate limit
_logger.LogDebug("Rate Limit hit for Kavita+ prefetch");
_logger.LogInformation("Rate Limit hit for Kavita+ prefetch");
return false;
}
@ -731,7 +737,7 @@ public class ExternalMetadataService : IExternalMetadataService
{
Name = w.Name,
AniListId = ScrobblingService.ExtractId<int>(w.Url, ScrobblingService.AniListCharacterWebsite),
Description = StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description)),
Description = StringHelper.CorrectUrls(StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description))),
})
.Concat(series.Metadata.People
.Where(p => p.Role == PersonRole.Character)
@ -743,7 +749,9 @@ public class ExternalMetadataService : IExternalMetadataService
.ToList();
if (characters.Count == 0) return false;
await SeriesService.HandlePeopleUpdateAsync(series.Metadata, characters, PersonRole.Character, _unitOfWork);
foreach (var spPerson in series.Metadata.People.Where(p => p.Role == PersonRole.Character))
{
// Set a sort order based on their role
@ -810,7 +818,7 @@ public class ExternalMetadataService : IExternalMetadataService
{
Name = w.Name,
AniListId = ScrobblingService.ExtractId<int>(w.Url, ScrobblingService.AniListStaffWebsite),
Description = StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description)),
Description = StringHelper.CorrectUrls(StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description))),
})
.Concat(series.Metadata.People
.Where(p => p.Role == PersonRole.CoverArtist)
@ -867,7 +875,7 @@ public class ExternalMetadataService : IExternalMetadataService
{
Name = w.Name,
AniListId = ScrobblingService.ExtractId<int>(w.Url, ScrobblingService.AniListStaffWebsite),
Description = StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description)),
Description = StringHelper.CorrectUrls(StringHelper.RemoveSourceInDescription(StringHelper.SquashBreaklines(w.Description))),
})
.Concat(series.Metadata.People
.Where(p => p.Role == PersonRole.Writer)

View file

@ -552,14 +552,22 @@ public class CoverDbService : ICoverDbService
series.CoverImage = filePath;
series.CoverImageLocked = true;
if (series.CoverImage == null)
{
_logger.LogDebug("[SeriesCoverImageBug] Setting Series Cover Image to null");
}
_imageService.UpdateColorScape(series);
_unitOfWork.SeriesRepository.Update(series);
}
}
else
{
series.CoverImage = string.Empty;
series.CoverImage = null;
series.CoverImageLocked = false;
if (series.CoverImage == null)
{
_logger.LogDebug("[SeriesCoverImageBug] Setting Series Cover Image to null");
}
_imageService.UpdateColorScape(series);
_unitOfWork.SeriesRepository.Update(series);
}

View file

@ -278,7 +278,8 @@ public partial class VersionUpdaterService : IVersionUpdaterService
{
// Attempt to fetch from cache
var cachedReleases = await TryGetCachedReleases();
if (cachedReleases != null)
// If there is a cached release and the current version is within it, use it, otherwise regenerate
if (cachedReleases != null && cachedReleases.Any(r => IsVersionEqual(r.UpdateVersion, BuildInfo.Version.ToString())))
{
if (count > 0)
{
@ -338,6 +339,29 @@ public partial class VersionUpdaterService : IVersionUpdaterService
return updateDtos;
}
/// <summary>
/// Compares 2 versions and ensures that the minor is always there
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
private static bool IsVersionEqual(string v1, string v2)
{
var versionParts = v1.Split('.');
if (versionParts.Length < 4)
{
v1 += ".0"; // Append missing parts
}
versionParts = v2.Split('.');
if (versionParts.Length < 4)
{
v2 += ".0"; // Append missing parts
}
return string.Equals(v2, v2, StringComparison.OrdinalIgnoreCase);
}
private async Task<IList<UpdateNotificationDto>?> TryGetCachedReleases()
{
if (!File.Exists(_cacheFilePath)) return null;
@ -370,7 +394,7 @@ public partial class VersionUpdaterService : IVersionUpdaterService
{
try
{
var json = System.Text.Json.JsonSerializer.Serialize(updates, JsonOptions);
var json = JsonSerializer.Serialize(updates, JsonOptions);
await File.WriteAllTextAsync(_cacheFilePath, json);
}
catch (Exception ex)