Skip to content

Commit

Permalink
Release Management Utility
Browse files Browse the repository at this point in the history
  • Loading branch information
da3dsoul committed Dec 22, 2023
1 parent 970c804 commit c06d889
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ public List<CL_AnimeEpisode_User> GetAllEpisodesWithMultipleFiles(int userID, bo
}
}

foreach (var ep in RepoFactory.AnimeEpisode.GetWithSoftDuplicates(ignoreVariations))
foreach (var ep in RepoFactory.AnimeEpisode.GetWithMultipleReleases(ignoreVariations))
{
if (onlyFinishedSeries)
{
Expand Down
2 changes: 1 addition & 1 deletion Shoko.Server/API/v2/Modules/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ public object GetMultipleFiles([FromQuery] API_Call_Parameters para)
var results = new Dictionary<int, Serie>();
try
{
var list = RepoFactory.AnimeEpisode.GetWithSoftDuplicates(true).ToList();
var list = RepoFactory.AnimeEpisode.GetWithMultipleReleases(true).ToList();
foreach (var ep in list)
{
var series = ep?.GetAnimeSeries();
Expand Down
65 changes: 0 additions & 65 deletions Shoko.Server/API/v3/Controllers/EpisodeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -464,71 +464,6 @@ public ActionResult SetWatchedStatusOnEpisode([FromRoute] int episodeID, [FromRo
return Ok();
}

/// <summary>
/// Get episodes with multiple files attached.
/// </summary>
/// <param name="seriesID">Shoko Series ID</param>
/// <param name="animeID">AniDB Anime ID</param>
/// <param name="includeDataFrom">Include data from selected <see cref="DataSource"/>s.</param>
/// <param name="includeFiles">Include files with the episodes.</param>
/// <param name="includeMediaInfo">Include media info data.</param>
/// <param name="includeAbsolutePaths">Include absolute paths for the file locations.</param>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <param name="onlyFinishedSeries">Only show finished series.</param>
/// <param name="pageSize">Limits the number of results per page. Set to 0 to disable the limit.</param>
/// <param name="page">Page number.</param>
/// <returns></returns>
[HttpGet("WithSoftDuplicates")]
public ActionResult<ListResult<Episode>> GetSoftDuplicatesForEpisode(
[FromQuery] int? seriesID = null,
[FromQuery] int? animeID = null,
[FromQuery, ModelBinder(typeof(CommaDelimitedModelBinder))] HashSet<DataSource> includeDataFrom = null,
[FromQuery] bool includeFiles = true,
[FromQuery] bool includeMediaInfo = true,
[FromQuery] bool includeAbsolutePaths = false,
[FromQuery] bool ignoreVariations = true,
[FromQuery] bool onlyFinishedSeries = false,
[FromQuery, Range(0, 1000)] int pageSize = 100,
[FromQuery, Range(1, int.MaxValue)] int page = 1)
{
if (seriesID.HasValue && !animeID.HasValue && seriesID.Value > 0)
{
var series = RepoFactory.AnimeSeries.GetByID(seriesID.Value);
if (series == null)
return new ListResult<Episode>();

if (!User.AllowedSeries(series))
return new ListResult<Episode>();
animeID = series.AniDB_ID;
}
else if (animeID.HasValue && animeID.Value > 0)
{
var anime = RepoFactory.AniDB_Anime.GetByAnimeID(animeID.Value);
if (anime == null)
return new ListResult<Episode>();

if (!User.AllowedAnime(anime))
return new ListResult<Episode>();
}
else if (animeID.HasValue && animeID.Value == 0)
{
animeID = null;
}

IEnumerable<SVR_AnimeEpisode> enumerable =
RepoFactory.AnimeEpisode.GetWithSoftDuplicates(ignoreVariations, animeID);
if (onlyFinishedSeries)
{
var dictSeriesFinishedAiring = RepoFactory.AnimeSeries.GetAll()
.ToDictionary(a => a.AnimeSeriesID, a => a.GetAnime().GetFinishedAiring());
enumerable = enumerable.Where(episode =>
dictSeriesFinishedAiring.TryGetValue(episode.AnimeSeriesID, out var finishedAiring) && finishedAiring);
}

return enumerable
.ToListResult(episode => new Episode(HttpContext, episode, includeDataFrom, includeFiles, includeMediaInfo, includeAbsolutePaths), page, pageSize);
}

/// <summary>
/// Get all episodes with no files.
/// </summary>
Expand Down
183 changes: 183 additions & 0 deletions Shoko.Server/API/v3/Controllers/ReleaseManagementController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Shoko.Commons.Extensions;
using Shoko.Server.API.Annotations;
using Shoko.Server.API.ModelBinders;
using Shoko.Server.API.v3.Helpers;
using Shoko.Server.API.v3.Models.Common;
using Shoko.Server.API.v3.Models.Shoko;
using Shoko.Server.Models;
using Shoko.Server.Repositories;
using Shoko.Server.Settings;

namespace Shoko.Server.API.v3.Controllers;

[ApiController]
[Route("/api/v{version:apiVersion}/[controller]")]
[ApiV3]
public class ReleaseManagementController : BaseController
{
private readonly ILogger<ReleaseManagementController> _logger;
private readonly SeriesFactory _seriesFactory;

/// <summary>
/// Get series with multiple releases.
/// </summary>
/// <param name="includeDataFrom">Include data from selected <see cref="DataSource"/>s.</param>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <param name="onlyFinishedSeries">Only show finished series.</param>
/// <param name="pageSize">Limits the number of results per page. Set to 0 to disable the limit.</param>
/// <param name="page">Page number.</param>
/// <returns></returns>
[HttpGet("Series")]
public ActionResult<ListResult<SeriesWithMultipleReleasesResult>> GetSeriesWithMultipleReleases(
[FromQuery, ModelBinder(typeof(CommaDelimitedModelBinder))] HashSet<DataSource> includeDataFrom = null,
[FromQuery] bool ignoreVariations = true,
[FromQuery] bool onlyFinishedSeries = false,
[FromQuery, Range(0, 1000)] int pageSize = 100,
[FromQuery, Range(1, int.MaxValue)] int page = 1)
{
IEnumerable<SVR_AnimeSeries> enumerable = RepoFactory.AnimeSeries.GetWithMultipleReleases(ignoreVariations);
if (onlyFinishedSeries) enumerable = enumerable.Where(a => a.GetAnime().GetFinishedAiring());

return enumerable
.OrderBy(series => series.GetSeriesName())
.ThenBy(series => series.AniDB_ID)
.ToListResult(series => _seriesFactory.GetSeriesWithMultipleReleasesResult(series, false, includeDataFrom, ignoreVariations), page, pageSize);
}

/// <summary>
/// Get episodes with multiple files attached.
/// </summary>
/// <param name="seriesID">Shoko Series ID</param>
/// <param name="includeDataFrom">Include data from selected <see cref="DataSource"/>s.</param>
/// <param name="includeFiles">Include files with the episodes.</param>
/// <param name="includeMediaInfo">Include media info data.</param>
/// <param name="includeAbsolutePaths">Include absolute paths for the file locations.</param>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <param name="pageSize">Limits the number of results per page. Set to 0 to disable the limit.</param>
/// <param name="page">Page number.</param>
/// <returns></returns>
[HttpGet("Series/{seriesID}")]
public ActionResult<ListResult<Episode>> GetEpisodesForSeries(
int seriesID,
[FromQuery, ModelBinder(typeof(CommaDelimitedModelBinder))] HashSet<DataSource> includeDataFrom = null,
[FromQuery] bool includeFiles = true,
[FromQuery] bool includeMediaInfo = true,
[FromQuery] bool includeAbsolutePaths = false,
[FromQuery] bool ignoreVariations = true,
[FromQuery, Range(0, 1000)] int pageSize = 100,
[FromQuery, Range(1, int.MaxValue)] int page = 1)
{
var series = RepoFactory.AnimeSeries.GetByID(seriesID);
if (series == null)
return new ListResult<Episode>();

if (!User.AllowedSeries(series))
return new ListResult<Episode>();

IEnumerable<SVR_AnimeEpisode> enumerable = RepoFactory.AnimeEpisode.GetWithMultipleReleases(ignoreVariations);

return enumerable
.ToListResult(episode => new Episode(HttpContext, episode, includeDataFrom, includeFiles, includeMediaInfo, includeAbsolutePaths), page, pageSize);
}

/// <summary>
/// Get episodes with multiple files attached.
/// </summary>
/// <param name="includeDataFrom">Include data from selected <see cref="DataSource"/>s.</param>
/// <param name="includeFiles">Include files with the episodes.</param>
/// <param name="includeMediaInfo">Include media info data.</param>
/// <param name="includeAbsolutePaths">Include absolute paths for the file locations.</param>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <param name="pageSize">Limits the number of results per page. Set to 0 to disable the limit.</param>
/// <param name="page">Page number.</param>
/// <returns></returns>
[HttpGet("Episodes")]
public ActionResult<ListResult<Episode>> GetEpisodes(
[FromQuery, ModelBinder(typeof(CommaDelimitedModelBinder))] HashSet<DataSource> includeDataFrom = null,
[FromQuery] bool includeFiles = true,
[FromQuery] bool includeMediaInfo = true,
[FromQuery] bool includeAbsolutePaths = false,
[FromQuery] bool ignoreVariations = true,
[FromQuery, Range(0, 1000)] int pageSize = 100,
[FromQuery, Range(1, int.MaxValue)] int page = 1)
{
IEnumerable<SVR_AnimeEpisode> enumerable = RepoFactory.AnimeEpisode.GetWithMultipleReleases(ignoreVariations);

return enumerable
.ToListResult(episode => new Episode(HttpContext, episode, includeDataFrom, includeFiles, includeMediaInfo, includeAbsolutePaths), page, pageSize);
}

/// <summary>
/// Get the list of file ids to remove according to the file quality
/// preference.
/// </summary>
/// <param name="seriesID">Shoko Series ID</param>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <returns></returns>
[HttpGet("Series/{seriesID}/Episode/FilesToDelete")]
public ActionResult<List<int>> GetFileIdsWithPreference(
int seriesID,
[FromQuery] bool ignoreVariations = true
)
{
var series = RepoFactory.AnimeSeries.GetByID(seriesID);
if (series == null)
return new List<int>();

if (!User.AllowedSeries(series))
return new List<int>();

IEnumerable<SVR_AnimeEpisode> enumerable = RepoFactory.AnimeEpisode.GetWithMultipleReleases(ignoreVariations);

return enumerable
.SelectMany(episode =>
{
var files = episode.GetVideoLocals();
files.Sort(FileQualityFilter.CompareTo);
return files
.Skip(FileQualityFilter.Settings.MaxNumberOfFilesToKeep)
.Where(file => !FileQualityFilter.CheckFileKeep(file))
.Select(file => file.VideoLocalID);
})
.Distinct()
.ToList();
}

/// <summary>
/// Get the list of file ids to remove according to the file quality
/// preference.
/// </summary>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <returns></returns>
[HttpGet("Episode/FilesToDelete")]
public ActionResult<List<int>> GetFileIdsWithPreference(
[FromQuery] bool ignoreVariations = true
)
{
IEnumerable<SVR_AnimeEpisode> enumerable = RepoFactory.AnimeEpisode.GetWithMultipleReleases(ignoreVariations);

return enumerable
.SelectMany(episode =>
{
var files = episode.GetVideoLocals();
files.Sort(FileQualityFilter.CompareTo);
return files
.Skip(FileQualityFilter.Settings.MaxNumberOfFilesToKeep)
.Where(file => !FileQualityFilter.CheckFileKeep(file))
.Select(file => file.VideoLocalID);
})
.Distinct()
.ToList();
}

public ReleaseManagementController(ISettingsProvider settingsProvider, ILogger<ReleaseManagementController> logger, SeriesFactory seriesFactory) : base(settingsProvider)
{
_logger = logger;
_seriesFactory = seriesFactory;
}
}
35 changes: 0 additions & 35 deletions Shoko.Server/API/v3/Controllers/SeriesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2076,39 +2076,4 @@ private static void CheckTitlesStartsWith(SVR_AnimeSeries a, string query,

#endregion

#region Utility

/// <summary>
/// Get series with soft duplicates.
/// </summary>
/// <param name="includeDataFrom">Include data from selected <see cref="DataSource"/>s.</param>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <param name="onlyFinishedSeries">Only show finished series.</param>
/// <param name="pageSize">Limits the number of results per page. Set to 0 to disable the limit.</param>
/// <param name="page">Page number.</param>
/// <returns></returns>
[HttpGet("WithSoftDuplicates")]
public ActionResult<ListResult<SeriesWithDuplicatesResult>> GetSeriesWithSoftDuplicates(
[FromQuery, ModelBinder(typeof(CommaDelimitedModelBinder))] HashSet<DataSource> includeDataFrom = null,
[FromQuery] bool ignoreVariations = true,
[FromQuery] bool onlyFinishedSeries = false,
[FromQuery, Range(0, 1000)] int pageSize = 100,
[FromQuery, Range(1, int.MaxValue)] int page = 1)
{
IEnumerable<SVR_AnimeSeries> enumerable =
RepoFactory.AnimeSeries.GetWithSoftDuplicates(ignoreVariations);
if (onlyFinishedSeries)
{
var dictSeriesFinishedAiring = RepoFactory.AnimeSeries.GetAll()
.ToDictionary(a => a.AnimeSeriesID, a => a.GetAnime().GetFinishedAiring());
enumerable = enumerable.Where(a => a.GetAnime().GetFinishedAiring());
}

return enumerable
.OrderBy(series => series.GetSeriesName())
.ThenBy(series => series.AniDB_ID)
.ToListResult(series => _seriesFactory.GetSeriesWithDuplicatesResult(series, false, includeDataFrom, ignoreVariations), page, pageSize);
}

#endregion
}
65 changes: 0 additions & 65 deletions Shoko.Server/API/v3/Controllers/WebUIController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -305,71 +305,6 @@ public ActionResult<WebUISeriesFileSummary> GetSeriesFileSummary(
return new WebUISeriesFileSummary(series, type, includeEpisodeDetails, includeMissingFutureEpisodes, includeMissingUnknownEpisodes, groupBy);
}


/// <summary>
/// Get the list of file ids to remove according to the file quality
/// preference.
/// </summary>
/// <param name="seriesID">Shoko Series ID</param>
/// <param name="animeID">AniDB Anime ID</param>
/// <param name="ignoreVariations">Ignore manually toggled variations in the results.</param>
/// <param name="onlyFinishedSeries">Only show finished series.</param>
/// <returns></returns>
[HttpGet("Episode/WithSoftDuplicates/FilesToDelete")]
public ActionResult<List<int>> GetFileIdsWithPreference(
[FromQuery] int? seriesID = null,
[FromQuery] int? animeID = null,
[FromQuery] bool ignoreVariations = true,
[FromQuery] bool onlyFinishedSeries = false
)
{
if (seriesID.HasValue && !animeID.HasValue && seriesID.Value > 0)
{
var series = RepoFactory.AnimeSeries.GetByID(seriesID.Value);
if (series == null)
return new List<int>();

if (!User.AllowedSeries(series))
return new List<int>();
animeID = series.AniDB_ID;
}
else if (animeID.HasValue && animeID.Value > 0)
{
var anime = RepoFactory.AniDB_Anime.GetByAnimeID(animeID.Value);
if (anime == null)
return new List<int>();

if (!User.AllowedAnime(anime))
return new List<int>();
}
else if (animeID.HasValue && animeID.Value == 0)
{
animeID = null;
}

IEnumerable<SVR_AnimeEpisode> enumerable = RepoFactory.AnimeEpisode.GetWithSoftDuplicates(ignoreVariations, animeID);
if (onlyFinishedSeries)
{
var dictSeriesFinishedAiring = RepoFactory.AnimeSeries.GetAll()
.ToDictionary(a => a.AnimeSeriesID, a => a.GetAnime().GetFinishedAiring());
enumerable = enumerable.Where(episode =>
dictSeriesFinishedAiring.TryGetValue(episode.AnimeSeriesID, out var finishedAiring) && finishedAiring);
}

return enumerable
.SelectMany(episode =>
{
var files = episode.GetVideoLocals();
files.Sort(FileQualityFilter.CompareTo);
return files
.Skip(FileQualityFilter.Settings.MaxNumberOfFilesToKeep)
.Where(file => !FileQualityFilter.CheckFileKeep(file))
.Select(file => file.VideoLocalID);
})
.Distinct()
.ToList();
}

/// <summary>
/// Install a fresh copy of the web ui for the selected
/// <paramref name="channel"/>. Will only install if it detects that no
Expand Down
Loading

0 comments on commit c06d889

Please sign in to comment.