Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/episode groups #20

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added: Episode Group selection / fetching
  • Loading branch information
Tyr3al committed Jun 29, 2023
commit 751f545769fb53df5e466e554ad336125698f4fd
36 changes: 36 additions & 0 deletions AutoTag.Core/TV/ShowResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Text.RegularExpressions;
using TMDbLib.Objects.Search;
using TMDbLib.Objects.TvShows;

namespace AutoTag.Core.TV;

public class ShowResult
{
public SearchTv TvSearchResult { get; }
private TvGroupCollection? GroupCollection { get; set; }

public ShowResult(SearchTv tvSearchResult)
{
TvSearchResult = tvSearchResult;
}

/// <summary>
/// Add optional episode group to tv result
/// </summary>
/// <param name="episodeGroup">Episode group fetched from tmdb api</param>
public void AddEpisodeGroup(TvGroupCollection episodeGroup)
{
GroupCollection = episodeGroup;
}

public static implicit operator ShowResult(SearchTv tv) => new(tv);

/// <summary>
/// Generates <see cref="ShowResult"/> list from any <see cref="SearchTv"/> enumerable
/// </summary>
/// <param name="results">Result from tmdb client</param>
public static List<ShowResult> FromSearchResults(IEnumerable<SearchTv> results)
{
return results.Select(result => (ShowResult)result).ToList();
}
}
76 changes: 49 additions & 27 deletions AutoTag.Core/TV/TVProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
using System.Globalization;
using System.Text.RegularExpressions;
using System.Text.RegularExpressions;

using TMDbLib.Client;
using TMDbLib.Objects.General;
using TMDbLib.Objects.Search;
using TMDbLib.Objects.TvShows;

