Skip to content

Commit

Permalink
feat(emby): Show watched status for TV requests
Browse files Browse the repository at this point in the history
* feat(emby): Show watched status for TV requests

* Consider only requested episodes in  played progress

* Clarify tv watched progress tooltip

* Fix unrespected code guidelines
  • Loading branch information
sephrat authored Jun 2, 2023
1 parent 151efe1 commit 1f37de0
Show file tree
Hide file tree
Showing 24 changed files with 1,624 additions and 42 deletions.
26 changes: 19 additions & 7 deletions src/Ombi.Api.Emby/EmbyApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,18 +254,30 @@ private static void AddHeaders(Request req, string apiKey)
req.AddHeader("Device", "Ombi");
}

public async Task<EmbyItemContainer<EmbyMovie>> GetMoviesPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri)
{
return await GetPlayed<EmbyMovie>("Movie", apiKey, userId, baseUri, startIndex, count, parentIdFilder);
}

private async Task<EmbyItemContainer<T>> GetPlayed<T>(string type, string apiKey, string userId, string baseUri, int startIndex, int count, string parentIdFilder = default)
public async Task<EmbyItemContainer<EmbyMovie>> GetMoviesPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri) =>
await GetPlayed<EmbyMovie>("Movie", apiKey, userId, baseUri, startIndex, count, parentIdFilder, "ProviderIds");

public async Task<EmbyItemContainer<EmbyEpisodes>> GetTvPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri) =>
await GetPlayed<EmbyEpisodes>("Episode", apiKey, userId, baseUri, startIndex, count, parentIdFilder);

private async Task<EmbyItemContainer<T>> GetPlayed<T>(
string type,
string apiKey,
string userId,
string baseUri,
int startIndex,
int count,
string parentIdFilder = default,
string fields = default)
{
var request = new Request($"emby/items", baseUri, HttpMethod.Get);

request.AddQueryString("Recursive", true.ToString());
request.AddQueryString("IncludeItemTypes", type);
request.AddQueryString("Fields", "ProviderIds");
if (!string.IsNullOrEmpty(fields))
{
request.AddQueryString("Fields", fields);
}
request.AddQueryString("UserId", userId);
request.AddQueryString("isPlayed", true.ToString());

Expand Down
1 change: 1 addition & 0 deletions src/Ombi.Api.Emby/IBaseEmbyApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ Task<EmbyItemContainer<EmbyMovie>> GetCollection(string mediaId,
Task<EmbyItemContainer<EmbySeries>> RecentlyAddedShows(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);

Task<EmbyItemContainer<EmbyMovie>> GetMoviesPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
Task<EmbyItemContainer<EmbyEpisodes>> GetTvPlayed(string apiKey, string parentIdFilder, int startIndex, int count, string userId, string baseUri);
}
}
81 changes: 68 additions & 13 deletions src/Ombi.Core/Engine/TvRequestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine
public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, ICurrentUser user,
INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ILogger<TvRequestEngine> logger,
ITvSender sender, IRepository<RequestLog> rl, ISettingsService<OmbiSettings> settings, ICacheService cache,
IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService) : base(user, requestService, rule, manager, cache, settings, sub)
IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService,
IUserPlayedEpisodeRepository userPlayedEpisodeRepository) : base(user, requestService, rule, manager, cache, settings, sub)
{
TvApi = tvApi;
MovieDbApi = movApi;
Expand All @@ -44,6 +45,7 @@ public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain
TvSender = sender;
_requestLog = rl;
_mediaCacheService = mediaCacheService;
_userPlayedEpisodeRepository = userPlayedEpisodeRepository;
}

private INotificationHelper NotificationHelper { get; }
Expand All @@ -54,6 +56,7 @@ public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain
private readonly ILogger<TvRequestEngine> _logger;
private readonly IRepository<RequestLog> _requestLog;
private readonly IMediaCacheService _mediaCacheService;
private readonly IUserPlayedEpisodeRepository _userPlayedEpisodeRepository;

public async Task<RequestEngineResult> RequestTvShow(TvRequestViewModel tv)
{
Expand Down Expand Up @@ -292,7 +295,7 @@ public async Task<RequestsViewModel<TvRequests>> GetRequests(int count, int posi
.Skip(position).Take(count).ToListAsync();

}
await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);

return new RequestsViewModel<TvRequests>
{
Expand Down Expand Up @@ -328,7 +331,7 @@ public async Task<RequestsViewModel<TvRequests>> GetRequestsLite(int count, int
return new RequestsViewModel<TvRequests>();
}

await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);

return new RequestsViewModel<TvRequests>
{
Expand All @@ -351,7 +354,7 @@ public async Task<IEnumerable<TvRequests>> GetRequests()
allRequests = await TvRepository.Get().ToListAsync();
}

await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);
return allRequests;
}

