Skip to content

Commit c222f1a

Browse files
authored
feat: Watchlist history errors(Ombi-app#4741)
[skip ci]
1 parent 15fe04d commit c222f1a

31 files changed

+3289
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
using System.Collections.Generic;
2+
using System.Text.Json.Serialization;
23

34
namespace Ombi.Api.Plex.Models
45
{
56
public class PlexWatchlistContainer
67
{
78
public PlexWatchlist MediaContainer { get; set; }
9+
[JsonIgnore]
10+
public bool AuthError { get; set; }
811
}
912
}

src/Ombi.Api.Plex/PlexApi.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Net;
23
using System.Net.Http;
34
using System.Threading;
45
using System.Threading.Tasks;
@@ -295,9 +296,18 @@ public async Task<PlexWatchlistContainer> GetWatchlist(string plexToken, Cancell
295296
var request = new Request("library/sections/watchlist/all", WatchlistUri, HttpMethod.Get);
296297
await AddHeaders(request, plexToken);
297298

298-
var result = await Api.Request<PlexWatchlistContainer>(request, cancellationToken);
299+
var result = await Api.Request(request, cancellationToken);
299300

300-
return result;
301+
if (result.StatusCode.Equals(HttpStatusCode.Unauthorized))
302+
{
303+
return new PlexWatchlistContainer
304+
{
305+
AuthError = true
306+
};
307+
}
308+
309+
var receivedString = await result.Content.ReadAsStringAsync(cancellationToken);
310+
return JsonConvert.DeserializeObject<PlexWatchlistContainer>(receivedString);
301311
}
302312

303313
public async Task<PlexWatchlistMetadataContainer> GetWatchlistMetadata(string ratingKey, string plexToken, CancellationToken cancellationToken)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using MockQueryable.Moq;
2+
using Moq.AutoMock;
3+
using NUnit.Framework;
4+
using Ombi.Core.Models;
5+
using Ombi.Core.Services;
6+
using Ombi.Store.Entities;
7+
using Ombi.Store.Repository;
8+
using Ombi.Test.Common;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
using UserType = Ombi.Store.Entities.UserType;
14+
15+
namespace Ombi.Core.Tests.Services
16+
{
17+
public class PlexServiceTests
18+
{
19+
20+
private PlexService _subject;
21+
private AutoMocker _mocker;
22+
23+
[SetUp]
24+
public void Setup()
25+
{
26+
_mocker = new AutoMocker();
27+
_subject = _mocker.CreateInstance<PlexService>();
28+
}
29+
30+
[Test]
31+
public async Task GetWatchListUsers_AllUsersSynced()
32+
{
33+
var userMock = MockHelper.MockUserManager(new List<OmbiUser>
34+
{
35+
new OmbiUser
36+
{
37+
MediaServerToken = "token",
38+
Id = "1",
39+
UserName = "user1",
40+
UserType = UserType.PlexUser,
41+
},
42+
new OmbiUser
43+
{
44+
MediaServerToken = "token",
45+
Id = "2",
46+
UserName = "user2",
47+
UserType = UserType.PlexUser,
48+
},
49+
new OmbiUser
50+
{
51+
MediaServerToken = "token",
52+
Id = "2",
53+
UserName = "user2",
54+
UserType = UserType.LocalUser,
55+
}
56+
});
57+
58+
_mocker.Use(userMock.Object);
59+
_subject = _mocker.CreateInstance<PlexService>();
60+
61+
_mocker.Setup<IRepository<PlexWatchlistUserError>, IQueryable<PlexWatchlistUserError>>(x => x.GetAll())
62+
.Returns(new List<PlexWatchlistUserError>().AsQueryable().BuildMock().Object);
63+
64+
var result = await _subject.GetWatchlistUsers(CancellationToken.None);
65+
66+
Assert.Multiple(() =>
67+
{
68+
Assert.That(result.All(x => x.SyncStatus == WatchlistSyncStatus.Successful));
69+
Assert.That(result.Count, Is.EqualTo(2));
70+
});
71+
}
72+
73+
[Test]
74+
public async Task GetWatchListUsers_NotEnabled()
75+
{
76+
var userMock = MockHelper.MockUserManager(new List<OmbiUser>
77+
{
78+
new OmbiUser
79+
{
80+
MediaServerToken = "",
81+
Id = "1",
82+
UserName = "user1",
83+
UserType = UserType.PlexUser,
84+
},
85+
new OmbiUser
86+
{
87+
MediaServerToken = null,
88+
Id = "2",
89+
UserName = "user2",
90+
UserType = UserType.PlexUser,
91+
},
92+
});
93+
94+
_mocker.Use(userMock.Object);
95+
_subject = _mocker.CreateInstance<PlexService>();
96+
97+
_mocker.Setup<IRepository<PlexWatchlistUserError>, IQueryable<PlexWatchlistUserError>>(x => x.GetAll())
98+
.Returns(new List<PlexWatchlistUserError>().AsQueryable().BuildMock().Object);
99+
100+
var result = await _subject.GetWatchlistUsers(CancellationToken.None);
101+
102+
Assert.Multiple(() =>
103+
{
104+
Assert.That(result.All(x => x.SyncStatus == WatchlistSyncStatus.NotEnabled));
105+
Assert.That(result.Count, Is.EqualTo(2));
106+
});
107+
}
108+
109+
110+
[Test]
111+
public async Task GetWatchListUsers_Failed()
112+
{
113+
var userMock = MockHelper.MockUserManager(new List<OmbiUser>
114+
{
115+
new OmbiUser
116+
{
117+
MediaServerToken = "test",
118+
Id = "1",
119+
UserName = "user1",
120+
UserType = UserType.PlexUser,
121+
},
122+
});
123+
124+
_mocker.Use(userMock.Object);
125+
_subject = _mocker.CreateInstance<PlexService>();
126+
127+
_mocker.Setup<IRepository<PlexWatchlistUserError>, IQueryable<PlexWatchlistUserError>>(x => x.GetAll())
128+
.Returns(new List<PlexWatchlistUserError>
129+
{
130+
new PlexWatchlistUserError
131+
{
132+
UserId = "1",
133+
MediaServerToken = "test",
134+
}
135+
}.AsQueryable().BuildMock().Object);
136+
137+
var result = await _subject.GetWatchlistUsers(CancellationToken.None);
138+
139+
Assert.Multiple(() =>
140+
{
141+
Assert.That(result.All(x => x.SyncStatus == WatchlistSyncStatus.Failed));
142+
Assert.That(result.Count, Is.EqualTo(1));
143+
});
144+
}
145+
}
146+
}

src/Ombi.Core/Engine/UserDeletionEngine.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class UserDeletionEngine : IUserDeletionEngine
2626
private readonly IMusicRequestRepository _musicRepository;
2727
private readonly IRepository<Votes> _voteRepository;
2828
private readonly IRepository<MobileDevices> _mobileDevicesRepository;
29+
private readonly IRepository<PlexWatchlistUserError> _watchlistUserError;
2930

3031
public UserDeletionEngine(IMovieRequestRepository movieRepository,
3132
OmbiUserManager userManager,
@@ -39,7 +40,8 @@ public UserDeletionEngine(IMovieRequestRepository movieRepository,
3940
IRepository<UserNotificationPreferences> notificationPreferencesRepo,
4041
IRepository<UserQualityProfiles> qualityProfilesRepo,
4142
IRepository<Votes> voteRepository,
42-
IRepository<MobileDevices> mobileDevicesRepository
43+
IRepository<MobileDevices> mobileDevicesRepository,
44+
IRepository<PlexWatchlistUserError> watchlistUserError
4345
)
4446
{
4547
_movieRepository = movieRepository;
@@ -56,6 +58,7 @@ IRepository<MobileDevices> mobileDevicesRepository
5658
_userQualityProfiles = qualityProfilesRepo;
5759
_voteRepository = voteRepository;
5860
_mobileDevicesRepository = mobileDevicesRepository;
61+
_watchlistUserError = watchlistUserError;
5962
}
6063

6164

@@ -68,6 +71,7 @@ public async Task<IdentityResult> DeleteUser(OmbiUser userToDelete)
6871
var musicRequested = _musicRepository.GetAll().Where(x => x.RequestedUserId == userId);
6972
var notificationPreferences = _userNotificationPreferences.GetAll().Where(x => x.UserId == userId);
7073
var userQuality = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == userId);
74+
var watchlistError = await _watchlistUserError.GetAll().FirstOrDefaultAsync(x => x.UserId == userId);
7175

7276
if (moviesUserRequested.Any())
7377
{
@@ -89,6 +93,10 @@ public async Task<IdentityResult> DeleteUser(OmbiUser userToDelete)
8993
{
9094
await _userQualityProfiles.Delete(userQuality);
9195
}
96+
if (watchlistError != null)
97+
{
98+
await _watchlistUserError.Delete(watchlistError);
99+
}
92100

93101
// Delete any issues and request logs
94102
var issues = _issuesRepository.GetAll().Where(x => x.UserReportedId == userId);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Ombi.Core.Models
2+
{
3+
public class PlexUserWatchlistModel
4+
{
5+
public string UserId { get; set; }
6+
public WatchlistSyncStatus SyncStatus { get; set; }
7+
public string UserName { get; set; }
8+
}
9+
10+
public enum WatchlistSyncStatus
11+
{
12+
Successful,
13+
Failed,
14+
NotEnabled
15+
}
16+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Ombi.Core.Models;
2+
using System.Collections.Generic;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
6+
namespace Ombi.Core.Services
7+
{
8+
public interface IPlexService
9+
{
10+
Task<List<PlexUserWatchlistModel>> GetWatchlistUsers(CancellationToken cancellationToken);
11+
}
12+
}

src/Ombi.Core/Services/PlexService.cs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Ombi.Core.Authentication;
3+
using Ombi.Core.Models;
4+
using Ombi.Store.Entities;
5+
using Ombi.Store.Repository;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
using UserType = Ombi.Store.Entities.UserType;
11+
12+
namespace Ombi.Core.Services
13+
{
14+
public class PlexService : IPlexService
15+
{
16+
private readonly IRepository<PlexWatchlistUserError> _watchlistUserErrors;
17+
private readonly OmbiUserManager _userManager;
18+
19+
public PlexService(IRepository<PlexWatchlistUserError> watchlistUserErrors, OmbiUserManager userManager)
20+
{
21+
_watchlistUserErrors = watchlistUserErrors;
22+
_userManager = userManager;
23+
}
24+
25+
public async Task<List<PlexUserWatchlistModel>> GetWatchlistUsers(CancellationToken cancellationToken)
26+
{
27+
var plexUsers = _userManager.Users.Where(x => x.UserType == UserType.PlexUser);
28+
var userErrors = await _watchlistUserErrors.GetAll().ToListAsync(cancellationToken);
29+
30+
var model = new List<PlexUserWatchlistModel>();
31+
32+
33+
foreach(var plexUser in plexUsers)
34+
{
35+
model.Add(new PlexUserWatchlistModel
36+
{
37+
UserId = plexUser.Id,
38+
UserName = plexUser.UserName,
39+
SyncStatus = GetWatchlistSyncStatus(plexUser, userErrors)
40+
});
41+
}
42+
43+
return model;
44+
}
45+
46+
private static WatchlistSyncStatus GetWatchlistSyncStatus(OmbiUser user, List<PlexWatchlistUserError> userErrors)
47+
{
48+
if (string.IsNullOrWhiteSpace(user.MediaServerToken))
49+
{
50+
return WatchlistSyncStatus.NotEnabled;
51+
}
52+
return userErrors.Any(x => x.UserId == user.Id) ? WatchlistSyncStatus.Failed : WatchlistSyncStatus.Successful;
53+
}
54+
}
55+
}

src/Ombi.DependencyInjection/IocExtensions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ public static void RegisterServices(this IServiceCollection services)
229229
services.AddTransient<IChangeLogProcessor, ChangeLogProcessor>();
230230
services.AddScoped<IFeatureService, FeatureService>();
231231
services.AddTransient<IRecentlyRequestedService, RecentlyRequestedService>();
232+
services.AddTransient<IPlexService, PlexService>();
232233
}
233234

234235
public static void RegisterJobs(this IServiceCollection services)

0 commit comments

Comments
 (0)