namespace AutoTag.Core.TV;
public class TVProcessor : IProcessor, IDisposable
public class TVProcessor : IProcessor
{
private readonly TMDbClient _tmdb;
private Dictionary<string, List<SearchTv>> _shows =
new Dictionary<string, List<SearchTv>>(StringComparer.OrdinalIgnoreCase);
private Dictionary<(int, int), TvSeason> _seasons =
new Dictionary<(int, int), TvSeason>();
private Dictionary<(string, int), string> _seasonPosters =
new Dictionary<(string, int), string>();
private readonly Dictionary<string, List<ShowResult>> _shows = new(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<(int, int), TvSeason> _seasons = new();
private readonly Dictionary<(string, int), string> _seasonPosters = new();
private IEnumerable<Genre> Genres = Enumerable.Empty<Genre>();

public TVProcessor(string apiKey, AutoTagConfig config)
Expand All @@ -34,7 +30,7 @@ public async Task<bool> ProcessAsync(
FileWriter writer
)
{
TVFileMetadata result = new TVFileMetadata();
var result = new TVFileMetadata();

#region Filename parsing
TVFileMetadata episodeData;
Expand Down Expand Up @@ -95,7 +91,8 @@ FileWriter writer
.OrderByDescending(result => SeriesNameSimilarity(episodeData.SeriesName, result.Name))
.ToList();

if (config.ManualMode)
// using episode groups, requires the manual selection of a show
if (config.ManualMode || config.EpisodeGroup)
{
int? chosen = selectResult(seriesResults
.Select(t => (t.Name, t.FirstAirDate?.Year.ToString() ?? "Unknown"))
Expand All @@ -104,7 +101,7 @@ FileWriter writer

if (chosen.HasValue)
{
_shows.Add(episodeData.SeriesName, new List<SearchTv> { seriesResults[chosen.Value] });
_shows.Add(episodeData.SeriesName, new List<ShowResult> { seriesResults[chosen.Value] });
}
else
{
Expand All @@ -120,35 +117,60 @@ FileWriter writer
}
else
{
_shows.Add(episodeData.SeriesName, seriesResults);
_shows.Add(episodeData.SeriesName, ShowResult.FromSearchResults(seriesResults));
}
}

if (config.EpisodeGroup)
{
var seriesResult = _shows[episodeData.SeriesName].First();
var tvShow = await _tmdb.GetTvShowAsync(seriesResult.TvSearchResult.Id, TvShowMethods.EpisodeGroups);
var groups = tvShow.EpisodeGroups;

// TODO: add group filter, to get only those, that have seasons

var chosenGroup = selectResult(groups.Results.Select(group =>
($"[{group.Type}] {group.Name}", $"S: {group.GroupCount} E: {group.EpisodeCount}")).ToList());

if (chosenGroup.HasValue)
{
var groupInfo = await _tmdb.GetTvEpisodeGroupsAsync(groups.Results.First().Id, config.Language);
seriesResult.AddEpisodeGroup(groupInfo);
}
else
{
setStatus("File skipped", MessageType.Warning);
return true;
}

}


// try searching for each series search result
foreach (var show in _shows[episodeData.SeriesName])
{
result.Id = show.Id;
result.SeriesName = show.Name;
var showData = show.TvSearchResult;

result.Id = showData.Id;
result.SeriesName = showData.Name;

TvSeason? seasonResult;
if (!_seasons.TryGetValue((show.Id, episodeData.Season), out seasonResult))
if (!_seasons.TryGetValue((showData.Id, episodeData.Season), out seasonResult))
{
seasonResult = await _tmdb.GetTvSeasonAsync(show.Id, episodeData.Season);
seasonResult = await _tmdb.GetTvSeasonAsync(showData.Id, episodeData.Season);

if (seasonResult == null)
{
if (show.Id == _shows[episodeData.SeriesName].Last().Id)
if (showData.Id == _shows[episodeData.SeriesName].Last().TvSearchResult.Id)
{
setStatus($"Error: Cannot find {episodeData} on TheMovieDB", MessageType.Error);

return false;
}
continue;
}
else
{
_seasons.Add((show.Id, episodeData.Season), seasonResult);
}

_seasons.Add((showData.Id, episodeData.Season), seasonResult);
}
result.SeasonEpisodes = seasonResult.Episodes.Count;

Expand All @@ -157,10 +179,10 @@ FileWriter writer
result.CoverURL = $"https://image.tmdb.org/t/p/original/{seasonResult.PosterPath}";
}

TvSeasonEpisode? episodeResult = seasonResult.Episodes.FirstOrDefault(e => e.EpisodeNumber == episodeData.Episode);
var episodeResult = seasonResult.Episodes.FirstOrDefault(e => e.EpisodeNumber == episodeData.Episode);
if (episodeResult == default)
{
if (show.Id == _shows[episodeData.SeriesName].Last().Id)
if (showData.Id == _shows[episodeData.SeriesName].Last().TvSearchResult.Id)
{
setStatus($"Error: Cannot find {episodeData} on TheMovieDB", MessageType.Error);

Expand All @@ -177,13 +199,13 @@ FileWriter writer
{
Genres = await _tmdb.GetTvGenresAsync();
}
result.Genres = show.GenreIds.Select(gId => Genres.First(g => g.Id == gId).Name).ToArray();
result.Genres = showData.GenreIds.Select(gId => Genres.First(g => g.Id == gId).Name).ToArray();

if (config.ExtendedTagging && file.Taggable)
{
result.Director = episodeResult.Crew.FirstOrDefault(c => c.Job == "Director")?.Name;

var credits = await _tmdb.GetTvEpisodeCreditsAsync(show.Id, result.Season, result.Episode);
var credits = await _tmdb.GetTvEpisodeCreditsAsync(showData.Id, result.Season, result.Episode);
result.Actors = credits.Cast.Select(c => c.Name).ToArray();
result.Characters = credits.Cast.Select(c => c.Character).ToArray();
}
Expand Down Expand Up @@ -224,7 +246,7 @@ FileWriter writer

return taggingSuccess && result.Success && result.Complete;
}

private double SeriesNameSimilarity(string parsedName, string seriesName)
{
if (seriesName.ToLower().Contains(parsedName.ToLower()))
Expand Down