using AutoMapper; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Modules.Library.WebApi.Models.Anime; using Modules.Library.WebApi.Models.Anime.CommonProperties; using Modules.Library.WebApi.Models.Views.Anime; using System.Net; namespace Modules.Library.WebApi.Controllers; [ApiController] [ApiExplorerSettings(GroupName = "AnimeTitleV1")] [Route("MediaContent/Anime/Title")] //[Route("[controller]")] [Authorize] public class TitleController : ControllerBase { private readonly IMapper _mapper; private readonly IMediator _mediator; private readonly ILogger _logger; public TitleController(IMapper mapper, IMediator mediator, ILogger logger) { _mapper = mapper; _mediator = mediator; _logger = logger; } [HttpGet("List")] [AllowAnonymous] public async Task> List() => _mapper.Map>(await _mediator.Send(new Application.Queries.Anime.AnimeTitle.AnimeTitleListQuery())); [HttpGet] [AllowAnonymous] public async Task ById(Guid TitleId) => _mapper.Map<Title>(await _mediator.Send(new Application.Queries.Anime.AnimeTitle.AnimeTitleQuery { Id = TitleId })); [HttpPost("Rate")] public async Task Rate(RateEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.RateTitleCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), RatePercentage = model.RatePercentage ?? throw new ArgumentNullException(nameof(model.RatePercentage)), }); [HttpPost("Unrate")] public async Task Unrate([FromBody]RateEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.UnrateTitleCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), }); [HttpPost("Create")] public async Task<Guid> CreateTitle([FromForm] TitleCreate model) { var streams = new List<Stream>(); try { var command = new Application.Commands.Anime.Title.CreateAnimeTitleCommand { Names = model.Names.Select(q => new Application.Commands.Anime.Title.Name { LanguageId = q.LanguageId, NameType = (Application.Commands.CommonModels.NameType)q.Type, Value = q.Value, }), Descriptions = model.Descriptions.Select(q => new Application.Commands.Anime.Title.Description { LanguageId = q.LanguageId, IsOriginal = q.IsOriginal, Value = q.Value, }), Genres = model.Genres.Select(q => new Application.Commands.Anime.Title.Genre { GenreId = q.GenreId, Proportion = q.Proportion, }), AnnouncementDate = model.AnnouncementDate, EstimatedReleaseDate = model.EstimatedReleaseDate, ReleaseDate = model.ReleaseDate, }; if (model.Preview?.NewFile != null) { var stream = model.Preview.NewFile.OpenReadStream(); streams.Add(stream); command.Preview = model.Preview == null ? null : new Application.Commands.Anime.Title.MediaInfo { Data = stream, Type = (Application.Commands.CommonModels.MediaInfoType)(model.Preview.NewType ?? throw new Exception("Type is not set")), ContentType = model.Preview.NewFile.ContentType, }; } else { if (!string.IsNullOrWhiteSpace(model.Preview?.NewUrl)) { command.Preview = new Application.Commands.Anime.Title.MediaInfo { Url = model.Preview.NewUrl, Type = (Application.Commands.CommonModels.MediaInfoType)(model.Preview.NewType ?? throw new Exception("Type is not set")), }; } } foreach (var relatedContent in model.RelatedContent) { if (relatedContent.NewFile != null) { var stream = relatedContent.NewFile.OpenReadStream(); streams.Add(stream); command.RelatedContent.Add(new Application.Commands.Anime.Title.MediaInfo { Data = stream, Type = (Application.Commands.CommonModels.MediaInfoType)(relatedContent.NewType ?? throw new Exception("Type is not set")), ContentType = relatedContent.NewFile.ContentType, }); } else { if (!string.IsNullOrWhiteSpace(relatedContent?.NewUrl)) { command.RelatedContent.Add(new Application.Commands.Anime.Title.MediaInfo { Url = relatedContent.NewUrl, Type = (Application.Commands.CommonModels.MediaInfoType)(relatedContent.NewType ?? throw new Exception("Type is not set")), }); } } } return await _mediator.Send(command); } finally { foreach (var stream in streams) { stream?.Close(); } } } [HttpPost("AddSeason")] public async Task<Guid> AddSeason([FromQuery] Guid titleId) => await _mediator.Send(new Application.Commands.Anime.Title.AddSeasonCommand { TitleId = titleId }); [HttpPost("DeleteSeason")] public async Task DeleteSeason([FromQuery] Guid titleId, [FromQuery] Guid itemId) => await _mediator.Send(new Application.Commands.Anime.Title.DeleteSeasonCommand { TitleId = titleId }); [HttpPost("AddEpisode")] public async Task<Guid> AddEpisode([FromQuery] Guid titleId) => await _mediator.Send(new Application.Commands.Anime.Title.AddEpisodeCommand { TitleId = titleId }); [HttpPost("DeleteEpisode")] public async Task DeleteEpisode([FromQuery] Guid titleId, [FromQuery] Guid itemId) => await _mediator.Send(new Application.Commands.Anime.Title.DeleteEpisodeCommand { TitleId = titleId }); [HttpPost("AddName")] public async Task AddName(NameEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Name.AddNameCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), LanguageId = model.LanguageId, NameType = (Application.Commands.CommonModels.NameType)model.Type, Value = model.Value }); [HttpPost("EditName")] public async Task EditName(NameEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Name.EditNameCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), LanguageId = model.LanguageId, NameType = (Application.Commands.CommonModels.NameType)model.Type, Value = model.Value, NewLanguageId = model.NewLanguageId, NewValue = model.NewValue, }); [HttpPost("DeleteName")] public async Task DeleteName(NameEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Name.DeleteNameCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), LanguageId = model.LanguageId, NameType = (Application.Commands.CommonModels.NameType)model.Type, Value = model.Value, }); [HttpGet("GetMedia")] [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(FileStreamResult))] [AllowAnonymous] public async Task<IActionResult> GetMedia(string objectId) //title id { if (!string.IsNullOrEmpty(objectId)) { var media = await _mediator.Send(new Application.Queries.Anime.GetMediaQuery { ObjectId = objectId, }); if (media == null) { return NotFound(); } else { return new FileStreamResult(media.Data, media.ContentType); } } else { return NotFound(); } } [HttpPost("SetPreview")] public async Task SetPreview([FromForm] MediaInfoEdit model) { if (model.NewFile == null && string.IsNullOrWhiteSpace(model.NewUrl)) throw new Exception("No file or url"); var command = new Application.Commands.Anime.Title.Properties.Preview.SetPreviewCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), Type = (Application.Commands.CommonModels.MediaInfoType)(model.NewType ?? throw new Exception("Type is not set")), }; if (model.NewFile != null) { using var stream = model.NewFile.OpenReadStream(); command.Data = stream; command.ContentType = model.NewFile.ContentType; var cd = model.NewFile.ContentDisposition; var a = model.NewFile.FileName; await _mediator.Send(command); } else { if (!string.IsNullOrWhiteSpace(model?.NewUrl)) { command.Url = model.NewUrl; await _mediator.Send(command); } } } [HttpPost("ClearPreview")] public async Task ClearPreview(MediaInfoEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Preview.DeletePreviewCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), }); [HttpPost("AddDescription")] public async Task AddDescription(DescriptionEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Description.AddDescriptionCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), IsOriginal = model.IsOriginal, LanguageId = model.LanguageId, Value = model.Value, }); [HttpPost("EditDescription")] public async Task EditDescription(DescriptionEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Description.EditDescriptionCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), LanguageId = model.LanguageId, IsOriginal = model.IsOriginal, Value = model.Value, NewLanguageId = model.NewLanguageId, NewValue = model.NewValue, }); [HttpPost("DeleteDescription")] public async Task DeleteDescription(DescriptionEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Description.DeleteDescriptionCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), LanguageId = model.LanguageId, IsOriginal = model.IsOriginal, Value = model.Value, }); [HttpPost("AddGenre")] public async Task AddDescription(GenreProportionEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Genre.AddGenreCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), GenreId = model.GenreId, Proportion = model.Proportion, }); [HttpPost("EditGenre")] public async Task EditGenre(GenreProportionEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Genre.SetGenreProportionCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), GenreId = model.GenreId, Proportion = model.Proportion }); [HttpPost("DeleteGenre")] public async Task DeleteGenre(GenreProportionEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.Genre.DeleteGenreCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), GenreId = model.GenreId, }); //[HttpGet("GetRelatedContent")] //public async Task AddRelatedContent(IFormFile file, MediaInfoEdit model) //{ // using var stream = file.OpenReadStream(); // await _mediator.Send(new Application.Commands.Anime.Title.Properties.RelatedContent.AddRelatedContentCommand // { // TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), // Type = (Application.Commands.CommonModels.MediaInfoType)model.Type, // Data = stream, // ContentType = model.ContentType, // }); //} [HttpPost("AddRelatedContent")] public async Task AddRelatedContent(IFormFile file, MediaInfoEdit model) { var command = new Application.Commands.Anime.Title.Properties.RelatedContent.AddRelatedContentCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), Type = (Application.Commands.CommonModels.MediaInfoType)(model.NewType ?? throw new Exception("Type is not set")), }; if (model.NewFile != null) { using var stream = file.OpenReadStream(); command.Data = stream; command.ContentType = file.ContentType; await _mediator.Send(command); } else { if (!string.IsNullOrWhiteSpace(model?.NewUrl)) { command.Url = model.NewUrl; await _mediator.Send(command); } } } [HttpPost("EditRelatedContent")] public async Task EditRelatedContent(IFormFile file, MediaInfoEdit model) { var command = new Application.Commands.Anime.Title.Properties.RelatedContent.EditRelatedContentCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), ObjectId = model.ObjectId ?? throw new Exception("Object id is required"), NewType = (Application.Commands.CommonModels.MediaInfoType?)model.NewType, }; if (model.NewFile != null) { using var stream = file.OpenReadStream(); command.NewData = stream; command.NewContentType = file.ContentType; var cd = file.ContentDisposition; var a = file.FileName; await _mediator.Send(command); } else { if (!string.IsNullOrWhiteSpace(model?.NewUrl)) { command.NewUrl = model.NewUrl; await _mediator.Send(command); } } } [HttpPost("DeleteRelatedContent")] public async Task DeleteRelatedContent(MediaInfoEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.RelatedContent.DeleteRelatedContentCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), ObjectId = model.ObjectId ?? throw new Exception("Object id is required"), }); [HttpPost("SetCompleted")] public async Task SetCompleted([FromQuery] Guid titleId, [FromQuery] bool completed) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.SetCompletedCommand { TitleId = titleId, Value = completed, }); [HttpPost("SetExpirationTime")] public async Task SetExpirationTime([FromQuery] Guid titleId, [FromQuery] long expirationTimeTicks) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.SetExpirationTimeCommand { TitleId = titleId, ExpirationTime = TimeSpan.FromTicks(expirationTimeTicks), }); [HttpPost("SetAnnouncementDate")] public async Task SetAnnouncementDate(DateEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.SetAnnouncementDateCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), Value = model.Value.HasValue ? new DateTimeOffset(model.Value.Value.DateTime, TimeSpan.Zero) : null }); [HttpPost("SetEstimatedReleaseDate")] public async Task SetEstimatedReleaseDate(DateEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.SetEstimatedReleaseDateCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), Value = model.Value.HasValue ? new DateTimeOffset(model.Value.Value.DateTime, TimeSpan.Zero) : null }); [HttpPost("SetReleaseDate")] public async Task SetReleaseDate(DateEdit model) => await _mediator.Send(new Application.Commands.Anime.Title.Properties.SetReleaseDateCommand { TitleId = model.AnimeTitleId ?? throw new ArgumentNullException(nameof(model.AnimeTitleId)), Value = model.Value.HasValue ? new DateTimeOffset(model.Value.Value.DateTime, TimeSpan.Zero) : null, }); }