Compare commits

...

No commits in common. "main" and "b001e215fef08219f8b5fcf76d24f17dd5f3d081" have entirely different histories.

985 changed files with 3947 additions and 145389 deletions

40
.gitignore vendored
View File

@ -1,8 +1,7 @@
# ---> VisualStudio
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files # User-specific files
*.rsuser *.rsuser
@ -92,7 +91,6 @@ StyleCopReport.xml
*.tmp_proj *.tmp_proj
*_wpftmp.csproj *_wpftmp.csproj
*.log *.log
*.tlog
*.vspscc *.vspscc
*.vssscc *.vssscc
.builds .builds
@ -296,17 +294,6 @@ node_modules/
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw *.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output # Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts **/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts
@ -363,9 +350,6 @@ ASALocalRun/
# Local History for Visual Studio # Local History for Visual Studio
.localhistory/ .localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database # BeatPulse healthcheck temp database
healthchecksdb healthchecksdb
@ -377,25 +361,3 @@ MigrationBackup/
# Fody - auto-generated XML schema # Fody - auto-generated XML schema
FodyWeavers.xsd FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

View File

@ -1,13 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/contentModel.xml
/.idea.MyBookmark.iml
/modules.xml
/projectSettingsUpdater.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,6 +0,0 @@
namespace Common.Application.DomainEvents.Abstractions;
public interface IHasDomainEvents
{
}

View File

@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,9 +0,0 @@
namespace Common.WebApi.Exceptions;
public abstract class AppException( string errorCode, string message, int statusCode,
params object[]? formatArgs) : Exception(message)
{
public string ErrorCode { get; } = errorCode;
public int StatusCode { get; } = statusCode;
public object[]? FormatArgs { get; } = formatArgs;
}

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="UnexpectedError" xml:space="preserve">
<value>An unexpected error has occurred</value>
</data>
</root>

View File

