using System; using System.Threading.Tasks; using API.DTOs.Uploads; using API.Interfaces; using API.Interfaces.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace API.Controllers { /// /// /// [Authorize(Policy = "RequireAdminRole")] public class UploadController : BaseApiController { private readonly IUnitOfWork _unitOfWork; private readonly IImageService _imageService; private readonly ILogger _logger; private readonly ITaskScheduler _taskScheduler; /// public UploadController(IUnitOfWork unitOfWork, IImageService imageService, ILogger logger, ITaskScheduler taskScheduler) { _unitOfWork = unitOfWork; _imageService = imageService; _logger = logger; _taskScheduler = taskScheduler; } /// /// Replaces series cover image and locks it with a base64 encoded image /// /// /// [Authorize(Policy = "RequireAdminRole")] [RequestSizeLimit(8_000_000)] [HttpPost("series")] public async Task UploadSeriesCoverImageFromUrl(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("You must pass a url to use"); } try { var bytes = _imageService.CreateThumbnailFromBase64(uploadFileDto.Url); var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(uploadFileDto.Id); if (bytes.Length > 0) { series.CoverImage = bytes; series.CoverImageLocked = true; _unitOfWork.SeriesRepository.Update(series); } if (_unitOfWork.HasChanges()) { await _unitOfWork.CommitAsync(); return Ok(); } } catch (Exception e) { _logger.LogError(e, "There was an issue uploading cover image for Series {Id}", uploadFileDto.Id); await _unitOfWork.RollbackAsync(); } return BadRequest("Unable to save cover image to Series"); } /// /// Replaces collection tag cover image and locks it with a base64 encoded image /// /// /// [Authorize(Policy = "RequireAdminRole")] [RequestSizeLimit(8_000_000)] [HttpPost("collection")] public async Task UploadCollectionCoverImageFromUrl(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("You must pass a url to use"); } try { var bytes = _imageService.CreateThumbnailFromBase64(uploadFileDto.Url); var tag = await _unitOfWork.CollectionTagRepository.GetTagAsync(uploadFileDto.Id); if (bytes.Length > 0) { tag.CoverImage = bytes; tag.CoverImageLocked = true; _unitOfWork.CollectionTagRepository.Update(tag); } if (_unitOfWork.HasChanges()) { await _unitOfWork.CommitAsync(); return Ok(); } } catch (Exception e) { _logger.LogError(e, "There was an issue uploading cover image for Collection Tag {Id}", uploadFileDto.Id); await _unitOfWork.RollbackAsync(); } return BadRequest("Unable to save cover image to Collection Tag"); } /// /// Replaces chapter cover image and locks it with a base64 encoded image. This will update the parent volume's cover image. /// /// /// [Authorize(Policy = "RequireAdminRole")] [RequestSizeLimit(8_000_000)] [HttpPost("chapter")] public async Task UploadChapterCoverImageFromUrl(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("You must pass a url to use"); } try { var bytes = _imageService.CreateThumbnailFromBase64(uploadFileDto.Url); if (bytes.Length > 0) { var chapter = await _unitOfWork.VolumeRepository.GetChapterAsync(uploadFileDto.Id); chapter.CoverImage = bytes; chapter.CoverImageLocked = true; _unitOfWork.ChapterRepository.Update(chapter); var volume = await _unitOfWork.SeriesRepository.GetVolumeAsync(chapter.VolumeId); volume.CoverImage = chapter.CoverImage; _unitOfWork.VolumeRepository.Update(volume); } if (_unitOfWork.HasChanges()) { await _unitOfWork.CommitAsync(); return Ok(); } } catch (Exception e) { _logger.LogError(e, "There was an issue uploading cover image for Chapter {Id}", uploadFileDto.Id); await _unitOfWork.RollbackAsync(); } return BadRequest("Unable to save cover image to Chapter"); } /// /// Replaces chapter cover image and locks it with a base64 encoded image. This will update the parent volume's cover image. /// /// Does not use Url property /// [Authorize(Policy = "RequireAdminRole")] [HttpPost("reset-chapter-lock")] public async Task ResetChapterLock(UploadFileDto uploadFileDto) { try { var chapter = await _unitOfWork.VolumeRepository.GetChapterAsync(uploadFileDto.Id); chapter.CoverImage = Array.Empty(); chapter.CoverImageLocked = false; _unitOfWork.ChapterRepository.Update(chapter); var volume = await _unitOfWork.SeriesRepository.GetVolumeAsync(chapter.VolumeId); volume.CoverImage = chapter.CoverImage; _unitOfWork.VolumeRepository.Update(volume); var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(volume.SeriesId); if (_unitOfWork.HasChanges()) { await _unitOfWork.CommitAsync(); _taskScheduler.RefreshSeriesMetadata(series.LibraryId, series.Id); return Ok(); } } catch (Exception e) { _logger.LogError(e, "There was an issue resetting cover lock for Chapter {Id}", uploadFileDto.Id); await _unitOfWork.RollbackAsync(); } return BadRequest("Unable to resetting cover lock for Chapter"); } } }