diff --git a/.github/workflows/release-workflow.yml b/.github/workflows/release-workflow.yml.backup similarity index 84% rename from .github/workflows/release-workflow.yml rename to .github/workflows/release-workflow.yml.backup index 36532db40..ed4fb581b 100644 --- a/.github/workflows/release-workflow.yml +++ b/.github/workflows/release-workflow.yml.backup @@ -155,21 +155,3 @@ jobs: - name: Image digest run: echo ${{ steps.docker_build_nightly.outputs.digest }} - - - name: Notify Discord - uses: rjstone/discord-webhook-notify@v1 - with: - severity: info - description: v${{steps.get-version.outputs.assembly-version}} - ${{ steps.findPr.outputs.title }} - details: '${{ steps.findPr.outputs.body }}' - text: <@&939225192553644133> A new stable build has been released. - webhookUrl: ${{ secrets.DISCORD_DOCKER_UPDATE_URL }} - - - name: Notify Discord - uses: rjstone/discord-webhook-notify@v1 - with: - severity: info - description: v${{steps.get-version.outputs.assembly-version}} - ${{ steps.findPr.outputs.title }} - details: '${{ steps.findPr.outputs.body }}' - text: <@&939225459156217917> <@&939225350775406643> A new nightly build has been released for docker. - webhookUrl: ${{ secrets.DISCORD_DOCKER_UPDATE_URL }} diff --git a/API/API.csproj b/API/API.csproj index 994bbc46f..3cd3513b8 100644 --- a/API/API.csproj +++ b/API/API.csproj @@ -13,6 +13,7 @@ + diff --git a/API/Controllers/UploadController.cs b/API/Controllers/UploadController.cs index b4a7dcc6c..79e20d422 100644 --- a/API/Controllers/UploadController.cs +++ b/API/Controllers/UploadController.cs @@ -1,7 +1,9 @@ using System; +using System.Linq; using System.Threading.Tasks; using API.Constants; using API.Data; +using API.Data.Repositories; using API.DTOs.Uploads; using API.Entities.Enums; using API.Extensions; @@ -293,6 +295,65 @@ public class UploadController : BaseApiController return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-cover-chapter-save")); } + /// + /// Replaces volume cover image and locks it with a base64 encoded image. + /// + /// This is a helper API for Komf - Kavita UI does not use. Volume will find first chapter to update. + /// + /// + [Authorize(Policy = "RequireAdminRole")] + [RequestSizeLimit(ControllerConstants.MaxUploadSizeBytes)] + [HttpPost("volume")] + public async Task UploadVolumeCoverImageFromUrl(UploadFileDto uploadFileDto) + { + // Check if Url is non empty, request the image and place in temp, then ask image service to handle it. + // See if we can do this all in memory without touching underlying system + if (string.IsNullOrEmpty(uploadFileDto.Url)) + { + return BadRequest(await _localizationService.Translate(User.GetUserId(), "url-required")); + } + + try + { + var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(uploadFileDto.Id, VolumeIncludes.Chapters); + if (volume == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "volume-doesnt-exist")); + + // Find the first chapter of the volume + var chapter = volume.Chapters[0]; + + var filePath = await CreateThumbnail(uploadFileDto, $"{ImageService.GetChapterFormat(chapter.Id, uploadFileDto.Id)}"); + + if (!string.IsNullOrEmpty(filePath)) + { + chapter.CoverImage = filePath; + chapter.CoverImageLocked = true; + _unitOfWork.ChapterRepository.Update(chapter); + + volume.CoverImage = chapter.CoverImage; + _unitOfWork.VolumeRepository.Update(volume); + } + + if (_unitOfWork.HasChanges()) + { + await _unitOfWork.CommitAsync(); + await _eventHub.SendMessageAsync(MessageFactory.CoverUpdate, + MessageFactory.CoverUpdateEvent(chapter.VolumeId, MessageFactoryEntityTypes.Volume), false); + await _eventHub.SendMessageAsync(MessageFactory.CoverUpdate, + MessageFactory.CoverUpdateEvent(volume.Id, MessageFactoryEntityTypes.Chapter), false); + return Ok(); + } + + } + catch (Exception e) + { + _logger.LogError(e, "There was an issue uploading cover image for Volume {Id}", uploadFileDto.Id); + await _unitOfWork.RollbackAsync(); + } + + return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-cover-volume-save")); + } + + /// /// Replaces library cover image with a base64 encoded image. If empty string passed, will reset to null. /// diff --git a/API/I18N/en.json b/API/I18N/en.json index 5094b0626..e038a9ea8 100644 --- a/API/I18N/en.json +++ b/API/I18N/en.json @@ -138,6 +138,8 @@ "generic-cover-reading-list-save": "Unable to save cover image to Reading List", "generic-cover-chapter-save": "Unable to save cover image to Chapter", "generic-cover-library-save": "Unable to save cover image to Library", + "generic-cover-person-save": "Unable to save cover image to Person", + "generic-cover-volume-save": "Unable to save cover image to Volume", "access-denied": "You do not have access", "reset-chapter-lock": "Unable to resetting cover lock for Chapter", diff --git a/API/Services/ImageService.cs b/API/Services/ImageService.cs index 33b422d70..7b0b26c16 100644 --- a/API/Services/ImageService.cs +++ b/API/Services/ImageService.cs @@ -223,7 +223,7 @@ public class ImageService : IImageService /// /// Creates a thumbnail out of a memory stream and saves to with the passed - /// fileName and .png extension. + /// fileName and the appropriate extension. /// /// Stream to write to disk. Ensure this is rewinded. /// filename to save as without extension @@ -235,7 +235,6 @@ public class ImageService : IImageService var (targetWidth, targetHeight) = size.GetDimensions(); if (stream.CanSeek) stream.Position = 0; using var sourceImage = Image.NewFromStream(stream); - if (stream.CanSeek) stream.Position = 0; var scalingSize = GetSizeForDimensions(sourceImage, targetWidth, targetHeight); var scalingCrop = GetCropForDimensions(sourceImage, targetWidth, targetHeight); diff --git a/openapi.json b/openapi.json index 1cdd53a63..321c53278 100644 --- a/openapi.json +++ b/openapi.json @@ -12448,6 +12448,40 @@ } } }, + "/api/Upload/volume": { + "post": { + "tags": [ + "Upload" + ], + "summary": "Replaces volume cover image and locks it with a base64 encoded image.", + "description": "This is a helper API for Komf - Kavita UI does not use. Volume will find first chapter to update.", + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadFileDto" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/UploadFileDto" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/UploadFileDto" + } + } + } + }, + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/Upload/library": { "post": { "tags": [ @@ -22350,4 +22384,4 @@ "description": "Responsible for all things Want To Read" } ] -} +} \ No newline at end of file