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

Plex: Show watched status for movie and TV requests #4991

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions src/Ombi.Api.Plex/IPlexApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public interface IPlexApi
Task<PlexFriends> GetUsers(string authToken);
Task<PlexAccount> GetAccount(string authToken);
Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, string sectionId);
Task<PlexMetadata> GetPlayed(string authToken, string uri, string sectionId, int maxNumberOfItems = 0);
Task<OAuthContainer> GetPin(int pinId);
Task<Uri> GetOAuthUrl(string code, string applicationUrl);
Task<PlexAddWrapper> AddUser(string emailAddress, string serverId, string authToken, int[] libs);
Expand Down
9 changes: 9 additions & 0 deletions src/Ombi.Api.Plex/Models/PlexMediaFilterType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Ombi.Api.Plex.Models
{
public enum PlexMediaFilterType
{
Movie = 1,
Show = 2,
Episode = 4,
}
}
24 changes: 24 additions & 0 deletions src/Ombi.Api.Plex/PlexApi.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading;
Expand Down Expand Up @@ -212,6 +213,29 @@ public async Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, s
return await Api.Request<PlexMetadata>(request);
}


public async Task<PlexMetadata> GetPlayed(string authToken, string uri, string sectionId, int maxNumberOfItems)
{
var request = new Request($"library/sections/{sectionId}/all", uri, HttpMethod.Get);
await AddHeaders(request, authToken);
request.AddQueryString("unwatched", "0");
request.AddQueryString("sort", "lastViewedAt:desc");

// for some reason, we need to explicitely include episodes for them to be returned by the API (movies are fine)
// also the order seems of importance: "4,1" doesn't work but "1,4" does work
var types = new List<int> { (int) PlexMediaFilterType.Movie, (int) PlexMediaFilterType.Episode };
var typeFilter = string.Join(",", types);
request.AddQueryString("type", typeFilter);

if (maxNumberOfItems != 0)
{
AddLimitHeaders(request, 0, maxNumberOfItems);
}


return await Api.Request<PlexMetadata>(request);
}

public async Task<OAuthContainer> GetPin(int pinId)
{
var request = new Request($"api/v2/pins/{pinId}", "https://plex.tv/", HttpMethod.Get);
Expand Down
2 changes: 1 addition & 1 deletion src/Ombi.Core.Tests/Authentication/OmbiUserManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void Setup()
AuthenticationSettings.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(new AuthenticationSettings());
_um = new OmbiUserManager(UserStore.Object, null, null, null, null, null, null, null, null,
PlexApi.Object, null, null, null, null, AuthenticationSettings.Object);
PlexApi.Object, null, null, null, null, AuthenticationSettings.Object, null);
}

public OmbiUserManager _um { get; set; }
Expand Down
40 changes: 39 additions & 1 deletion src/Ombi.Core/Authentication/OmbiUserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
Expand All @@ -41,6 +42,7 @@
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;

namespace Ombi.Core.Authentication
{
Expand All @@ -52,7 +54,7 @@ public OmbiUserManager(IUserStore<OmbiUser> store, IOptions<IdentityOptions> opt
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<OmbiUser>> logger, IPlexApi plexApi,
IEmbyApiFactory embyApi, ISettingsService<EmbySettings> embySettings,
IJellyfinApiFactory jellyfinApi, ISettingsService<JellyfinSettings> jellyfinSettings,
ISettingsService<AuthenticationSettings> auth)
ISettingsService<AuthenticationSettings> auth, IRepository<PlexWatchlistUserError> userError)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
_plexApi = plexApi;
Expand All @@ -61,6 +63,8 @@ public OmbiUserManager(IUserStore<OmbiUser> store, IOptions<IdentityOptions> opt
_embySettings = embySettings;
_jellyfinSettings = jellyfinSettings;
_authSettings = auth;
_userError = userError;
_logger = logger;
}

private readonly IPlexApi _plexApi;
Expand All @@ -69,6 +73,8 @@ public OmbiUserManager(IUserStore<OmbiUser> store, IOptions<IdentityOptions> opt
private readonly ISettingsService<EmbySettings> _embySettings;
private readonly ISettingsService<JellyfinSettings> _jellyfinSettings;
private readonly ISettingsService<AuthenticationSettings> _authSettings;
private readonly IRepository<PlexWatchlistUserError> _userError;
private readonly Microsoft.Extensions.Logging.ILogger _logger;
private string _clientIpAddress;
public string ClientIpAddress { get => _clientIpAddress; set => _clientIpAddress = value; }

Expand Down Expand Up @@ -139,6 +145,38 @@ public async Task<OmbiUser> GetOmbiUserFromPlexToken(string plexToken)

}

public async Task<ICollection<OmbiUser>> GetPlexUsersWithValidTokens()
{
var plexUsersWithTokens = Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList();
_logger.LogDebug($"Found {plexUsersWithTokens.Count} users with tokens");
var result = new List<OmbiUser>();

foreach (var user in plexUsersWithTokens)
{
// Check if the user has errors and the token is the same (not refreshed)
var failedUser = await _userError.GetAll().Where(x => x.UserId == user.Id).FirstOrDefaultAsync();
if (failedUser != null)
{
if (failedUser.MediaServerToken.Equals(user.MediaServerToken))
{
_logger.LogWarning($"Skipping user '{user.UserName}' as they failed previously and the token has not yet been refreshed. They need to re-authenticate with Ombi");
continue;
}
else
{
// remove that guy
await _userError.Delete(failedUser);
failedUser = null;
}
}
if (failedUser == null)
{
result.Add(user);
}
}
return result;

}

/// <summary>
/// Sign the user into plex and make sure we can get the authentication token.
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 @@ -244,6 +244,7 @@ public static void RegisterJobs(this IServiceCollection services)
services.AddSingleton<IJobFactory, IoCJobFactory>();

services.AddTransient<IPlexContentSync, PlexContentSync>();
services.AddTransient<IPlexPlayedSync, PlexPlayedSync>();
services.AddTransient<IPlexWatchlistImport, PlexWatchlistImport>();
services.AddTransient<IEmbyContentSync, EmbyContentSync>();
services.AddTransient<IEmbyPlayedSync, EmbyPlayedSync>();
Expand Down
8 changes: 8 additions & 0 deletions src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexPlayedSync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Quartz;

namespace Ombi.Schedule.Jobs
{
public interface IPlexPlayedSync : IJob
{
}
}
Loading