@ -1,4 +1,4 @@
namespace Modules.Rating.Database namespace Common.Domain
{ {
public class Class1 public class Class1
{ {

View File

@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,6 +0,0 @@
namespace Common.Security.Infrastructure.Mediatr;
public interface IRequirePermission
{
string PermissionCode { get; }
}

View File

@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.29.0" />
</ItemGroup>
</Project>

View File

@ -1,89 +0,0 @@
using System.Text.Json.Serialization;
using System.Text.Json;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
using Microsoft.AspNetCore.Mvc;
namespace Common.WebApi.Middlewares;
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly IHostEnvironment _host;
private readonly ILogger _logger;
private readonly JsonSerializerOptions _serializerOptions;
public ExceptionMiddleware(RequestDelegate next, IHostEnvironment host, ILogger<ExceptionMiddleware> logger)
{
_logger = logger;
_next = next;
_host = host;
_serializerOptions = new JsonSerializerOptions
{
Converters = {
new JsonStringEnumConverter()
},
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
}
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
//if (httpContext.Request.Method == "POST")
//{
// using var streamreader = new System.IO.StreamReader(httpContext.Request.Body);
// var body = await streamreader.ReadToEndAsync();
//}
await _next(httpContext);
}
catch (Exception exc)
{
var title = exc.Message;
var detail = "Unexpected error occured";
if (!_host.IsProduction()) detail = GetExceptionDetail(exc, false, true);
if (exc is MongoException dbUpdateException)
{
title = "Database error";
if (!_host.IsProduction()) detail = GetExceptionDetail(dbUpdateException, true, true);
}
else if (exc.Source?.Contains("Mongo") == true)
{
title = "Database error";
if (!_host.IsProduction()) detail = GetExceptionDetail(exc, true, true);
}
var problemDetail = new ProblemDetails
{
Title = title,
Detail = detail,
Instance = httpContext.Request.Path,
Status = StatusCodes.Status400BadRequest
};
_logger.LogError("Необработанная ошибка: {Message}", exc.Message);
httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
httpContext.Response.ContentType = "application/problem+json";
await httpContext.Response.WriteAsync(JsonSerializer.Serialize(problemDetail, _serializerOptions));
}
}
private string GetExceptionDetail(Exception exc, bool includeMessage, bool includeInner)
{
var sb = new StringBuilder();
if (!string.IsNullOrWhiteSpace(exc.Message) && includeMessage) sb.Append(exc.Message);
if (!string.IsNullOrWhiteSpace(exc.InnerException?.Message) && includeInner)
{
if (sb.Length > 0) sb.AppendLine();
sb.AppendLine("Inner:");
sb.Append(exc.InnerException.Message);
}
if (sb.Length > 0) sb.AppendLine();
sb.Append(exc.StackTrace);
return sb.ToString();
}
}

View File

@ -1,24 +0,0 @@
namespace Common.WebApi;
public static class DependencyInjectionExtensions
{
public static IServiceCollection AddApplicationDatabase(this IServiceCollection services, string? connectionString)
{
if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentNullException(nameof(connectionString));
services.AddDbContext<UserDbContext>(options =>
{
options.UseNpgsql(connectionString, q =>
{
q.MigrationsAssembly(Assembly.GetAssembly(typeof(UserDbContext))!.GetName().Name);
q.MigrationsHistoryTable("__Migrations");
});
//options.UseNpgsql(connectionString);
//AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); //Включаем UTC-время.
//options.UseLazyLoadingProxies(); // lazy loading
});
AddRepositories(services);
// AddGateways(services);
return services;
}
}

View File

@ -1,16 +0,0 @@
using ExcelTableImporter.Models.ExcelModels;
namespace ExcelTableImporter.Commands;
public class CommandHandlerFactory(AnimeLibrary library)
{
public ICommandHandler? GetHandler(ICommand command)
{
return command switch
{
ExitCommand exitCommand => new ExitCommandHandler(library, exitCommand),
ListCommand listCommand => new ListCommandHandler(library, listCommand),
_ => null
};
}
}

View File

@ -1,33 +0,0 @@
using ExcelTableImporter.Models.ExcelModels;
namespace ExcelTableImporter.Commands;
public interface ICommand
{
string HelpText { get; }
string UsageText { get; }
}
public interface ICommandHandler
{
void Handle();
}
public abstract class AnimeLibraryCommandHandlerBase<T>(AnimeLibrary library, T command) : ICommandHandler
where T : ICommand
{
protected readonly AnimeLibrary Library = library;
public void Handle()
{
try
{
Handle(command);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
protected abstract void Handle(T command);
}

View File

@ -1,177 +0,0 @@
using System.Globalization;
using System.Text.RegularExpressions;
using ExcelTableImporter.Models.ExcelModels;
using ExcelTableImporter.Models.ExcelModels.ExcelModels;
using NPOI.SS.UserModel;
namespace ExcelTableImporter;
public class LibrayLoader
{
public async Task<AnimeLibrary> LoadLibrary(string filePath)
{
var animeRows = await ReadExcelFile(filePath);
return MakeLibrary(animeRows);
}
private async Task<List<AnimeRow>> ReadExcelFile(string filePath)
{
await using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
IWorkbook workbook = WorkbookFactory.Create(stream);
var sheet = workbook.GetSheetAt(0);
var animeRows = new List<AnimeRow>();
for (var i = 1; i <= sheet.LastRowNum; i++)
{
var row = sheet.GetRow(i);
var isEmpty = row.GetCell(0) is null
&& row.GetCell(1) is null
&& row.GetCell(2) is null
&& row.GetCell(3) is null
&& row.GetCell(4) is null
&& row.GetCell(8) is null
&& row.GetCell(9) is null;
if (isEmpty) continue;
var c1 = row.GetCell(0)?.ToString(); // russian name
var c2 = row.GetCell(1)?.ToString(); // original name
var c3 = TryShort(row.GetCell(2)); // release year
var c4 = ReadSerialsCount(row.GetCell(3)); // formula cell
var c5 = ReadSerialsCount(row.GetCell(4)); // series viewed
var c6 = row.GetCell(6)?.ToString(); // is completed
var c7 = TryShort(row.GetCell(8)); // rating
var c8 = row.GetCell(9)?.ToString(); // comment
// var str = $"{c1} | {c2} [{c3}] - {c4} - : — {c5} — [{c6}] [{c7}]; {c8}";
animeRows.Add(new AnimeRow
{
NameRussian = c1,
NameOriginal = c2,
ReleaseYear = c3,
AnimeSeriesCountItems = ParseFormula(c4),
AnimeSeriesViewsCountItems = ParseFormula(c5),
IsCompleted = c6 == "Да",
RatingValue = c7,
Comment = c8,
});
// Console.WriteLine(str);
}
return animeRows;
}
private AnimeLibrary MakeLibrary(List<AnimeRow> animeRows)
{
var animeTitles = new Dictionary<string, AnimeTitle>(StringComparer.OrdinalIgnoreCase);
foreach (var row in animeRows)
{
if (!animeTitles.TryGetValue(row.NameOriginal, out var title))
{
title = new AnimeTitle
{
NameRussian = row.NameRussian,
NameOriginal = row.NameOriginal,
ReleaseYear = row.ReleaseYear,
RatingValue = row.RatingValue,
Comment = row.Comment
};
animeTitles[row.NameOriginal] = title;
}
var part = new AnimePart
{
ReleaseYear = row.ReleaseYear,
Type = DetectPartType(row.NameRussian, row.NameOriginal),
SeasonNumber = DetectSeasonNumber(row.NameRussian)
};
foreach (var item in row.AnimeSeriesCountItems)
{
part.EpisodeGroups.Add(new AnimeEpisodeGroup
{
Order = item.Order,
Count = item.Count,
Viewed = row.AnimeSeriesViewsCountItems
.FirstOrDefault(v => v.Order == item.Order)?.Count ?? 0
});
}
title.Parts.Add(part);
}
return new AnimeLibrary
{
Titles = animeTitles.Values.ToList()
};
}
static short? TryShort(ICell? cell)
{
if (cell == null) return null;
if (cell.CellType == CellType.Numeric) return Convert.ToInt16(cell.NumericCellValue);
if (short.TryParse(cell.ToString(), out var v)) return v;
return null;
}
static string? ReadSerialsCount(ICell? cell)
{
if (cell == null) return null;
return cell.CellType switch
{
CellType.Numeric => cell.NumericCellValue.ToString(CultureInfo.InvariantCulture),
CellType.Formula => cell.CellFormula,
_ => null
};
}
static List<AnimeSeriesCountItem> ParseFormula(string? formula)
{
var result = new List<AnimeSeriesCountItem>();
if (string.IsNullOrWhiteSpace(formula)) return result;
formula = formula.TrimStart('=');
var parts = formula.Split('+', StringSplitOptions.RemoveEmptyEntries);
var order = 1;
foreach (var p in parts)
{
if (int.TryParse(p, out var count))
{
result.Add(new AnimeSeriesCountItem
{
Order = order++,
Count = count
});
}
}
return result;
}
static AnimePartType DetectPartType(string nameRu, string nameOrig)
{
var name = (nameRu + " " + nameOrig).ToLowerInvariant();
if (name.Contains("фильм") || name.Contains("movie") || name.Contains("gekijouban"))
return AnimePartType.Movie;
if (name.Contains("ova"))
return AnimePartType.Ova;
if (name.Contains("special") || name.Contains("спешл"))
return AnimePartType.Special;
return AnimePartType.Season;
}
static int? DetectSeasonNumber(string nameRu)
{
var match = Regex.Match(nameRu, @"сезон\s*(\d+)", RegexOptions.IgnoreCase);
if (match.Success && int.TryParse(match.Groups[1].Value, out var num))
return num;
return null;
}
}

View File

@ -1,37 +0,0 @@
namespace ExcelTableImporter.Models.ExcelModels;
public class AnimeTitle
{
public string NameRussian { get; set; } = null!;
public string NameOriginal { get; set; } = null!;
public int ReleaseYear { get; set; }
public List<AnimePart> Parts { get; set; } = [];
public bool IsCompleted { get; set; }
public int RatingValue { get; set; }
public string? Comment { get; set; }
}
public class AnimePart
{
public AnimePartType Type { get; set; }
public int? SeasonNumber { get; set; }
public int ReleaseYear { get; set; }
public List<AnimeEpisodeGroup> EpisodeGroups { get; set; } = [];
}
public enum AnimePartType
{
Season,
RegularEpisode,
Movie,
Ova,
Special,
Unknown
}
public class AnimeEpisodeGroup
{
public int Order { get; set; }
public int Count { get; set; }
public int Viewed { get; set; }
}

View File

@ -1,168 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Application.Services;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Title;
public class AddEpisodeCommand : IRequest<Guid>, IDisposable, IAsyncDisposable
{
public Guid TitleId { get; init; }
public IEnumerable<Name> Names { get; init; } = [];
public MediaInfo? Preview { get; set; }
public IEnumerable<Description> Descriptions { get; init; } = [];
public IEnumerable<Genre> Genres { get; init; } = [];
public List<MediaInfo> RelatedContent { get; init; } = [];
public DateTimeOffset? AnnouncementDate { get; init; }
public DateTimeOffset? ExpectedReleaseDate { get; init; }
public DateTimeOffset ReleaseDate { get; init; }
public int? Number { get; init; }
public ushort? Order { get; init; }
public Models.AnimeEpisodeType Type { get; init; }
public TimeSpan? Duration { get; init; }
public void Dispose()
{
if (Preview != null && Preview.Data != null && Preview.Data.CanSeek)
{
Preview.Data.Dispose();
}
Preview = null;
foreach (var item in RelatedContent)
{
if (item.Data != null && item.Data.CanSeek)
{
item.Data.Dispose();
}
}
RelatedContent.Clear();
}
public async ValueTask DisposeAsync()
{
if (Preview != null && Preview.Data != null && Preview.Data.CanSeek)
{
await Preview.Data.DisposeAsync();
}
Preview = null;
foreach (var item in RelatedContent)
{
if (item.Data != null && item.Data.CanSeek)
{
await item.Data.DisposeAsync();
}
}
RelatedContent.Clear();
}
}
public class AddEpisodeCommandHandler(IAnimeTitleGateway titleGateway, IAnimeEpisodeGateway episodeGateway, ILanguageGateway languageGateway,
IGenreGateway genreGateway, MediaInfoService mediaInfoService) : IRequestHandler<AddEpisodeCommand, Guid>
{
public async Task<Guid> Handle(AddEpisodeCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId, cancellationToken);
//if (!request.Names.Any()) throw new Exception("No names");
var languages = (await languageGateway
.GetLanguageByIds(request.Names.Select(q => q.LanguageId).Distinct(), cancellationToken)).ToArray();
var genres = (await genreGateway
.GetGenreByIds(request.Genres.Select(q => q.GenreId).Distinct(), cancellationToken)).ToArray();
//var episode = title.AddEpisode((Domain.Entities.MediaContent.Items.Anime.AnimeEpisodeType)request.Type);
//replace type by tags
//var episodeType = request.Type switch
//{
// Models.AnimeEpisodeType.Regilar => Domain.Entities.MediaContent.Items.Anime.AnimeEpisodeType.Regilar,
// Models.AnimeEpisodeType.Ova => Domain.Entities.MediaContent.Items.Anime.AnimeEpisodeType.Ova,
// Models.AnimeEpisodeType.FullLength => Domain.Entities.MediaContent.Items.Anime.AnimeEpisodeType.FullLength,
// _ => throw new NotImplementedException()
//};
AnimeEpisode episode;
if (!request.Order.HasValue)
{
episode = title.AddEpisode((AnimeEpisodeType)request.Type, request.Names.Select(q =>
new Domain.Entities.MediaContent.CommonProperties.NameItem((Domain.Entities.MediaContent.CommonProperties.NameType)q.NameType,
languages.First(x => x.Id == q.LanguageId).Id, q.Value)), request.Number, request.Duration);
}
else
{
episode = title.AddEpisodeAsVariant((AnimeEpisodeType)request.Type, request.Names.Select(q =>
new Domain.Entities.MediaContent.CommonProperties.NameItem((Domain.Entities.MediaContent.CommonProperties.NameType)q.NameType,
languages.First(x => x.Id == q.LanguageId).Id, q.Value)), request.Order.Value, request.Number, request.Duration);
}
//var language = await languageGateway.GetLanguageById(request.NameLanguageId);
foreach (var name in request.Names)
{
var languageId = languages.First(x => x.Id == name.LanguageId).Id;
var type = (Domain.Entities.MediaContent.CommonProperties.NameType)name.NameType;
episode.CommonProperties.AddName(type, languageId, name.Value);
}
if (request.Descriptions.Any())
{
foreach (var description in request.Descriptions)
{
var languageId = languages.First(q => q.Id == description.LanguageId).Id;
if (description.IsOriginal) episode.CommonProperties.AddOriginalDescription(languageId, description.Value);
else episode.CommonProperties.AddNotOriginalDescription(languageId, description.Value);
}
}
if (request.Genres.Any())
{
foreach (var genre in request.Genres)
{
var genreId = genres.First(q => q.Id == genre.GenreId).Id;
episode.CommonProperties.AddGenre(genreId, genre.Proportion);
}
}
if (request.RelatedContent.Any())
{
foreach (var relatedContentItem in request.RelatedContent)
{
//add model
var (objectId, contentType) = await mediaInfoService.Add(new MediaInfoService.CreateModel
{
Data = relatedContentItem.Data,
Url = relatedContentItem.Url,
ContentType = relatedContentItem.ContentType,
Type = (Domain.Entities.MediaInfoType)relatedContentItem.Type,
}, false, cancellationToken);
//objectId
episode.CommonProperties.AddRelatedContent(objectId, (Domain.Entities.MediaInfoType)relatedContentItem.Type, contentType);
}
}
episode.CommonProperties.SetAnnouncementDate(request.AnnouncementDate);
episode.CommonProperties.SetExpectedReleaseDate(request.ExpectedReleaseDate);
episode.CommonProperties.SetReleaseDate(request.ReleaseDate);
var animeEpisodeId = await episodeGateway.Create(title.Id, null, episode, cancellationToken);
if (request.Preview != null)
{
title = await titleGateway.GetById(title.Id, cancellationToken);
episode = title.Items.OfType<AnimeEpisode>().First(q => q.Id == animeEpisodeId);
var (objectId, contentType) = await mediaInfoService.Add(new MediaInfoService.CreateModel
{
Id = animeEpisodeId,
Data = request.Preview.Data,
Url = request.Preview.Url,
ContentType = request.Preview.ContentType,
Type = (Domain.Entities.MediaInfoType)request.Preview.Type,
}, true, cancellationToken);
episode.CommonProperties.SetPreview(objectId, (Domain.Entities.MediaInfoType)request.Preview.Type, contentType);
await episodeGateway.Update(title.Id, null, episode, cancellationToken);
}
//return await titleGateway.Create(animeTitle);
return animeEpisodeId;
}
}

View File

@ -1,33 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Description;
public class AddDescriptionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public bool IsOriginal { get; set; }
}
public class AddDescriptionCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<AddDescriptionCommand, Unit>
{
public async Task<Unit> Handle(AddDescriptionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
if (!await languageGateway.IsLanguageExists(request.LanguageId)) throw new Exception();
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
if (request.IsOriginal) episode.CommonProperties.AddOriginalDescription(request.LanguageId, request.Value);
else episode.CommonProperties.AddNotOriginalDescription(request.LanguageId, request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,32 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Description;
public class DeleteDescriptionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public bool IsOriginal { get; set; }
}
public class DeleteDescriptionCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteDescriptionCommand, Unit>
{
public async Task<Unit> Handle(DeleteDescriptionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
var description = new Domain.Entities.MediaContent.CommonProperties.Description(request.LanguageId, request.IsOriginal, request.Value);
episode.CommonProperties.RemoveDescription(description);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,34 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Description;
public class EditDescriptionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public bool IsOriginal { get; set; }
public Guid? NewLanguageId { get; set; }
public string? NewValue { get; set; }
}
public class EditDescriptionCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<EditDescriptionCommand, Unit>
{
public async Task<Unit> Handle(EditDescriptionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
if (!await languageGateway.IsLanguageExists(request.LanguageId)) throw new Exception("Language not exists");
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
var description = new Domain.Entities.MediaContent.CommonProperties.Description(request.LanguageId, request.IsOriginal, request.Value);
episode.CommonProperties.SetDescriptionValue(description, request.NewLanguageId, request.NewValue);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,32 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Genre;
public class AddGenreCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public Guid GenreId { get; set; }
public decimal? Proportion { get; set; }
}
public class AddGenreCommandHandler(IAnimeTitleGateway titleGateway, IGenreGateway genreGateway) : IRequestHandler<AddGenreCommand, Unit>
{
public async Task<Unit> Handle(AddGenreCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
if (!await genreGateway.IsGenreExists(request.GenreId)) throw new Exception("NotFound");
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.AddGenre(request.GenreId, request.Proportion);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,28 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Genre;
public class DeleteGenreCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public Guid GenreId { get; set; }
}
public class DeleteGenreCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteGenreCommand, Unit>
{
public async Task<Unit> Handle(DeleteGenreCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.RemoveGenre(request.GenreId);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,30 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Genre;
public class SetGenreProportionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public Guid GenreId { get; set; }
public decimal? Proportion { get; set; }
public decimal? NewProportion { get; set; }
}
public class SetGenreProportionCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetGenreProportionCommand, Unit>
{
public async Task<Unit> Handle(SetGenreProportionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.SetGenreProportion(request.GenreId, request.NewProportion);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,33 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Name;
public class AddNameCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public NameType NameType { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
}
public class AddNameCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<AddNameCommand, Unit>
{
public async Task<Unit> Handle(AddNameCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var language = await languageGateway.GetLanguageById(request.LanguageId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.AddName((Domain.Entities.MediaContent.CommonProperties.NameType)request.NameType, language.Id, request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,33 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.CommonProperties;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Name;
public class DeleteNameCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public CommonModels.NameType NameType { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
}
public class DeleteNameCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<DeleteNameCommand, Unit>
{
public async Task<Unit> Handle(DeleteNameCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var language = await languageGateway.GetLanguageById(request.LanguageId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.RemoveName(new NameItem((NameType)request.NameType, request.LanguageId, request.Value));
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,37 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.CommonProperties;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Name;
public class EditNameCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public CommonModels.NameType NameType { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public string? NewValue { get; set; }
public Guid? NewLanguageId { get; set; }
}
public class EditNameCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<EditNameCommand, Unit>
{
public async Task<Unit> Handle(EditNameCommand request, CancellationToken cancellationToken)
{
if (!request.NewLanguageId.HasValue && string.IsNullOrWhiteSpace(request.NewValue))
{
throw new ArgumentNullException($"{nameof(EditNameCommand.NewLanguageId)}, {nameof(EditNameCommand.NewValue)}");
}
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.SetNameValue(new NameItem((NameType)request.NameType, request.LanguageId, request.Value), request.NewLanguageId, request.NewValue);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,27 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Preview;
public class DeletePreviewCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
}
public class DeletePreviewCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeletePreviewCommand, Unit>
{
public async Task<Unit> Handle(DeletePreviewCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.DeletePreview();
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,31 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.Preview;
public class SetPreviewCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public string Url { get; set; } = default!;
public MediaInfoType Type { get; set; }
public string ContentType { get; set; } = default!;
}
public class SetPreviewCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetPreviewCommand, Unit>
{
public async Task<Unit> Handle(SetPreviewCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.SetPreview(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,31 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.RelatedContent;
public class AddRelatedContentCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public MediaInfoType Type { get; set; }
public string Url { get; set; } = default!;
public string ContentType { get; set; } = default!;
}
public class AddRelatedContentCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<AddRelatedContentCommand, Unit>
{
public async Task<Unit> Handle(AddRelatedContentCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.AddRelatedContent(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,33 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.RelatedContent;
public class DeleteRelatedContentCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public MediaInfoType Type { get; set; }
public string Url { get; set; } = default!;
public string ContentType { get; set; } = default!;
}
public class DeleteRelatedContentCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteRelatedContentCommand, Unit>
{
public async Task<Unit> Handle(DeleteRelatedContentCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var mediaInfo = new Domain.Entities.MediaInfo(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.RemoveRelatedContent(mediaInfo);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,35 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties.RelatedContent;
public class EditRelatedContentCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public MediaInfoType Type { get; set; }
public string Url { get; set; } = default!;
public string ContentType { get; set; } = default!;
public MediaInfoType NewType { get; set; }
public string NewUrl { get; set; } = default!;
public string NewContentType { get; set; } = default!;
}
public class EditRelatedContentCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<EditRelatedContentCommand, Unit>
{
public async Task<Unit> Handle(EditRelatedContentCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var mediaInfo = new Domain.Entities.MediaInfo(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.EditRelatedContent(mediaInfo, request.NewUrl, (Domain.Entities.MediaInfoType)request.NewType, request.NewContentType);
return Unit.Value;
}
}

View File

@ -1,29 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties;
public class SetAnnouncementDateCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public DateTimeOffset? Value { get; set; }
}
public class SetAnnouncementDateCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetAnnouncementDateCommand, Unit>
{
public async Task<Unit> Handle(SetAnnouncementDateCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.SetAnnouncementDate(request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,30 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties;
public class SetCompletedCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public bool Value { get; set; }
}
public class SetCompletedCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetCompletedCommand, Unit>
{
public async Task<Unit> Handle(SetCompletedCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
if (request.Value) episode.SetCompleted();
else episode.SetNotCompleted();
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,29 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties;
public class SetDurationCommand : IRequest<Unit>
{
public Guid TitleId { get; init; }
public Guid SeasonId { get; init; }
public Guid EpisodeId { get; init; }
public TimeSpan Duration { get; init; }
}
public class SetDurationCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetDurationCommand, Unit>
{
public async Task<Unit> Handle(SetDurationCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.SetDuration(request.Duration);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,29 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties;
public class SetEstimatedReleaseDateCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public DateTimeOffset? Value { get; set; }
}
public class SetEstimatedReleaseDateCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetEstimatedReleaseDateCommand, Unit>
{
public async Task<Unit> Handle(SetEstimatedReleaseDateCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.SetEstimatedReleaseDate(request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,29 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties;
public class SetExpirationTimeCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public TimeSpan ExpirationTime { get; set; }
}
public class SetExpirationTimeCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetExpirationTimeCommand, Unit>
{
public async Task<Unit> Handle(SetExpirationTimeCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.SetExpirationTime(request.ExpirationTime);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,29 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Episode.Properties;
public class SetReleaseDateCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
public DateTimeOffset? Value { get; set; }
}
public class SetReleaseDateCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetReleaseDateCommand, Unit>
{
public async Task<Unit> Handle(SetReleaseDateCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var episode = season.Episodes.FirstOrDefault(q => q.Id == request.EpisodeId) ??
throw new Exception("Episode not found");
episode.CommonProperties.SetReleaseDate(request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,30 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Rating.Api.Commands;
using Modules.User.Application;
namespace Modules.Library.Application.Commands.Anime.Episode;
public class UnvoteTitleCommand : IRequest<Unit>
{
public Guid TitleId { get; init; }
}
public class UnvoteEpisodeCommandHandler(IAnimeTitleGateway titleGateway, UserContext userContext, IMediator mediator) : IRequestHandler<UnvoteTitleCommand, Unit>
{
public async Task<Unit> Handle(UnvoteTitleCommand request, CancellationToken cancellationToken)
{
var user = await userContext.GetUserInfo(cancellationToken);
if (!user.IsAuthenticated || (!user.Id.HasValue || user.Id == Guid.Empty))
{
throw new Exception("User is not authenticated");
}
var subjectId = user.Id.Value;
var title = await titleGateway.GetById(request.TitleId, cancellationToken);
if (!title.Deleted)
{
await mediator.Send(new UnrateObjectCommand { ObjectId = title.Id, SubjectId = subjectId }, cancellationToken);
}
return Unit.Value;
}
}

View File

@ -1,38 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Rating.Api.Commands;
using Modules.User.Application;
namespace Modules.Library.Application.Commands.Anime.Episode;
public class VoteTitleCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; init; }
public Guid EpisodeId { get; init; }
public ushort RatingPercentage { get; set; }
}
public class VoteTitleCommandHandler(IAnimeTitleGateway titleGateway, UserContext userContext, IMediator mediator) : IRequestHandler<VoteTitleCommand, Unit>
{
public async Task<Unit> Handle(VoteTitleCommand request, CancellationToken cancellationToken)
{
var user = await userContext.GetUserInfo(cancellationToken);
if (!user.IsAuthenticated || (!user.Id.HasValue || user.Id == Guid.Empty))
{
throw new Exception("User is not authenticated");
}
var subjectId = user.Id.Value;
var title = await titleGateway.GetById(request.TitleId);
if (!title.Deleted)
{
await mediator.Send(new VoteForObjectCommand
{
ObjectId = title.Id,
SubjectId = subjectId,
RatingPercentage = request.RatingPercentage
}, cancellationToken);
}
return Unit.Value;
}
}

View File

@ -1,8 +0,0 @@
namespace Modules.Library.Application.Commands.Anime.Models;
public enum AnimeEpisodeType
{
Regular,
Ova,
Ona,
}

View File

@ -1,32 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season;
public class AddEpisodeCommand : IRequest<Guid>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public AnimeEpisodeType Type { get; set; }
}
public enum AnimeEpisodeType
{
Regilar,
FullLength,
Ova,
}
public class AddEpisodeCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<AddEpisodeCommand, Guid>
{
public async Task<Guid> Handle(AddEpisodeCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().First(q => q.Id == request.SeasonId);
var episode = season.AddEpisode((Domain.Entities.MediaContent.Items.Anime.AnimeEpisodeType)request.Type);
await titleGateway.Update(title);
return episode.Id;
}
}

View File

@ -1,20 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
namespace Modules.Library.Application.Commands.Anime.Season;
public class CreateSeasonCommand : IRequest<Guid>
{
public Guid TitleId { get; set; }
}
public class CreateSeasonCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<CreateSeasonCommand, Guid>
{
public async Task<Guid> Handle(CreateSeasonCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.AddSeason();
await titleGateway.Update(title);
return season.Id;
}
}

View File

@ -1,25 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season;
public class DeleteEpisodeCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid EpisodeId { get; set; }
}
public class DeleteEpisodeCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteEpisodeCommand, Unit>
{
public async Task<Unit> Handle(DeleteEpisodeCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().First(q => q.Id == request.SeasonId);
var episode = season.Episodes.First(q => q.Id == request.EpisodeId);
episode.Delete();
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,24 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season;
public class DeleteSeasonCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
}
public class DeleteSeasonCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteSeasonCommand, Unit>
{
public async Task<Unit> Handle(DeleteSeasonCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.Delete();
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,30 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Description;
public class AddDescriptionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public bool IsOriginal { get; set; }
}
public class AddDescriptionCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<AddDescriptionCommand, Unit>
{
public async Task<Unit> Handle(AddDescriptionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
if (!await languageGateway.IsLanguageExists(request.LanguageId)) throw new Exception();
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
if (request.IsOriginal) season.CommonProperties.AddOriginalDescription(request.LanguageId, request.Value);
else season.CommonProperties.AddNotOriginalDescription(request.LanguageId, request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,29 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Description;
public class DeleteDescriptionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public bool IsOriginal { get; set; }
}
public class DeleteDescriptionCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteDescriptionCommand, Unit>
{
public async Task<Unit> Handle(DeleteDescriptionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
var description = new Domain.Entities.MediaContent.CommonProperties.Description(request.LanguageId, request.IsOriginal, request.Value);
season.CommonProperties.RemoveDescription(description);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,31 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Description;
public class EditDescriptionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public bool IsOriginal { get; set; }
public string? NewValue { get; set; }
public Guid? NewLanguageId { get; set; }
}
public class EditDescriptionCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<EditDescriptionCommand, Unit>
{
public async Task<Unit> Handle(EditDescriptionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
if (!await languageGateway.IsLanguageExists(request.LanguageId)) throw new Exception("Language not exists");
var description = new Domain.Entities.MediaContent.CommonProperties.Description(request.LanguageId, request.IsOriginal, request.Value);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.SetDescriptionValue(description, request.NewLanguageId, request.NewValue);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,28 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Genre;
public class AddGenreCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid GenreId { get; set; }
public decimal? Proportion { get; set; }
}
public class AddGenreCommandHandler(IAnimeTitleGateway titleGateway, IGenreGateway genreGateway) : IRequestHandler<AddGenreCommand, Unit>
{
public async Task<Unit> Handle(AddGenreCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
if (!await genreGateway.IsGenreExists(request.GenreId)) throw new Exception("NotFound");
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.AddGenre(request.GenreId, request.Proportion);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,25 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Genre;
public class DeleteGenreCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid GenreId { get; set; }
}
public class DeleteGenreCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteGenreCommand, Unit>
{
public async Task<Unit> Handle(DeleteGenreCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.RemoveGenre(request.GenreId);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,27 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Genre;
public class SetGenreProportionCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public Guid GenreId { get; set; }
public decimal? Proportion { get; set; }
public decimal? NewProportion { get; set; }
}
public class SetGenreProportionCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetGenreProportionCommand, Unit>
{
public async Task<Unit> Handle(SetGenreProportionCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.SetGenreProportion(request.GenreId, request.NewProportion);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,30 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Name;
public class AddNameCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public NameType NameType { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
}
public class AddNameCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<AddNameCommand, Unit>
{
public async Task<Unit> Handle(AddNameCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var language = await languageGateway.GetLanguageById(request.LanguageId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.AddName((Domain.Entities.MediaContent.CommonProperties.NameType)request.NameType, language.Id, request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,30 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.CommonProperties;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Name;
public class DeleteNameCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public CommonModels.NameType NameType { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
}
public class DeleteNameCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway) : IRequestHandler<DeleteNameCommand, Unit>
{
public async Task<Unit> Handle(DeleteNameCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var language = await languageGateway.GetLanguageById(request.LanguageId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.RemoveName(new NameItem((NameType)request.NameType, request.LanguageId, request.Value));
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,34 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.CommonProperties;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Name;
public class EditNameCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public CommonModels.NameType NameType { get; set; }
public Guid LanguageId { get; set; }
public string Value { get; set; } = default!;
public string? NewValue { get; set; }
public Guid? NewLanguageId { get; set; }
}
public class EditNameCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<EditNameCommand, Unit>
{
public async Task<Unit> Handle(EditNameCommand request, CancellationToken cancellationToken)
{
if (!request.NewLanguageId.HasValue && string.IsNullOrWhiteSpace(request.NewValue))
{
throw new ArgumentNullException($"{nameof(EditNameCommand.NewLanguageId)}, {nameof(EditNameCommand.NewValue)}");
}
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.SetNameValue(new NameItem((NameType)request.NameType, request.LanguageId, request.Value), request.NewLanguageId, request.NewValue);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,24 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Preview;
public class DeletePreviewCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
}
public class DeletePreviewCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeletePreviewCommand, Unit>
{
public async Task<Unit> Handle(DeletePreviewCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.DeletePreview();
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,28 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.Preview;
public class SetPreviewCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public string Url { get; set; } = default!;
public MediaInfoType Type { get; set; }
public string ContentType { get; set; } = default!;
}
public class SetPreviewCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetPreviewCommand, Unit>
{
public async Task<Unit> Handle(SetPreviewCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.SetPreview(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,28 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.RelatedContent;
public class AddRelatedContentCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public MediaInfoType Type { get; set; }
public string Url { get; set; } = default!;
public string ContentType { get; set; } = default!;
}
public class AddRelatedContentCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<AddRelatedContentCommand, Unit>
{
public async Task<Unit> Handle(AddRelatedContentCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.AddRelatedContent(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,29 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.RelatedContent;
public class DeleteRelatedContentCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public MediaInfoType Type { get; set; }
public string Url { get; set; } = default!;
public string ContentType { get; set; } = default!;
}
public class DeleteRelatedContentCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<DeleteRelatedContentCommand, Unit>
{
public async Task<Unit> Handle(DeleteRelatedContentCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var mediaInfo = new Domain.Entities.MediaInfo(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.RemoveRelatedContent(mediaInfo);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,31 +0,0 @@
using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties.RelatedContent;
public class EditRelatedContentCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public MediaInfoType Type { get; set; }
public string Url { get; set; } = default!;
public string ContentType { get; set; } = default!;
public MediaInfoType NewType { get; set; }
public string NewUrl { get; set; } = default!;
public string NewContentType { get; set; } = default!;
}
public class EditRelatedContentCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<EditRelatedContentCommand, Unit>
{
public async Task<Unit> Handle(EditRelatedContentCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var mediaInfo = new Domain.Entities.MediaInfo(request.Url, (Domain.Entities.MediaInfoType)request.Type, request.ContentType);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.EditRelatedContent(mediaInfo, request.NewUrl, (Domain.Entities.MediaInfoType)request.NewType, request.NewContentType);
return Unit.Value;
}
}

View File

@ -1,26 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties;
public class SetAnnouncementDateCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public DateTimeOffset? Value { get; set; }
}
public class SetAnnouncementDateCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetAnnouncementDateCommand, Unit>
{
public async Task<Unit> Handle(SetAnnouncementDateCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.SetAnnouncementDate(request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,27 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties;
public class SetCompletedCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public bool Value { get; set; }
}
public class SetCompletedCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetCompletedCommand, Unit>
{
public async Task<Unit> Handle(SetCompletedCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
if (request.Value) season.SetCompleted();
else season.SetNotCompleted();
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,26 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties;
public class SetEstimatedReleaseDateCommand : IRequest<Unit>
{
public Guid TitleId { get; init; }
public Guid SeasonId { get; init; }
public DateTimeOffset? Value { get; init; }
}
public class SetEstimatedReleaseDateCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetEstimatedReleaseDateCommand, Unit>
{
public async Task<Unit> Handle(SetEstimatedReleaseDateCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId, cancellationToken);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.SetExpectedReleaseDate(request.Value);
await titleGateway.Update(title, cancellationToken);
return Unit.Value;
}
}

View File

@ -1,26 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties;
public class SetExpirationTimeCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public TimeSpan ExpirationTime { get; set; }
}
public class SetExpirationTimeCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetExpirationTimeCommand, Unit>
{
public async Task<Unit> Handle(SetExpirationTimeCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.SetExpirationTime(request.ExpirationTime);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,26 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;
namespace Modules.Library.Application.Commands.Anime.Season.Properties;
public class SetReleaseDateCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public Guid SeasonId { get; set; }
public DateTimeOffset? Value { get; set; }
}
public class SetReleaseDateCommandHandler(IAnimeTitleGateway titleGateway) : IRequestHandler<SetReleaseDateCommand, Unit>
{
public async Task<Unit> Handle(SetReleaseDateCommand request, CancellationToken cancellationToken)
{
var title = await titleGateway.GetById(request.TitleId);
var season = title.Items.OfType<AnimeSeason>().FirstOrDefault(q => q.Id == request.SeasonId) ??
throw new Exception("Season not found");
season.CommonProperties.SetReleaseDate(request.Value);
await titleGateway.Update(title);
return Unit.Value;
}
}

View File

@ -1,30 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Rating.Api.Commands;
using Modules.User.Application;
namespace Modules.Library.Application.Commands.Anime.Season;
public class UnvoteTitleCommand : IRequest<Unit>
{
public Guid TitleId { get; init; }
}
public class UnvoteSeasonCommandHandler(IAnimeTitleGateway titleGateway, UserContext userContext, IMediator mediator) : IRequestHandler<UnvoteTitleCommand, Unit>
{
public async Task<Unit> Handle(UnvoteTitleCommand request, CancellationToken cancellationToken)
{
var user = await userContext.GetUserInfo(cancellationToken);
if (!user.IsAuthenticated || (!user.Id.HasValue || user.Id == Guid.Empty))
{
throw new Exception("User is not authenticated");
}
var subjectId = user.Id.Value;
var title = await titleGateway.GetById(request.TitleId, cancellationToken);
if (!title.Deleted)
{
await mediator.Send(new UnrateObjectCommand { ObjectId = title.Id, SubjectId = subjectId }, cancellationToken);
}
return Unit.Value;
}
}

View File

@ -1,36 +0,0 @@
using MediatR;
using Modules.Library.Application.Gateways;
using Modules.Rating.Api.Commands;
using Modules.User.Application;
namespace Modules.Library.Application.Commands.Anime.Season;
public class VoteSeasonCommand : IRequest<Unit>
{
public Guid TitleId { get; set; }
public ushort RatingPercentage { get; set; }
}
public class VoteSeasonCommandHandler(IAnimeTitleGateway titleGateway, UserContext userContext, IMediator mediator) : IRequestHandler<VoteSeasonCommand, Unit>
{
public async Task<Unit> Handle(VoteSeasonCommand request, CancellationToken cancellationToken)
{
var user = await userContext.GetUserInfo(cancellationToken);
if (!user.IsAuthenticated || (!user.Id.HasValue || user.Id == Guid.Empty))
{
throw new Exception("User is not authenticated");
}
var subjectId = user.Id.Value;
var title = await titleGateway.GetById(request.TitleId);
if (!title.Deleted)
{
await mediator.Send(new VoteForObjectCommand
{
ObjectId = title.Id,
SubjectId = subjectId,
RatingPercentage = request.RatingPercentage
}, cancellationToken);
}
return Unit.Value;
}
}

Some files were not shown because too many files have changed in this diff Show More