diff --git a/API/Controllers/SeriesController.cs b/API/Controllers/SeriesController.cs index 8c2a0ced0..c420a955f 100644 --- a/API/Controllers/SeriesController.cs +++ b/API/Controllers/SeriesController.cs @@ -322,7 +322,7 @@ public class SeriesController : BaseApiController [HttpPost("scan")] public ActionResult ScanSeries(RefreshSeriesDto refreshSeriesDto) { - _taskScheduler.ScanSeries(refreshSeriesDto.LibraryId, refreshSeriesDto.SeriesId, refreshSeriesDto.ForceUpdate); + _taskScheduler.ScanSeries(refreshSeriesDto.LibraryId, refreshSeriesDto.SeriesId, true); return Ok(); } diff --git a/API/Services/BookService.cs b/API/Services/BookService.cs index d03a44daa..54d2257ab 100644 --- a/API/Services/BookService.cs +++ b/API/Services/BookService.cs @@ -455,17 +455,32 @@ public class BookService : IBookService }; ComicInfo.CleanComicInfo(info); - foreach (var identifier in epubBook.Schema.Package.Metadata.Identifiers.Where(id => !string.IsNullOrEmpty(id.Scheme) && id.Scheme.Equals("ISBN"))) + var weblinks = new List(); + foreach (var identifier in epubBook.Schema.Package.Metadata.Identifiers) { if (string.IsNullOrEmpty(identifier.Identifier)) continue; - var isbn = identifier.Identifier.Replace("urn:isbn:", string.Empty).Replace("isbn:", string.Empty); - if (!ArticleNumberHelper.IsValidIsbn10(isbn) && !ArticleNumberHelper.IsValidIsbn13(isbn)) + if (!string.IsNullOrEmpty(identifier.Scheme) && identifier.Scheme.Equals("ISBN", StringComparison.InvariantCultureIgnoreCase)) { - _logger.LogDebug("[BookService] {File} has invalid ISBN number", filePath); - continue; + var isbn = identifier.Identifier.Replace("urn:isbn:", string.Empty).Replace("isbn:", string.Empty); + if (!ArticleNumberHelper.IsValidIsbn10(isbn) && !ArticleNumberHelper.IsValidIsbn13(isbn)) + { + _logger.LogDebug("[BookService] {File} has invalid ISBN number", filePath); + continue; + } + info.Isbn = isbn; } - info.Isbn = isbn; - break; + + if ((!string.IsNullOrEmpty(identifier.Scheme) && identifier.Scheme.Equals("URL", StringComparison.InvariantCultureIgnoreCase)) || + identifier.Identifier.StartsWith("url:")) + { + var url = identifier.Identifier.Replace("url:", string.Empty); + weblinks.Add(url.Trim()); + } + } + + if (weblinks.Count > 0) + { + info.Web = string.Join(',', weblinks.Distinct()); } // Parse tags not exposed via Library diff --git a/API/Services/Tasks/Scanner/ProcessSeries.cs b/API/Services/Tasks/Scanner/ProcessSeries.cs index bf634f6b6..6ad7f6100 100644 --- a/API/Services/Tasks/Scanner/ProcessSeries.cs +++ b/API/Services/Tasks/Scanner/ProcessSeries.cs @@ -36,7 +36,7 @@ public interface IProcessSeries void UpdateVolumes(Series series, IList parsedInfos, bool forceUpdate = false); void UpdateChapters(Series series, Volume volume, IList parsedInfos, bool forceUpdate = false); void AddOrUpdateFileForChapter(Chapter chapter, ParserInfo info, bool forceUpdate = false); - void UpdateChapterFromComicInfo(Chapter chapter, ComicInfo? comicInfo); + void UpdateChapterFromComicInfo(Chapter chapter, ComicInfo? comicInfo, bool forceUpdate = false); } /// @@ -534,11 +534,11 @@ public class ProcessSeries : IProcessSeries foreach (var chapter in volume.Chapters) { var firstFile = chapter.Files.MinBy(x => x.Chapter); - if (firstFile == null || _cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, firstFile)) continue; + if (firstFile == null || _cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, forceUpdate, firstFile)) continue; try { var firstChapterInfo = infos.SingleOrDefault(i => i.FullFilePath.Equals(firstFile.FilePath)); - UpdateChapterFromComicInfo(chapter, firstChapterInfo?.ComicInfo); + UpdateChapterFromComicInfo(chapter, firstChapterInfo?.ComicInfo, forceUpdate); } catch (Exception ex) { @@ -660,12 +660,12 @@ public class ProcessSeries : IProcessSeries } } - public void UpdateChapterFromComicInfo(Chapter chapter, ComicInfo? comicInfo) + public void UpdateChapterFromComicInfo(Chapter chapter, ComicInfo? comicInfo, bool forceUpdate = false) { if (comicInfo == null) return; var firstFile = chapter.Files.MinBy(x => x.Chapter); if (firstFile == null || - _cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, false, firstFile)) return; + _cacheHelper.IsFileUnmodifiedSinceCreationOrLastScan(chapter, forceUpdate, firstFile)) return; _logger.LogTrace("[ScannerService] Read ComicInfo for {File}", firstFile.FilePath); diff --git a/API/Services/Tasks/ScannerService.cs b/API/Services/Tasks/ScannerService.cs index 5569e8640..7f41f685a 100644 --- a/API/Services/Tasks/ScannerService.cs +++ b/API/Services/Tasks/ScannerService.cs @@ -258,7 +258,7 @@ public class ScannerService : IScannerService return; } - await _processSeries.ProcessSeriesAsync(parsedFiles, library); + await _processSeries.ProcessSeriesAsync(parsedFiles, library, bypassFolderOptimizationChecks); parsedSeries.Add(foundParsedSeries, parsedFiles); } diff --git a/UI/Web/src/app/_single-module/review-card/review-card.component.html b/UI/Web/src/app/_single-module/review-card/review-card.component.html index fd888e2a4..e665aaaaf 100644 --- a/UI/Web/src/app/_single-module/review-card/review-card.component.html +++ b/UI/Web/src/app/_single-module/review-card/review-card.component.html @@ -30,7 +30,7 @@ {{(isMyReview ? '' : review.username | defaultValue:'')}} - {{t('rating-percentage', {r: review.score})}}% + {{t('rating-percentage', {r: review.score})}} diff --git a/UI/Web/src/assets/langs/en.json b/UI/Web/src/assets/langs/en.json index da9894680..079e8ba93 100644 --- a/UI/Web/src/assets/langs/en.json +++ b/UI/Web/src/assets/langs/en.json @@ -951,7 +951,8 @@ "less-than-hour": "<1 Hour", "range-hours": "{{value}} {{hourWord}}", "hour": "Hour", - "hours": "Hours" + "hours": "Hours", + "read-time-title": "{{series-info-cards.read-time-title}}" }, "series-info-cards": { diff --git a/openapi.json b/openapi.json index 18abbc66e..b4cf725bd 100644 --- a/openapi.json +++ b/openapi.json @@ -7,7 +7,7 @@ "name": "GPL-3.0", "url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE" }, - "version": "0.7.6.2" + "version": "0.7.6.5" }, "servers": [ {