mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-06 05:01:13 -07:00
feat(emby): Show watched status for TV requests
* feat(emby): Show watched status for TV requests * Consider only requested episodes in played progress * Clarify tv watched progress tooltip * Fix unrespected code guidelines
This commit is contained in:
parent
151efe19d0
commit
1f37de0888
24 changed files with 1623 additions and 41 deletions
|
@ -254,18 +254,30 @@ namespace Ombi.Api.Emby
|
|||
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);
|
||||
}
|
||||
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");
|
||||
|
||||
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<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());
|
||||
|
||||
|
|
|
@ -34,5 +34,6 @@ namespace Ombi.Api.Emby
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -35,7 +35,8 @@ namespace Ombi.Core.Engine
|
|||
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;
|
||||
|
@ -44,6 +45,7 @@ namespace Ombi.Core.Engine
|
|||
TvSender = sender;
|
||||
_requestLog = rl;
|
||||
_mediaCacheService = mediaCacheService;
|
||||
_userPlayedEpisodeRepository = userPlayedEpisodeRepository;
|
||||
}
|
||||
|
||||
private INotificationHelper NotificationHelper { get; }
|
||||
|
@ -54,6 +56,7 @@ namespace Ombi.Core.Engine
|
|||
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)
|
||||
{
|
||||
|
@ -292,7 +295,7 @@ namespace Ombi.Core.Engine
|
|||
.Skip(position).Take(count).ToListAsync();
|
||||
|
||||
}
|
||||
await CheckForSubscription(shouldHide, allRequests);
|
||||
await FillAdditionalFields(shouldHide, allRequests);
|
||||
|
||||
return new RequestsViewModel<TvRequests>
|
||||
{
|
||||
|
@ -328,7 +331,7 @@ namespace Ombi.Core.Engine
|
|||
return new RequestsViewModel<TvRequests>();
|
||||
}
|
||||
|
||||
await CheckForSubscription(shouldHide, allRequests);
|
||||
await FillAdditionalFields(shouldHide, allRequests);
|
||||
|
||||
return new RequestsViewModel<TvRequests>
|
||||
{
|
||||
|
@ -351,7 +354,7 @@ namespace Ombi.Core.Engine
|
|||
allRequests = await TvRepository.Get().ToListAsync();
|
||||
}
|
||||
|
||||
await CheckForSubscription(shouldHide, allRequests);
|
||||
await FillAdditionalFields(shouldHide, allRequests);
|
||||
return allRequests;
|
||||
}
|
||||
|
||||
|
@ -396,7 +399,7 @@ namespace Ombi.Core.Engine
|
|||
? 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();
|
||||
|
@ -469,7 +472,7 @@ namespace Ombi.Core.Engine
|
|||
? 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();
|
||||
|
@ -523,7 +526,7 @@ namespace Ombi.Core.Engine
|
|||
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();
|
||||
|
@ -551,7 +554,7 @@ namespace Ombi.Core.Engine
|
|||
allRequests = await TvRepository.GetLite().ToListAsync();
|
||||
}
|
||||
|
||||
await CheckForSubscription(shouldHide, allRequests);
|
||||
await FillAdditionalFields(shouldHide, allRequests);
|
||||
return allRequests;
|
||||
}
|
||||
|
||||
|
@ -570,7 +573,7 @@ namespace Ombi.Core.Engine
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -624,7 +627,7 @@ namespace Ombi.Core.Engine
|
|||
allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync();
|
||||
}
|
||||
|
||||
await CheckForSubscription(shouldHide, allRequests);
|
||||
await FillAdditionalFields(shouldHide, allRequests);
|
||||
|
||||
return allRequests;
|
||||
}
|
||||
|
@ -643,7 +646,7 @@ namespace Ombi.Core.Engine
|
|||
}
|
||||
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
|
||||
|
||||
await CheckForSubscription(shouldHide, results);
|
||||
await FillAdditionalFields(shouldHide, results);
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -864,14 +867,20 @@ namespace Ombi.Core.Engine
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -896,6 +905,52 @@ namespace Ombi.Core.Engine
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -198,6 +198,7 @@ namespace Ombi.DependencyInjection
|
|||
services.AddScoped<IJellyfinContentRepository, JellyfinContentRepository>();
|
||||
services.AddScoped<INotificationTemplatesRepository, NotificationTemplatesRepository>();
|
||||
services.AddScoped<IUserPlayedMovieRepository, UserPlayedMovieRepository>();
|
||||
services.AddScoped<IUserPlayedEpisodeRepository, UserPlayedEpisodeRepository>();
|
||||
|
||||
services.AddScoped<ITvRequestRepository, TvRequestRepository>();
|
||||
services.AddScoped<IMovieRequestRepository, MovieRequestRepository>();
|
||||
|
|
|
@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.Emby;
|
||||
using Ombi.Api.Emby.Models;
|
||||
using Ombi.Api.Emby.Models.Media.Tv;
|
||||
using Ombi.Api.Emby.Models.Movie;
|
||||
using Ombi.Core.Authentication;
|
||||
using Ombi.Core.Settings;
|
||||
|
@ -18,20 +19,34 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
{
|
||||
public class EmbyPlayedSync : EmbyLibrarySync, IEmbyPlayedSync
|
||||
{
|
||||
public EmbyPlayedSync(ISettingsService<EmbySettings> settings, IEmbyApiFactory api, ILogger<EmbyContentSync> logger,
|
||||
IUserPlayedMovieRepository repo, INotificationHubService notification, OmbiUserManager user) : base(settings, api, logger, notification)
|
||||
public EmbyPlayedSync(
|
||||
ISettingsService<EmbySettings> settings,
|
||||
IEmbyApiFactory api,
|
||||
ILogger<EmbyContentSync> logger,
|
||||
IUserPlayedMovieRepository movieRepo,
|
||||
IUserPlayedEpisodeRepository episodeRepo,
|
||||
IEmbyContentRepository contentRepo,
|
||||
INotificationHubService notification,
|
||||
OmbiUserManager user) : base(settings, api, logger, notification)
|
||||
{
|
||||
_userManager = user;
|
||||
_repo = repo;
|
||||
_movieRepo = movieRepo;
|
||||
_contentRepo = contentRepo;
|
||||
_episodeRepo = episodeRepo;
|
||||
}
|
||||
private OmbiUserManager _userManager { get; }
|
||||
|
||||
private readonly IUserPlayedMovieRepository _repo;
|
||||
private readonly IUserPlayedMovieRepository _movieRepo;
|
||||
private readonly IUserPlayedEpisodeRepository _episodeRepo;
|
||||
private readonly IEmbyContentRepository _contentRepo;
|
||||
|
||||
protected override Task ProcessTv(EmbyServers server, string parentId = default)
|
||||
protected async override Task ProcessTv(EmbyServers server, string parentId = default)
|
||||
{
|
||||
// TODO
|
||||
return Task.CompletedTask;
|
||||
var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.EmbyUser || x.UserType == UserType.EmbyConnectUser).ToListAsync();
|
||||
foreach (var user in allUsers)
|
||||
{
|
||||
await ProcessTvUser(server, user, parentId);
|
||||
}
|
||||
}
|
||||
|
||||
protected async override Task ProcessMovies(EmbyServers server, string parentId = default)
|
||||
|
@ -65,7 +80,7 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
var totalCount = movies.TotalRecordCount;
|
||||
var processed = 0;
|
||||
var mediaToAdd = new HashSet<UserPlayedMovie>();
|
||||
|
||||
|
||||
while (processed < totalCount)
|
||||
{
|
||||
foreach (var movie in movies.Items)
|
||||
|
@ -80,7 +95,7 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
{
|
||||
movies = await Api.GetMoviesPlayed(server.ApiKey, parentId, processed, AmountToTake, user.ProviderUserId, server.FullUri);
|
||||
}
|
||||
await _repo.AddRange(mediaToAdd);
|
||||
await _movieRepo.AddRange(mediaToAdd);
|
||||
mediaToAdd.Clear();
|
||||
}
|
||||
}
|
||||
|
@ -98,13 +113,117 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
UserId = user.Id
|
||||
};
|
||||
// Check if it exists
|
||||
var existingMovie = await _repo.Get(userPlayedMovie.TheMovieDbId, userPlayedMovie.UserId);
|
||||
var existingMovie = await _movieRepo.Get(userPlayedMovie.TheMovieDbId, userPlayedMovie.UserId);
|
||||
var alreadyGoingToAdd = content.Any(x => x.TheMovieDbId == userPlayedMovie.TheMovieDbId && x.UserId == userPlayedMovie.UserId);
|
||||
if (existingMovie == null && !alreadyGoingToAdd)
|
||||
{
|
||||
content.Add(userPlayedMovie);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessTvUser(EmbyServers server, OmbiUser user, string parentId = default)
|
||||
{
|
||||
EmbyItemContainer<EmbyEpisodes> episodes;
|
||||
if (recentlyAdded)
|
||||
{
|
||||
var recentlyAddedAmountToTake = 10; // to be adjusted?
|
||||
episodes = await Api.GetTvPlayed(server.ApiKey, parentId, 0, recentlyAddedAmountToTake, user.ProviderUserId, server.FullUri);
|
||||
// Setting this so we don't attempt to grab more than we need
|
||||
if (episodes.TotalRecordCount > recentlyAddedAmountToTake)
|
||||
{
|
||||
episodes.TotalRecordCount = recentlyAddedAmountToTake;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
episodes = await Api.GetTvPlayed(server.ApiKey, parentId, 0, AmountToTake, user.ProviderUserId, server.FullUri);
|
||||
}
|
||||
var totalCount = episodes.TotalRecordCount;
|
||||
var processed = 0;
|
||||
var mediaToAdd = new HashSet<UserPlayedEpisode>();
|
||||
|
||||
while (processed < totalCount)
|
||||
{
|
||||
foreach (var episode in episodes.Items)
|
||||
{
|
||||
await ProcessTv(episode, user, mediaToAdd, server);
|
||||
processed++;
|
||||
}
|
||||
|
||||
// Get the next batch
|
||||
// Recently Added should never be checked as the TotalRecords should equal the amount to take
|
||||
if (!recentlyAdded)
|
||||
{
|
||||
episodes = await Api.GetTvPlayed(server.ApiKey, parentId, processed, AmountToTake, user.ProviderUserId, server.FullUri);
|
||||
}
|
||||
await _episodeRepo.AddRange(mediaToAdd);
|
||||
mediaToAdd.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task ProcessTv(EmbyEpisodes episode, OmbiUser user, ICollection<UserPlayedEpisode> content, EmbyServers server)
|
||||
{
|
||||
|
||||
var parent = await _contentRepo.GetByEmbyId(episode.SeriesId);
|
||||
if (parent == null)
|
||||
{
|
||||
_logger.LogInformation("The episode {0} does not relate to a series, so we cannot save this",
|
||||
episode.Name);
|
||||
return;
|
||||
}
|
||||
if (parent.TheMovieDbId.IsNullOrEmpty())
|
||||
{
|
||||
_logger.LogWarning($"Episode {episode.Name} is not linked to a TMDB series. Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
await AddToContent(content, new UserPlayedEpisode()
|
||||
{
|
||||
TheMovieDbId = int.Parse(parent.TheMovieDbId),
|
||||
SeasonNumber = episode.ParentIndexNumber,
|
||||
EpisodeNumber = episode.IndexNumber,
|
||||
UserId = user.Id
|
||||
});
|
||||
|
||||
if (episode.IndexNumberEnd.HasValue && episode.IndexNumberEnd.Value != episode.IndexNumber)
|
||||
{
|
||||
int episodeNumber = episode.IndexNumber;
|
||||
do
|
||||
{
|
||||
_logger.LogDebug($"Multiple-episode file detected. Adding episode ${episodeNumber}");
|
||||
episodeNumber++;
|
||||
|
||||
await AddToContent(content, new UserPlayedEpisode()
|
||||
{
|
||||
TheMovieDbId = int.Parse(parent.TheMovieDbId),
|
||||
SeasonNumber = episode.ParentIndexNumber,
|
||||
EpisodeNumber = episodeNumber,
|
||||
UserId = user.Id
|
||||
});
|
||||
|
||||
|
||||
} while (episodeNumber < episode.IndexNumberEnd.Value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private async Task AddToContent(ICollection<UserPlayedEpisode> content, UserPlayedEpisode episode)
|
||||
{
|
||||
|
||||
// Check if it exists
|
||||
var existingEpisode = await _episodeRepo.Get(episode.TheMovieDbId, episode.SeasonNumber, episode.EpisodeNumber, episode.UserId);
|
||||
var alreadyGoingToAdd = content.Any(x =>
|
||||
x.TheMovieDbId == episode.TheMovieDbId
|
||||
&& x.SeasonNumber == episode.SeasonNumber
|
||||
&& x.EpisodeNumber == episode.EpisodeNumber
|
||||
&& x.UserId == episode.UserId);
|
||||
if (existingEpisode == null && !alreadyGoingToAdd)
|
||||
{
|
||||
content.Add(episode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
IPlexContentRepository plexRepo,
|
||||
IEmbyContentRepository embyRepo,
|
||||
IJellyfinContentRepository jellyfinRepo,
|
||||
IUserPlayedMovieRepository userPlayedRepo,
|
||||
IUserPlayedMovieRepository userPlayedMovieRepo,
|
||||
IUserPlayedEpisodeRepository userPlayedEpisodeRepo,
|
||||
ISettingsService<EmbySettings> embySettings,
|
||||
ISettingsService<JellyfinSettings> jellyfinSettings)
|
||||
{
|
||||
|
@ -30,7 +31,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
_plexRepo = plexRepo;
|
||||
_embyRepo = embyRepo;
|
||||
_jellyfinRepo = jellyfinRepo;
|
||||
_userPlayedRepo = userPlayedRepo;
|
||||
_userPlayedMovieRepo = userPlayedMovieRepo;
|
||||
_userPlayedEpisodeRepo = userPlayedEpisodeRepo;
|
||||
_embySettings = embySettings;
|
||||
_jellyfinSettings = jellyfinSettings;
|
||||
_plexSettings.ClearCache();
|
||||
|
@ -41,7 +43,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
private readonly IPlexContentRepository _plexRepo;
|
||||
private readonly IEmbyContentRepository _embyRepo;
|
||||
private readonly IJellyfinContentRepository _jellyfinRepo;
|
||||
private readonly IUserPlayedMovieRepository _userPlayedRepo;
|
||||
private readonly IUserPlayedMovieRepository _userPlayedMovieRepo;
|
||||
private readonly IUserPlayedEpisodeRepository _userPlayedEpisodeRepo;
|
||||
private readonly ISettingsService<EmbySettings> _embySettings;
|
||||
private readonly ISettingsService<JellyfinSettings> _jellyfinSettings;
|
||||
|
||||
|
@ -66,7 +69,10 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
try
|
||||
{
|
||||
const string movieSql = "DELETE FROM UserPlayedMovie";
|
||||
await _userPlayedRepo.ExecuteSql(movieSql);
|
||||
await _userPlayedMovieRepo.ExecuteSql(movieSql);
|
||||
|
||||
const string episodeSql = "DELETE FROM UserPlayedEpisode";
|
||||
await _userPlayedEpisodeRepo.ExecuteSql(episodeSql);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace Ombi.Store.Context
|
|||
public DbSet<SickRageCache> SickRageCache { get; set; }
|
||||
public DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
||||
public DbSet<UserPlayedMovie> UserPlayedMovie { get; set; }
|
||||
public DbSet<UserPlayedEpisode> UserPlayedEpisode { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
|
|
|
@ -59,6 +59,9 @@ namespace Ombi.Store.Entities.Requests
|
|||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public int RequestedUserPlayedProgress { get; set; }
|
||||
}
|
||||
|
||||
public enum SeriesType
|
||||
|
|
10
src/Ombi.Store/Entities/UserPlayedEpisode.cs
Normal file
10
src/Ombi.Store/Entities/UserPlayedEpisode.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Ombi.Store.Entities
|
||||
{
|
||||
public class UserPlayedEpisode : Entity
|
||||
{
|
||||
public int TheMovieDbId { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
public int EpisodeNumber { get; set; }
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
}
|
589
src/Ombi.Store/Migrations/ExternalMySql/20230515182204_MovieEpisodePlayed.Designer.cs
generated
Normal file
589
src/Ombi.Store/Migrations/ExternalMySql/20230515182204_MovieEpisodePlayed.Designer.cs
generated
Normal file
|
@ -0,0 +1,589 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Ombi.Store.Context.MySql;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Ombi.Store.Migrations.ExternalMySql
|
||||
{
|
||||
[DbContext(typeof(ExternalMySqlContext))]
|
||||
[Migration("20230515182204_MovieEpisodePlayed")]
|
||||
partial class MovieEpisodePlayed
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.9")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("CouchPotatoCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("EmbyId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Quality")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("EmbyContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("EmbyId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ParentId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.ToTable("EmbyEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("JellyfinId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Quality")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("JellyfinContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("JellyfinId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ParentId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.ToTable("JellyfinEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("ArtistId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ForeignAlbumId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("Monitored")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<decimal>("PercentOfTracks")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<DateTime>("ReleaseDate")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("TrackCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("LidarrAlbumCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("ArtistId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ArtistName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ForeignArtistId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("Monitored")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("LidarrArtistCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("GrandparentKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ParentKey")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GrandparentKey");
|
||||
|
||||
b.ToTable("PlexEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ParentKey")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PlexContentId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("PlexServerContentId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("SeasonKey")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlexServerContentId");
|
||||
|
||||
b.ToTable("PlexSeasonsContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Quality")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ReleaseYear")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("RequestId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PlexServerContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("TmdbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PlexWatchlistHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("HasFile")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("HasRegular")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("RadarrCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SickRageCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SickRageEpisodeCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SonarrCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("HasFile")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("MovieDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SonarrEpisodeCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserPlayedEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedMovie", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserPlayedMovie");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||
.WithMany("Episodes")
|
||||
.HasForeignKey("ParentId")
|
||||
.HasPrincipalKey("EmbyId");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series")
|
||||
.WithMany("Episodes")
|
||||
.HasForeignKey("ParentId")
|
||||
.HasPrincipalKey("JellyfinId");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||
.WithMany("Episodes")
|
||||
.HasForeignKey("GrandparentKey")
|
||||
.HasPrincipalKey("Key");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.PlexServerContent", null)
|
||||
.WithMany("Seasons")
|
||||
.HasForeignKey("PlexServerContentId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||
{
|
||||
b.Navigation("Episodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b =>
|
||||
{
|
||||
b.Navigation("Episodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||
{
|
||||
b.Navigation("Episodes");
|
||||
|
||||
b.Navigation("Seasons");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Ombi.Store.Migrations.ExternalMySql
|
||||
{
|
||||
public partial class MovieEpisodePlayed : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UserPlayedEpisode",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
TheMovieDbId = table.Column<int>(type: "int", nullable: false),
|
||||
SeasonNumber = table.Column<int>(type: "int", nullable: false),
|
||||
EpisodeNumber = table.Column<int>(type: "int", nullable: false),
|
||||
UserId = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_UserPlayedEpisode", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "UserPlayedEpisode");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -488,6 +488,29 @@ namespace Ombi.Store.Migrations.ExternalMySql
|
|||
b.ToTable("SonarrEpisodeCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserPlayedEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedMovie", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
|
587
src/Ombi.Store/Migrations/ExternalSqlite/20230515161757_EpisodeUserPlayed.Designer.cs
generated
Normal file
587
src/Ombi.Store/Migrations/ExternalSqlite/20230515161757_EpisodeUserPlayed.Designer.cs
generated
Normal file
|
@ -0,0 +1,587 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Ombi.Store.Context.Sqlite;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Ombi.Store.Migrations.ExternalSqlite
|
||||
{
|
||||
[DbContext(typeof(ExternalSqliteContext))]
|
||||
[Migration("20230515161757_EpisodeUserPlayed")]
|
||||
partial class EpisodeUserPlayed
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.9");
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("CouchPotatoCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("EmbyId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Quality")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("EmbyContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("EmbyId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ParentId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.ToTable("EmbyEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("JellyfinId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Quality")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("JellyfinContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("JellyfinId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ParentId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.ToTable("JellyfinEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("ArtistId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ForeignAlbumId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Monitored")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("PercentOfTracks")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ReleaseDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("TrackCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("LidarrAlbumCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ArtistId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ArtistName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ForeignArtistId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Monitored")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("LidarrArtistCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("GrandparentKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ParentKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GrandparentKey");
|
||||
|
||||
b.ToTable("PlexEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ParentKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PlexContentId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PlexServerContentId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SeasonKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlexServerContentId");
|
||||
|
||||
b.ToTable("PlexSeasonsContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("AddedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Quality")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ReleaseYear")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("RequestId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("TheMovieDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TvDbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PlexServerContent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("TmdbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PlexWatchlistHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("Has4K")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("HasFile")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("HasRegular")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("RadarrCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SickRageCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SickRageEpisodeCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SonarrCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("HasFile")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MovieDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TvDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SonarrEpisodeCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserPlayedEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedMovie", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserPlayedMovie");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||
.WithMany("Episodes")
|
||||
.HasForeignKey("ParentId")
|
||||
.HasPrincipalKey("EmbyId");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series")
|
||||
.WithMany("Episodes")
|
||||
.HasForeignKey("ParentId")
|
||||
.HasPrincipalKey("JellyfinId");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||
.WithMany("Episodes")
|
||||
.HasForeignKey("GrandparentKey")
|
||||
.HasPrincipalKey("Key");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.PlexServerContent", null)
|
||||
.WithMany("Seasons")
|
||||
.HasForeignKey("PlexServerContentId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||
{
|
||||
b.Navigation("Episodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b =>
|
||||
{
|
||||
b.Navigation("Episodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||
{
|
||||
b.Navigation("Episodes");
|
||||
|
||||
b.Navigation("Seasons");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Ombi.Store.Migrations.ExternalSqlite
|
||||
{
|
||||
public partial class EpisodeUserPlayed : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UserPlayedEpisode",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
TheMovieDbId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
SeasonNumber = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
EpisodeNumber = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
UserId = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_UserPlayedEpisode", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "UserPlayedEpisode");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -486,6 +486,29 @@ namespace Ombi.Store.Migrations.ExternalSqlite
|
|||
b.ToTable("SonarrEpisodeCache");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedEpisode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("EpisodeNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TheMovieDbId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UserPlayedEpisode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.UserPlayedMovie", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
|
13
src/Ombi.Store/Repository/IUserPlayedEpisodeRepository.cs
Normal file
13
src/Ombi.Store/Repository/IUserPlayedEpisodeRepository.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Store.Repository
|
||||
{
|
||||
public interface IUserPlayedEpisodeRepository : IExternalRepository<UserPlayedEpisode>
|
||||
{
|
||||
Task<UserPlayedEpisode> Get(int theMovieDbId, int seasonNumber, int episodeNumber, string userId);
|
||||
}
|
||||
}
|
26
src/Ombi.Store/Repository/UserPlayedEpisodeRepository.cs
Normal file
26
src/Ombi.Store/Repository/UserPlayedEpisodeRepository.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Ombi.Store.Context;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Store.Repository
|
||||
{
|
||||
public class UserPlayedEpisodeRepository : ExternalRepository<UserPlayedEpisode>, IUserPlayedEpisodeRepository
|
||||
{
|
||||
protected ExternalContext Db { get; }
|
||||
public UserPlayedEpisodeRepository(ExternalContext db) : base(db)
|
||||
{
|
||||
Db = db;
|
||||
}
|
||||
|
||||
public async Task<UserPlayedEpisode> Get(int theMovieDbId, int seasonNumber, int episodeNumber, string userId)
|
||||
{
|
||||
return await Db.UserPlayedEpisode.FirstOrDefaultAsync(x => x.TheMovieDbId == theMovieDbId && x.SeasonNumber == seasonNumber && x.EpisodeNumber == episodeNumber && x.UserId == userId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,6 +46,7 @@ import { MatNativeDateModule } from '@angular/material/core';
|
|||
import { MatPaginatorI18n } from "./localization/MatPaginatorI18n";
|
||||
import { MatPaginatorIntl } from "@angular/material/paginator";
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatSlideToggleModule } from "@angular/material/slide-toggle";
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
|
@ -150,6 +151,7 @@ export function JwtTokenGetter() {
|
|||
OverlayModule,
|
||||
MatCheckboxModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
JwtModule.forRoot({
|
||||
config: {
|
||||
tokenGetter: JwtTokenGetter,
|
||||
|
|
|
@ -132,6 +132,7 @@ export interface ITvRequests {
|
|||
background: any;
|
||||
totalSeasons: number;
|
||||
tvDbId: number; // NO LONGER USED
|
||||
requestedUserPlayedProgress: number;
|
||||
|
||||
open: boolean; // THIS IS FOR THE UI
|
||||
|
||||
|
|
|
@ -60,6 +60,19 @@
|
|||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="watchedByRequestedUser">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
disableClear
|
||||
matTooltip="{{ 'Requests.WatchedProgressTooltip' | translate}}">
|
||||
{{ 'Requests.Watched' | translate}}
|
||||
</th>
|
||||
<td mat-cell id="requestedUserPlayedProgress{{element.id}}" *matCellDef="let element">
|
||||
<mat-progress-bar mode="determinate" value="{{element.requestedUserPlayedProgress}}" class="played-progress"></mat-progress-bar>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
@import "./styles/variables.scss";
|
||||
|
||||
.played-progress {
|
||||
width: 5rem;
|
||||
height: 1rem;
|
||||
}
|
|
@ -4,6 +4,7 @@ import { Observable, merge, of as observableOf } from 'rxjs';
|
|||
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { AuthService } from "../../../auth/auth.service";
|
||||
import { FeaturesFacade } from "../../../state/features/features.facade";
|
||||
import { MatPaginator } from "@angular/material/paginator";
|
||||
import { MatSort } from "@angular/material/sort";
|
||||
import { RequestFilterType } from "../../models/RequestFilterType";
|
||||
|
@ -13,15 +14,16 @@ import { StorageService } from "../../../shared/storage/storage-service";
|
|||
@Component({
|
||||
templateUrl: "./tv-grid.component.html",
|
||||
selector: "tv-grid",
|
||||
styleUrls: ["../requests-list.component.scss"]
|
||||
styleUrls: ["../requests-list.component.scss", "tv-grid.component.scss"]
|
||||
})
|
||||
export class TvGridComponent implements OnInit, AfterViewInit {
|
||||
public dataSource: IChildRequests[] = [];
|
||||
public resultsLength: number;
|
||||
public isLoadingResults = true;
|
||||
public displayedColumns: string[] = ['series', 'requestedBy', 'status', 'requestStatus', 'requestedDate','actions'];
|
||||
public displayedColumns: string[] = ['series', 'requestedBy', 'status', 'requestStatus', 'requestedDate'];
|
||||
public gridCount: string = "15";
|
||||
public isAdmin: boolean;
|
||||
public isPlayedSyncEnabled = false;
|
||||
public defaultSort: string = "requestedDate";
|
||||
public defaultOrder: string = "desc";
|
||||
public currentFilter: RequestFilterType = RequestFilterType.All;
|
||||
|
@ -40,12 +42,17 @@ export class TvGridComponent implements OnInit, AfterViewInit {
|
|||
@ViewChild(MatSort) sort: MatSort;
|
||||
|
||||
constructor(private requestService: RequestServiceV2, private auth: AuthService,
|
||||
private ref: ChangeDetectorRef, private storageService: StorageService) {
|
||||
private ref: ChangeDetectorRef, private storageService: StorageService,
|
||||
private featureFacade: FeaturesFacade) {
|
||||
|
||||
}
|
||||
|
||||
public ngOnInit() {
|
||||
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
||||
public ngOnInit() {
|
||||
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
||||
this.isPlayedSyncEnabled = this.featureFacade.isPlayedSyncEnabled();
|
||||
|
||||
this.addDynamicColumns();
|
||||
|
||||
const defaultCount = this.storageService.get(this.storageKeyGridCount);
|
||||
const defaultSort = this.storageService.get(this.storageKey);
|
||||
const defaultOrder = this.storageService.get(this.storageKeyOrder);
|
||||
|
@ -64,9 +71,18 @@ export class TvGridComponent implements OnInit, AfterViewInit {
|
|||
}
|
||||
}
|
||||
|
||||
addDynamicColumns() {
|
||||
if (this.isPlayedSyncEnabled) {
|
||||
this.displayedColumns.push('watchedByRequestedUser');
|
||||
}
|
||||
|
||||
// always put the actions column at the end
|
||||
this.displayedColumns.push('actions');
|
||||
}
|
||||
|
||||
public async ngAfterViewInit() {
|
||||
|
||||
this.storageService.save(this.storageKeyGridCount, this.gridCount);
|
||||
this.storageService.save(this.storageKeyGridCount, this.gridCount);
|
||||
this.storageService.save(this.storageKeyCurrentFilter, (+this.currentFilter).toString());
|
||||
this.paginator.showFirstLastButtons = true;
|
||||
|
||||
|
@ -78,7 +94,7 @@ export class TvGridComponent implements OnInit, AfterViewInit {
|
|||
startWith({}),
|
||||
switchMap((value: any) => {
|
||||
this.isLoadingResults = true;
|
||||
|
||||
|
||||
if (value.active || value.direction) {
|
||||
this.storageService.save(this.storageKey, value.active);
|
||||
this.storageService.save(this.storageKeyOrder, value.direction);
|
||||
|
@ -103,7 +119,7 @@ export class TvGridComponent implements OnInit, AfterViewInit {
|
|||
const filter = () => { this.dataSource = this.dataSource.filter((req) => {
|
||||
return req.id !== request.id;
|
||||
})};
|
||||
|
||||
|
||||
const onChange = () => {
|
||||
this.ref.detectChanges();
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ import {MatMenuModule} from '@angular/material/menu';
|
|||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatProgressSpinnerModule } from "@angular/material/progress-spinner";
|
||||
import { MatProgressBarModule } from "@angular/material/progress-bar";
|
||||
import {MatRadioModule} from '@angular/material/radio';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
|
@ -66,6 +67,7 @@ import { WatchProvidersSelectComponent } from "./components/watch-providers-sele
|
|||
MomentModule,
|
||||
MatCardModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
MatAutocompleteModule,
|
||||
MatInputModule,
|
||||
MatTabsModule,
|
||||
|
@ -99,6 +101,7 @@ import { WatchProvidersSelectComponent } from "./components/watch-providers-sele
|
|||
TranslateModule,
|
||||
SidebarModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
IssuesReportComponent,
|
||||
EpisodeRequestComponent,
|
||||
AdminRequestDialogComponent,
|
||||
|
|
|
@ -161,6 +161,7 @@
|
|||
"RequestStatus": "Request status",
|
||||
"Watched": "Watched",
|
||||
"WatchedTooltip": "The user who made the request has watched it",
|
||||
"WatchedProgressTooltip": "Shows how much the user who made the request has watched it",
|
||||
"WatchedByUsersCount": "{{count}} users have watched this.",
|
||||
"Denied": " Denied:",
|
||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue