IsEmpty Filter and other small fixes (#3142)

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-09-13 15:15:01 -07:00 committed by GitHub
parent e574caf7eb
commit 07a36176de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
96 changed files with 1361 additions and 1135 deletions

View file

@ -7,6 +7,7 @@ using API.Extensions;
using API.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace API.Controllers;
@ -31,16 +32,17 @@ public class CblController : BaseApiController
/// If this returns errors, the cbl will always be rejected by Kavita.
/// </summary>
/// <param name="cbl">FormBody with parameter name of cbl</param>
/// <param name="comicVineMatching">Use comic vine matching or not. Defaults to false</param>
/// <param name="useComicVineMatching">Use comic vine matching or not. Defaults to false</param>
/// <returns></returns>
[HttpPost("validate")]
public async Task<ActionResult<CblImportSummaryDto>> ValidateCbl(IFormFile cbl, [FromQuery] bool comicVineMatching = false)
[SwaggerIgnore]
public async Task<ActionResult<CblImportSummaryDto>> ValidateCbl(IFormFile cbl, [FromQuery] bool useComicVineMatching = false)
{
var userId = User.GetUserId();
try
{
var cblReadingList = await SaveAndLoadCblFile(cbl);
var importSummary = await _readingListService.ValidateCblFile(userId, cblReadingList, comicVineMatching);
var importSummary = await _readingListService.ValidateCblFile(userId, cblReadingList, useComicVineMatching);
importSummary.FileName = cbl.FileName;
return Ok(importSummary);
}
@ -82,16 +84,17 @@ public class CblController : BaseApiController
/// </summary>
/// <param name="cbl">FormBody with parameter name of cbl</param>
/// <param name="dryRun">If true, will only emulate the import but not perform. This should be done to preview what will happen</param>
/// <param name="comicVineMatching">Use comic vine matching or not. Defaults to false</param>
/// <param name="useComicVineMatching">Use comic vine matching or not. Defaults to false</param>
/// <returns></returns>
[HttpPost("import")]
public async Task<ActionResult<CblImportSummaryDto>> ImportCbl(IFormFile cbl, [FromQuery] bool dryRun = false, [FromQuery] bool comicVineMatching = false)
[SwaggerIgnore]
public async Task<ActionResult<CblImportSummaryDto>> ImportCbl(IFormFile cbl, [FromQuery] bool dryRun = false, [FromQuery] bool useComicVineMatching = false)
{
try
{
var userId = User.GetUserId();
var cblReadingList = await SaveAndLoadCblFile(cbl);
var importSummary = await _readingListService.CreateReadingListFromCbl(userId, cblReadingList, dryRun, comicVineMatching);
var importSummary = await _readingListService.CreateReadingListFromCbl(userId, cblReadingList, dryRun, useComicVineMatching);
importSummary.FileName = cbl.FileName;
return Ok(importSummary);

View file

@ -19,6 +19,7 @@ using API.Services.Tasks.Scanner;
using API.SignalR;
using AutoMapper;
using EasyCaching.Core;
using Hangfire;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
@ -132,13 +133,19 @@ public class LibraryController : BaseApiController
if (!await _unitOfWork.CommitAsync()) return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-library"));
await _libraryWatcher.RestartWatching();
await _taskScheduler.ScanLibrary(library.Id);
await _libraryCacheProvider.RemoveByPrefixAsync(CacheKey);
if (library.FolderWatching)
{
await _libraryWatcher.RestartWatching();
}
BackgroundJob.Enqueue(() => _taskScheduler.ScanLibrary(library.Id, false));
await _eventHub.SendMessageAsync(MessageFactory.LibraryModified,
MessageFactory.LibraryModifiedEvent(library.Id, "create"), false);
await _eventHub.SendMessageAsync(MessageFactory.SideNavUpdate,
MessageFactory.SideNavUpdateEvent(User.GetUserId()), false);
await _libraryCacheProvider.RemoveByPrefixAsync(CacheKey);
return Ok();
}
@ -409,7 +416,7 @@ public class LibraryController : BaseApiController
_taskScheduler.CleanupChapters(chapterIds);
}
await _libraryWatcher.RestartWatching();
BackgroundJob.Enqueue(() => _libraryWatcher.RestartWatching());
foreach (var seriesId in seriesIds)
{
@ -496,16 +503,17 @@ public class LibraryController : BaseApiController
_unitOfWork.LibraryRepository.Update(library);
if (!await _unitOfWork.CommitAsync()) return BadRequest(await _localizationService.Translate(userId, "generic-library-update"));
if (folderWatchingUpdate || originalFoldersCount != dto.Folders.Count() || typeUpdate)
{
BackgroundJob.Enqueue(() => _libraryWatcher.RestartWatching());
}
if (originalFoldersCount != dto.Folders.Count() || typeUpdate)
{
await _libraryWatcher.RestartWatching();
await _taskScheduler.ScanLibrary(library.Id);
}
if (folderWatchingUpdate)
{
await _libraryWatcher.RestartWatching();
}
await _eventHub.SendMessageAsync(MessageFactory.LibraryModified,
MessageFactory.LibraryModifiedEvent(library.Id, "update"), false);

View file

@ -873,6 +873,7 @@ public class OpdsController : BaseApiController
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"{baseUrl}api/image/series-cover?seriesId={seriesId}&apiKey={apiKey}"));
var chapterDict = new Dictionary<int, short>();
var fileDict = new Dictionary<int, short>();
var seriesDetail = await _seriesService.GetSeriesDetail(seriesId, userId);
foreach (var volume in seriesDetail.Volumes)
{
@ -881,12 +882,14 @@ public class OpdsController : BaseApiController
foreach (var chapter in chaptersForVolume)
{
var chapterId = chapter.Id;
if (chapterDict.ContainsKey(chapterId)) continue;
if (!chapterDict.TryAdd(chapterId, 0)) continue;
var chapterDto = _mapper.Map<ChapterDto>(chapter);
foreach (var mangaFile in chapter.Files)
{
chapterDict.Add(chapterId, 0);
// If a chapter has multiple files that are within one chapter, this dict prevents duplicate key exception
if (!fileDict.TryAdd(mangaFile.Id, 0)) continue;
feed.Entries.Add(await CreateChapterWithFile(userId, seriesId, volume.Id, chapterId, _mapper.Map<MangaFileDto>(mangaFile), series,
chapterDto, apiKey, prefix, baseUrl));
}
@ -905,6 +908,8 @@ public class OpdsController : BaseApiController
var chapterDto = _mapper.Map<ChapterDto>(chapter);
foreach (var mangaFile in files)
{
// If a chapter has multiple files that are within one chapter, this dict prevents duplicate key exception
if (!fileDict.TryAdd(mangaFile.Id, 0)) continue;
feed.Entries.Add(await CreateChapterWithFile(userId, seriesId, chapter.VolumeId, chapter.Id, _mapper.Map<MangaFileDto>(mangaFile), series,
chapterDto, apiKey, prefix, baseUrl));
}
@ -916,6 +921,9 @@ public class OpdsController : BaseApiController
var chapterDto = _mapper.Map<ChapterDto>(special);
foreach (var mangaFile in files)
{
// If a chapter has multiple files that are within one chapter, this dict prevents duplicate key exception
if (!fileDict.TryAdd(mangaFile.Id, 0)) continue;
feed.Entries.Add(await CreateChapterWithFile(userId, seriesId, special.VolumeId, special.Id, _mapper.Map<MangaFileDto>(mangaFile), series,
chapterDto, apiKey, prefix, baseUrl));
}

View file

@ -46,6 +46,7 @@ public class PluginController(IUnitOfWork unitOfWork, ITokenService tokenService
}
var user = await unitOfWork.UserRepository.GetUserByIdAsync(userId);
logger.LogInformation("Plugin {PluginName} has authenticated with {UserName} ({UserId})'s API Key", pluginName.Replace(Environment.NewLine, string.Empty), user!.UserName, userId);
return new UserDto
{
Username = user.UserName!,

View file

@ -319,11 +319,12 @@ public class SeriesController : BaseApiController
/// <param name="libraryId"></param>
/// <returns></returns>
[HttpPost("all-v2")]
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetAllSeriesV2(FilterV2Dto filterDto, [FromQuery] UserParams userParams, [FromQuery] int libraryId = 0)
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetAllSeriesV2(FilterV2Dto filterDto, [FromQuery] UserParams userParams,
[FromQuery] int libraryId = 0, [FromQuery] QueryContext context = QueryContext.None)
{
var userId = User.GetUserId();
var series =
await _unitOfWork.SeriesRepository.GetSeriesDtoForLibraryIdV2Async(userId, userParams, filterDto);
await _unitOfWork.SeriesRepository.GetSeriesDtoForLibraryIdV2Async(userId, userParams, filterDto, context);
// Apply progress/rating information (I can't work out how to do this in initial query)
if (series == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-series"));

View file

@ -277,4 +277,16 @@ public class ServerController : BaseApiController
return Ok();
}
/// <summary>
/// Runs the Sync Themes task
/// </summary>
/// <returns></returns>
[Authorize("RequireAdminRole")]
[HttpPost("sync-themes")]
public async Task<ActionResult> SyncThemes()
{
await _taskScheduler.SyncThemes();
return Ok();
}
}

View file

@ -23,6 +23,7 @@ using Kavita.Common.Helpers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Swashbuckle.AspNetCore.Annotations;
namespace API.Controllers;
@ -370,7 +371,7 @@ public class SettingsController : BaseApiController
return Ok(updateSettingsDto);
}
public void UpdateBookmarkDirectory(string originalBookmarkDirectory, string bookmarkDirectory)
private void UpdateBookmarkDirectory(string originalBookmarkDirectory, string bookmarkDirectory)
{
_directoryService.ExistOrCreate(bookmarkDirectory);
_directoryService.CopyDirectoryToDirectory(originalBookmarkDirectory, bookmarkDirectory);