Expand Down Expand Up @@ -396,7 +399,7 @@ public async Task<RequestsViewModel<ChildRequests>> GetRequests(int count, int p
? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();

await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);

// Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
Expand Down Expand Up @@ -469,7 +472,7 @@ public async Task<RequestsViewModel<ChildRequests>> GetRequests(int count, int p
? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();

await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);

// Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
Expand Down Expand Up @@ -523,7 +526,7 @@ public async Task<RequestsViewModel<ChildRequests>> GetUnavailableRequests(int c
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();
await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);

// Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
Expand Down Expand Up @@ -551,7 +554,7 @@ public async Task<IEnumerable<TvRequests>> GetRequestsLite()
allRequests = await TvRepository.GetLite().ToListAsync();
}

await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);
return allRequests;
}

Expand All @@ -570,7 +573,7 @@ public async Task<TvRequests> GetTvRequest(int requestId)
request = await TvRepository.Get().Where(x => x.Id == requestId).FirstOrDefaultAsync();
}

await CheckForSubscription(shouldHide, new List<TvRequests>{request});
await FillAdditionalFields(shouldHide, new List<TvRequests>{request});
return request;
}

Expand Down Expand Up @@ -624,7 +627,7 @@ public async Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId)
allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync();
}

await CheckForSubscription(shouldHide, allRequests);
await FillAdditionalFields(shouldHide, allRequests);

return allRequests;
}
Expand All @@ -643,7 +646,7 @@ public async Task<IEnumerable<TvRequests>> SearchTvRequest(string search)
}
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();

await CheckForSubscription(shouldHide, results);
await FillAdditionalFields(shouldHide, results);
return results;
}

Expand Down Expand Up @@ -864,14 +867,20 @@ public async Task<int> GetTotal()
}
}

private async Task CheckForSubscription(HideResult shouldHide, List<TvRequests> x)
private async Task FillAdditionalFields(HideResult shouldHide, List<TvRequests> x)
{
foreach (var tvRequest in x)
{
await CheckForSubscription(shouldHide, tvRequest.ChildRequests);
await FillAdditionalFields(shouldHide, tvRequest.ChildRequests);
}
}

private async Task FillAdditionalFields(HideResult shouldHide, List<ChildRequests> childRequests)
{
await CheckForSubscription(shouldHide, childRequests);
CheckForPlayed(shouldHide, childRequests);
}

private async Task CheckForSubscription(HideResult shouldHide, List<ChildRequests> childRequests)
{
var sub = _subscriptionRepository.GetAll();
Expand All @@ -896,6 +905,52 @@ private async Task CheckForSubscription(HideResult shouldHide, List<ChildRequest
}
}

private class EpisodeKey
{
public int SeasonNumber;
public int EpisodeNumber;
}

private void CheckForPlayed(HideResult shouldHide, List<ChildRequests> childRequests)
{
var theMovieDbIds = childRequests.Select(x => x.Id);
foreach (var request in childRequests)
{
var requestedEpisodes = GetEpisodesKeys(request);

var playedEpisodes = _userPlayedEpisodeRepository
.GetAll()
.Where(x => x.TheMovieDbId == request.Id && x.UserId == request.RequestedUserId)
.AsEnumerable()
.Join(requestedEpisodes,
played => new { played.SeasonNumber, played.EpisodeNumber },
requested => new { requested.SeasonNumber, requested.EpisodeNumber },
(played, requested) => new { played });

var playedCount = playedEpisodes.Count();
var toWatchCount = requestedEpisodes.Count();
request.RequestedUserPlayedProgress = 100 * playedCount / toWatchCount;

}
}

private List<EpisodeKey> GetEpisodesKeys(ChildRequests request)
{
List<EpisodeKey> result = new List<EpisodeKey>();
foreach(var season in request.SeasonRequests)
{
foreach(var episode in season.Episodes)
{
result.Add(new EpisodeKey
{
SeasonNumber = season.SeasonNumber,
EpisodeNumber = episode.EpisodeNumber
});
}
}
return result;
}

private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest, string requestOnBehalf, int rootFolder, int qualityProfile)
{
// Add the child
Expand Down
1 change: 1 addition & 0 deletions src/Ombi.DependencyInjection/IocExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ public static void RegisterStore(this IServiceCollection services)
services.AddScoped<IJellyfinContentRepository, JellyfinContentRepository>();
services.AddScoped<INotificationTemplatesRepository, NotificationTemplatesRepository>();
services.AddScoped<IUserPlayedMovieRepository, UserPlayedMovieRepository>();
services.AddScoped<IUserPlayedEpisodeRepository, UserPlayedEpisodeRepository>();

services.AddScoped<ITvRequestRepository, TvRequestRepository>();
services.AddScoped<IMovieRequestRepository, MovieRequestRepository>();
Expand Down
Loading

0 comments on commit 1f37de0

Please sign in to comment.