< Summary

Information
Class: MRA.WebApi.Controllers.Art.DrawingController
Assembly: MRA.WebApi
File(s): D:\a\MiguelRomerART\MiguelRomerART\MRA.WebApi\Controllers\Art\DrawingController.cs
Line coverage
32%
Covered lines: 63
Uncovered lines: 129
Coverable lines: 192
Total lines: 366
Line coverage: 32.8%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Products()100%11100%
Characters()100%11100%
Models()100%11100%
Details()100%11100%
FullDetails()100%11100%
FetchDrawingDetails()100%11100%
Filter()100%11100%
FullFilter()100%210%
FilteringDrawings()100%1177.77%
Cheer()100%210%
Vote()100%210%
Save()0%210140%
Exist()0%620%
CheckBlob()0%620%
UploadBlob()0%2040%
UploadImage()100%210%

File(s)

D:\a\MiguelRomerART\MiguelRomerART\MRA.WebApi\Controllers\Art\DrawingController.cs

#LineLine coverage
 1using Microsoft.AspNetCore.Authorization;
 2using Microsoft.AspNetCore.Mvc;
 3using MRA.DTO.Exceptions;
 4using MRA.DTO.Models;
 5using MRA.DTO.ViewModels.Art;
 6using MRA.DTO.ViewModels.Art.Select;
 7using MRA.Services;
 8using MRA.Services.Models.Drawings;
 9using MRA.Services.Storage;
 10using MRA.WebApi.Models.Responses;
 11using MRA.WebApi.Models.Responses.Errors;
 12using MRA.WebApi.Models.Responses.Errors.Drawings;
 13using System.Globalization;
 14
 15namespace MRA.WebApi.Controllers.Art;
 16
 17[ApiController]
 18[Route("api/art/drawing")]
 19public class DrawingController : Controller
 20{
 21    private readonly IAppService _appService;
 22    private readonly IDrawingService _drawingService;
 23    private readonly IStorageService _storageService;
 24    private readonly ILogger<DrawingController> _logger;
 25
 1326    public DrawingController(
 1327        ILogger<DrawingController> logger,
 1328        IAppService appService,
 1329        IStorageService storageService,
 1330        IDrawingService drawingService)
 31    {
 1332        _logger = logger;
 1333        _appService = appService;
 1334        _drawingService = drawingService;
 1335        _storageService = storageService;
 1336    }
 37
 38    [HttpGet("products")]
 39    public async Task<ActionResult<IEnumerable<ProductListItem>>> Products()
 40    {
 41        try
 42        {
 243            _logger.LogInformation("Requesting products");
 244            var products = await _drawingService.GetProductsAsync();
 145            _logger.LogInformation("Products found: {Count}", products.Count());
 146            return Ok(products);
 47        }
 148        catch (Exception ex)
 49        {
 150            _logger.LogError(ex, DrawingProductErrorMessages.InternalServer);
 151            return StatusCode(StatusCodes.Status500InternalServerError,
 152                new ErrorResponse(DrawingProductErrorMessages.InternalServer));
 53        }
 254    }
 55
 56    [HttpGet("characters")]
 57    public async Task<ActionResult<List<CharacterListItem>>> Characters()
 58    {
 59        try
 60        {
 261            _logger.LogInformation("Requesting characters");
 262            var characters = await _drawingService.GetCharactersAsync();
 163            _logger.LogInformation("Characters found: {Count}", characters.Count());
 164            return Ok(characters);
 65        }
 166        catch (Exception ex)
 67        {
 168            _logger.LogError(ex, DrawingCharactersErrorMessages.InternalServer);
 169            return StatusCode(StatusCodes.Status500InternalServerError,
 170                new ErrorResponse(DrawingCharactersErrorMessages.InternalServer));
 71        }
 272    }
 73
 74    [HttpGet("models")]
 75    public async Task<ActionResult<List<string>>> Models()
 76    {
 77        try
 78        {
 279            _logger.LogInformation("Requesting models");
 280            var models = await _drawingService.GetModelsAsync();
 181            _logger.LogInformation("Models found: '{Count}'", models.Count());
 382            var modelNames = models.Select(x => x.ModelName).ToList();
 183            return Ok(modelNames);
 84        }
 185        catch (Exception ex)
 86        {
 187            _logger.LogError(ex, DrawingModelsErrorMessages.InternalServer);
 188            return StatusCode(StatusCodes.Status500InternalServerError,
 189                new ErrorResponse(DrawingModelsErrorMessages.InternalServer));
 90        }
 291    }
 92
 93
 94    [HttpGet("details/{id}")]
 95    public async Task<ActionResult<DrawingModel>> Details(string id)
 96    {
 397        return await FetchDrawingDetails(id, true);
 398    }
 99
 100    [Authorize]
 101    [HttpGet("full-details/{id}")]
 102    public async Task<ActionResult<DrawingModel>> FullDetails(string id)
 103    {
 3104        return await FetchDrawingDetails(id, false);
 3105    }
 106
 107    private async Task<ActionResult<DrawingModel>> FetchDrawingDetails(string id, bool onlyIfVisible)
 108    {
 109        try
 110        {
 6111            _logger.LogInformation("Requesting drawing details '{Id}'", id);
 6112            var drawing = await _appService.FindDrawingByIdAsync(id, onlyIfVisible: onlyIfVisible, updateViews: true, ca
 2113            return Ok(drawing);
 114        }
 2115        catch (DrawingNotFoundException dnf)
 116        {
 2117            _logger.LogWarning(dnf, dnf.Message);
 2118            return NotFound(new ErrorResponse(dnf.Message));
 119        }
 2120        catch (Exception ex)
 121        {
 2122            _logger.LogError(ex, DrawingDetailsErrorMessages.InternalServer(id));
 2123            return StatusCode(StatusCodes.Status500InternalServerError,
 2124                new ErrorResponse(DrawingDetailsErrorMessages.InternalServer(id)));
 125        }
 6126    }
 127
 128
 129    [HttpPost("filter")]
 130    public async Task<ActionResult<FilterResults>> Filter([FromBody] DrawingFilter filters)
 131    {
 1132        filters.OnlyVisible = true;
 1133        return await FilteringDrawings(filters);
 1134    }
 135
 136    [Authorize]
 137    [HttpPost("full-filter")]
 138    public async Task<ActionResult<FilterResults>> FullFilter([FromBody] DrawingFilter filters)
 139    {
 0140        filters.OnlyVisible = false;
 0141        return await FilteringDrawings(filters);
 0142    }
 143
 144    private async Task<ActionResult<FilterResults>> FilteringDrawings(DrawingFilter filters)
 145    {
 146        try
 147        {
 1148            _logger.LogInformation($"Filtering drawings");
 1149            var results = await _appService.FilterDrawingsAsync(filters);
 0150            _logger.LogInformation("Total drawings found: {Count}", results.TotalDrawings.Count());
 0151            return Ok(results);
 152        }
 1153        catch (Exception ex)
 154        {
 1155            _logger.LogError(ex, DrawingFilterErrorMessages.InternalServer);
 1156            return StatusCode(StatusCodes.Status500InternalServerError,
 1157                new ErrorResponse(DrawingFilterErrorMessages.InternalServer));
 158        }
 1159    }
 160
 161    [HttpPost("cheer")]
 162    public async Task<ActionResult> Cheer([FromBody] string id)
 163    {
 164        try
 165        {
 0166            _logger.LogInformation($"Recibido like para dibujo \"{id}\"");
 0167            return Ok(await _drawingService.UpdateLikesAsync(id));
 168        }
 0169        catch (DrawingNotFoundException dnf)
 170        {
 0171            _logger.LogWarning($"No se encontró ningún dibujo \"{id}\"");
 0172            return NotFound(new { message = $"No drawing found with ID \"{id}\"" });
 173        }
 0174        catch (Exception ex)
 175        {
 0176            _logger.LogError($"Error al recibir like para dibujo \"{id}\": " + ex.Message);
 0177            return StatusCode(StatusCodes.Status500InternalServerError,
 0178                new { message = $"Error when liking drawing with ID \"{id}\"" });
 179        }
 0180    }
 181
 182    [HttpPost("vote/{id}")]
 183    public async Task<ActionResult<VoteSubmittedModel>> Vote(string id, [FromBody] int score)
 184    {
 185        try
 186        {
 0187            _logger.LogInformation($"Recibido voto para dibujo \"{id}\" ({score})");
 0188            var results = await _drawingService.VoteDrawingAsync(id, score);
 0189            _logger.LogInformation($"Nuevos resultados para \"{id}\" ({results.NewScoreHuman}) [{results.NewVotes} votos
 0190            return Ok(results);
 191        }
 0192        catch (DrawingNotFoundException dnf)
 193        {
 0194            _logger.LogWarning($"No se encontró ningún dibujo \"{id}\"");
 0195            return NotFound(new { message = $"No drawing found with ID \"{id}\"" });
 196        }
 0197        catch (Exception ex)
 198        {
 0199            _logger.LogError($"Error al recibir voto para dibujo \"{id}\": " + ex.Message);
 0200            return StatusCode(StatusCodes.Status500InternalServerError,
 0201                new { message = $"Error when receiving vote with ID \"{id}\"" });
 202        }
 0203    }
 204
 205    [Authorize]
 206    [HttpPost("save/{id}")]
 207    public async Task<ActionResult<DrawingModel>> Save(string id, [FromBody] SaveDrawingRequest request)
 208    {
 209        try
 210        {
 0211            _logger.LogInformation("Guardando dibujo '{Id}'", id);
 0212            var dateObject = DateTime.ParseExact(request.DateHyphen, "yyyy-MM-dd", CultureInfo.InvariantCulture);
 0213            var drawing = new DrawingModel()
 0214            {
 0215                ListComments = request.ListComments ?? [],
 0216                ListCommentsStyle = request.ListCommentsStyle ?? [],
 0217                ListCommentsPros = request.ListCommentsPros ?? [],
 0218                ListCommentsCons = request.ListCommentsCons ?? [],
 0219                Date = request.DateHyphen.Replace("-", "/"),
 0220                DateHyphen = request.DateHyphen,
 0221                DateObject = dateObject,
 0222                Favorite = request.Favorite,
 0223                Id = request.Id,
 0224                ModelName = request.ModelName,
 0225                Name = request.Name,
 0226                Paper = (int)request.Paper,
 0227                Path = request.Path,
 0228                PathThumbnail = request.PathThumbnail,
 0229                ProductName = request.ProductName,
 0230                ProductType = (int)request.ProductType,
 0231                ReferenceUrl = request.ReferenceUrl,
 0232                ScoreCritic = request.ScoreCritic,
 0233                Software = (int)request.Software,
 0234                Filter = (int)request.Filter,
 0235                SpotifyUrl = request.SpotifyUrl,
 0236                Tags = request.TagsText?.Split(DrawingTagManager.TAG_SEPARATOR) ?? [],
 0237                Time = request.Time ?? 0,
 0238                Title = request.Title ?? string.Empty,
 0239                Type = (int)request.Type,
 0240                InstagramUrl = request.InstagramUrl,
 0241                TwitterUrl = request.BlueskyUrl,
 0242                Visible = request.Visible
 0243            };
 244
 0245            var savedDrawing = await _drawingService.SaveDrawingAsync(drawing);
 0246            _appService.Clear();
 0247            savedDrawing.TagsText = string.Join(DrawingTagManager.TAG_SEPARATOR, savedDrawing.Tags);
 0248            return Ok(savedDrawing);
 249        }
 0250        catch (Exception ex)
 251        {
 0252            _logger.LogError($"Error al guardar dibujo \"{id}\": " + ex.Message);
 0253            return StatusCode(StatusCodes.Status500InternalServerError,
 0254                new { message = $"Error al guardar dibujo \"{id}\"" });
 255        }
 0256    }
 257
 258    [HttpGet("exist/{id}")]
 259    public async Task<ActionResult<bool>> Exist(string id)
 260    {
 261        try
 262        {
 0263            _logger.LogInformation($"Comprobando si existe dibujo \"{id}\"");
 0264            var exists = await _drawingService.ExistsDrawing(id);
 0265            _logger.LogInformation($"Existe dibujo \"{id}\": {(exists ? "Sí" : "No")}");
 0266            return Ok(exists);
 267        }
 0268        catch (Exception ex)
 269        {
 0270            _logger.LogError($"Error al comprobar dibujo \"{id}\": " + ex.Message);
 0271            return StatusCode(StatusCodes.Status500InternalServerError,
 0272                new { message = $"Error when checking drawing with ID \"{id}\"" });
 273        }
 0274    }
 275
 276    [Authorize]
 277    [HttpPost("check/blob")]
 278    public async Task<ActionResult<CheckAzurePathResponse>> CheckBlob([FromBody] CheckAzurePathRequest request)
 279    {
 280        try
 281        {
 0282            _logger.LogInformation($"Comprobando si existe blob de Azure \"{request.Id}\"");
 0283            var existe = await _storageService.ExistsBlob(request.Id);
 0284            if (!existe)
 285            {
 0286                _logger.LogWarning($"No existe el blob de Azure \"{request.Id}\"");
 287            }
 288
 0289            var blobLocationThumbnail = _storageService.CrearThumbnailName(request.Id);
 290
 0291            var urlBase = _storageService.GetBlobURL();
 0292            var url = urlBase + request.Id;
 0293            var url_tn = urlBase + blobLocationThumbnail;
 294
 0295            return new CheckAzurePathResponse()
 0296            {
 0297                Existe = existe,
 0298                Url = url,
 0299                UrlThumbnail = url_tn,
 0300                PathThumbnail = blobLocationThumbnail
 0301            };
 302        }
 0303        catch (Exception ex)
 304        {
 0305            _logger.LogError($"Error al comprobar si existe blob de Azure \"{request.Id}\": " + ex.Message);
 0306            return StatusCode(StatusCodes.Status500InternalServerError,
 0307                new { message = $"Error when checking blob \"{request.Id}\"" });
 308        }
 0309    }
 310
 311    [Authorize]
 312    [HttpPost("upload/blob")]
 313    public async Task<ActionResult<UploadAzureImageResponse>> UploadBlob(IFormFile image, [FromForm] int size, [FromForm
 314    {
 315        try
 316        {
 0317            _logger.LogInformation($"Subiendo fichero a Azure \"{image.FileName}\"");
 0318            if (image == null || image.Length == 0)
 319            {
 320                //return new UploadAzureImageResponse()
 321                //{
 322                //    Ok = false,
 323                //    Error = "No se ha proporcionado ninguna imagen",
 324                //};
 0325                _logger.LogWarning("No se ha proporcionado ningún fichero");
 0326                return BadRequest(new { message = $"No se ha proporcinoado ningún fichero" });
 327            }
 328
 0329            var blobLocationThumbnail = _storageService.CrearThumbnailName(path);
 0330            await UploadImage(image, blobLocationThumbnail, size);
 0331            _logger.LogInformation($"Subida imagen de Thumbnail a \"{blobLocationThumbnail}\"");
 0332            await UploadImage(image, path, 0);
 0333            _logger.LogInformation($"Subida imagen a \"{path}\"");
 334
 0335            var urlBase = _storageService.GetBlobURL();
 0336            var url = urlBase + path;
 0337            var url_tn = urlBase + blobLocationThumbnail;
 338
 0339            return Ok(new UploadAzureImageResponse()
 0340            {
 0341                Ok = true,
 0342                Error = "",
 0343                Url = url,
 0344                UrlThumbnail = url_tn,
 0345                PathThumbnail = blobLocationThumbnail
 0346            });
 347        }
 0348        catch (Exception ex)
 349        {
 0350            _logger.LogError($"Error al subir blob de Azure: " + ex.Message);
 0351            return StatusCode(StatusCodes.Status500InternalServerError,
 0352                new { message = $"Error when uploading blob" });
 353        }
 0354    }
 355
 356    private async Task UploadImage(IFormFile azureImage, string path, int azureImageThumbnailSize)
 357    {
 0358        using (var imageStream = new MemoryStream())
 359        {
 0360            await azureImage.CopyToAsync(imageStream);
 0361            imageStream.Position = 0;
 362
 0363            await _storageService.ResizeAndSave(imageStream, path, azureImageThumbnailSize);
 0364        }
 0365    }
 366}