merge
58
CHANGELOG.md
|
@ -4,14 +4,66 @@
|
||||||
|
|
||||||
### **New Features**
|
### **New Features**
|
||||||
|
|
||||||
|
- Added automation tests for the voting feature. [TidusJar]
|
||||||
|
|
||||||
|
- Update LidarrAvailabilityChecker.cs. [Jamie]
|
||||||
|
|
||||||
|
- Update CHANGELOG.md. [Jamie]
|
||||||
|
|
||||||
- Changes language selector to always show native language name. [Victor Usoltsev]
|
- Changes language selector to always show native language name. [Victor Usoltsev]
|
||||||
|
|
||||||
- Updated test dependancies. [TidusJar]
|
- Updated test dependancies. [TidusJar]
|
||||||
|
|
||||||
|
- Added in the external repo so we can rip out external stuff. [TidusJar]
|
||||||
|
|
||||||
- Added the ability to purge/remove issues. [TidusJar]
|
- Added the ability to purge/remove issues. [TidusJar]
|
||||||
|
|
||||||
### **Fixes**
|
### **Fixes**
|
||||||
|
|
||||||
|
- New translations en.json (French) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (French) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (French) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (French) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Swedish) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Spanish) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Portuguese, Brazilian) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Polish) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Norwegian) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Italian) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (German) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (French) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Dutch) [Jamie]
|
||||||
|
|
||||||
|
- New translations en.json (Danish) [Jamie]
|
||||||
|
|
||||||
|
- When a users requests content and the voting is enabled, the user who requested is an automatic +1 vote. [TidusJar]
|
||||||
|
|
||||||
|
- Revert, no idea how this happened. [TidusJar]
|
||||||
|
|
||||||
|
- Fixed the build. Thanks Matt! [TidusJar]
|
||||||
|
|
||||||
|
- Fixes untickable mass email checkboxes in Safari. [Victor Usoltsev]
|
||||||
|
|
||||||
|
- [ImgBot] optimizes images. [ImgBotApp]
|
||||||
|
|
||||||
|
- Revert "Feature/purge issues" [Jamie]
|
||||||
|
|
||||||
|
- Fixed the issue where user preferences was not being inported into some notifications. [TidusJar]
|
||||||
|
|
||||||
|
- New role to enable users to remove their own requests. [Anojh]
|
||||||
|
|
||||||
- Users can now remove their own requests. [Anojh]
|
- Users can now remove their own requests. [Anojh]
|
||||||
|
|
||||||
- New translations en.json (Danish) [Jamie]
|
- New translations en.json (Danish) [Jamie]
|
||||||
|
@ -60,6 +112,12 @@
|
||||||
|
|
||||||
- Date and times are now in the local users date time. [TidusJar]
|
- Date and times are now in the local users date time. [TidusJar]
|
||||||
|
|
||||||
|
- Fixed the migration. [TidusJar]
|
||||||
|
|
||||||
|
- ExternalContext migrations. [TidusJar]
|
||||||
|
|
||||||
|
- The settings have now been split out of the main db. [TidusJar]
|
||||||
|
|
||||||
- Search for the Lidarr Album when it's a new artist. [TidusJar]
|
- Search for the Lidarr Album when it's a new artist. [TidusJar]
|
||||||
|
|
||||||
- The album in Lidarr does not need to be marked as monitored for us to pick up it's available. Fixes #2536. [Jamie]
|
- The album in Lidarr does not need to be marked as monitored for us to pick up it's available. Fixes #2536. [Jamie]
|
||||||
|
|
|
@ -3,10 +3,14 @@ configuration: Release
|
||||||
os: Visual Studio 2017
|
os: Visual Studio 2017
|
||||||
environment:
|
environment:
|
||||||
nodejs_version: "9.8.0"
|
nodejs_version: "9.8.0"
|
||||||
|
typescript_version: "3.0.1"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
# Get the latest stable version of Node.js or io.js
|
# Get the latest stable version of Node.js or io.js
|
||||||
- ps: Install-Product node $env:nodejs_version
|
- ps: Install-Product node $env:nodejs_version
|
||||||
|
|
||||||
|
- cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\3.0;%path%
|
||||||
|
- cmd: tsc -v
|
||||||
build_script:
|
build_script:
|
||||||
- ps: ./build.ps1 --settings_skipverification=true
|
- ps: ./build.ps1 --settings_skipverification=true
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Ombi.Api.Notifications
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var id = await _appConfig.Get(ConfigurationTypes.Notification);
|
var id = await _appConfig.GetAsync(ConfigurationTypes.Notification);
|
||||||
var request = new Request(string.Empty, ApiUrl, HttpMethod.Post);
|
var request = new Request(string.Empty, ApiUrl, HttpMethod.Post);
|
||||||
|
|
||||||
var body = new OneSignalNotificationBody
|
var body = new OneSignalNotificationBody
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<IEnumerable<MovieRequests>> SearchMovieRequest(string search);
|
Task<IEnumerable<MovieRequests>> SearchMovieRequest(string search);
|
||||||
|
|
||||||
Task RemoveMovieRequest(int requestId);
|
Task RemoveMovieRequest(int requestId);
|
||||||
|
Task RemoveAllMovieRequests();
|
||||||
|
|
||||||
Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
|
Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
|
||||||
Task<RequestEngineResult> ApproveMovie(MovieRequests request);
|
Task<RequestEngineResult> ApproveMovie(MovieRequests request);
|
||||||
|
|
|
@ -416,6 +416,12 @@ namespace Ombi.Core.Engine
|
||||||
await MovieRepository.Delete(request);
|
await MovieRepository.Delete(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task RemoveAllMovieRequests()
|
||||||
|
{
|
||||||
|
var request = MovieRepository.GetAll();
|
||||||
|
await MovieRepository.DeleteRange(request);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> UserHasRequest(string userId)
|
public async Task<bool> UserHasRequest(string userId)
|
||||||
{
|
{
|
||||||
return await MovieRepository.GetAll().AnyAsync(x => x.RequestedUserId == userId);
|
return await MovieRepository.GetAll().AnyAsync(x => x.RequestedUserId == userId);
|
||||||
|
@ -483,7 +489,7 @@ namespace Ombi.Core.Engine
|
||||||
RequestType = RequestType.Movie,
|
RequestType = RequestType.Movie,
|
||||||
});
|
});
|
||||||
|
|
||||||
return new RequestEngineResult {Result = true, Message = $"{movieName} has been successfully added!"};
|
return new RequestEngineResult {Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
|
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
|
||||||
|
|
|
@ -495,7 +495,7 @@ namespace Ombi.Core.Engine
|
||||||
RequestType = RequestType.Album,
|
RequestType = RequestType.Album,
|
||||||
});
|
});
|
||||||
|
|
||||||
return new RequestEngineResult { Result = true, Message = $"{model.Title} has been successfully added!" };
|
return new RequestEngineResult { Result = true, Message = $"{model.Title} has been successfully added!", RequestId = model.Id };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,6 @@
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public bool IsError => !string.IsNullOrEmpty(ErrorMessage);
|
public bool IsError => !string.IsNullOrEmpty(ErrorMessage);
|
||||||
public string ErrorMessage { get; set; }
|
public string ErrorMessage { get; set; }
|
||||||
|
public int RequestId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -604,15 +604,16 @@ namespace Ombi.Core.Engine
|
||||||
var result = await TvSender.Send(model);
|
var result = await TvSender.Send(model);
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
return new RequestEngineResult { Result = true };
|
return new RequestEngineResult { Result = true, RequestId = model.Id};
|
||||||
}
|
}
|
||||||
return new RequestEngineResult
|
return new RequestEngineResult
|
||||||
{
|
{
|
||||||
ErrorMessage = result.Message
|
ErrorMessage = result.Message,
|
||||||
|
RequestId = model.Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RequestEngineResult { Result = true };
|
return new RequestEngineResult { Result = true, RequestId = model.Id };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
|
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
|
||||||
|
|
|
@ -149,13 +149,17 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
public async Task<VoteEngineResult> UpVote(int requestId, RequestType requestType)
|
public async Task<VoteEngineResult> UpVote(int requestId, RequestType requestType)
|
||||||
{
|
{
|
||||||
|
var voteSettings = await _voteSettings.GetSettingsAsync();
|
||||||
|
if (!voteSettings.Enabled)
|
||||||
|
{
|
||||||
|
return new VoteEngineResult {Result = true};
|
||||||
|
}
|
||||||
// How many votes does this have?!
|
// How many votes does this have?!
|
||||||
var currentVotes = GetVotes(requestId, requestType);
|
var currentVotes = GetVotes(requestId, requestType);
|
||||||
var voteSettings = await _voteSettings.GetSettingsAsync();
|
|
||||||
|
|
||||||
// Does this user have a downvote? If so we should revert it and make it an upvote
|
|
||||||
var user = await GetUser();
|
var user = await GetUser();
|
||||||
|
|
||||||
|
// Does this user have a downvote? If so we should revert it and make it an upvote
|
||||||
var currentVote = await GetVoteForUser(requestId, user.Id);
|
var currentVote = await GetVoteForUser(requestId, user.Id);
|
||||||
if (currentVote != null && currentVote.VoteType == VoteType.Upvote)
|
if (currentVote != null && currentVote.VoteType == VoteType.Upvote)
|
||||||
{
|
{
|
||||||
|
@ -206,7 +210,7 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
return new VoteEngineResult
|
return new VoteEngineResult
|
||||||
{
|
{
|
||||||
ErrorMessage = "Voted succesfully but could not approve movie!"
|
ErrorMessage = "Voted succesfully but could not approve!"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +222,11 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
public async Task<VoteEngineResult> DownVote(int requestId, RequestType requestType)
|
public async Task<VoteEngineResult> DownVote(int requestId, RequestType requestType)
|
||||||
{
|
{
|
||||||
|
var voteSettings = await _voteSettings.GetSettingsAsync();
|
||||||
|
if (!voteSettings.Enabled)
|
||||||
|
{
|
||||||
|
return new VoteEngineResult { Result = true };
|
||||||
|
}
|
||||||
var user = await GetUser();
|
var user = await GetUser();
|
||||||
var currentVote = await GetVoteForUser(requestId, user.Id);
|
var currentVote = await GetVoteForUser(requestId, user.Id);
|
||||||
if (currentVote != null && currentVote.VoteType == VoteType.Downvote)
|
if (currentVote != null && currentVote.VoteType == VoteType.Downvote)
|
||||||
|
|
|
@ -7,12 +7,12 @@ namespace Ombi.Core.Rule.Rules.Request
|
||||||
{
|
{
|
||||||
public class SonarrCacheRequestRule : BaseRequestRule, IRules<BaseRequest>
|
public class SonarrCacheRequestRule : BaseRequestRule, IRules<BaseRequest>
|
||||||
{
|
{
|
||||||
public SonarrCacheRequestRule(IOmbiContext ctx)
|
public SonarrCacheRequestRule(IExternalContext ctx)
|
||||||
{
|
{
|
||||||
_ctx = ctx;
|
_ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
|
|
||||||
public Task<RuleResult> Execute(BaseRequest obj)
|
public Task<RuleResult> Execute(BaseRequest obj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,12 +34,12 @@ namespace Ombi.Core.Rule.Rules.Search
|
||||||
{
|
{
|
||||||
public class SonarrCacheSearchRule : BaseSearchRule, IRules<SearchViewModel>
|
public class SonarrCacheSearchRule : BaseSearchRule, IRules<SearchViewModel>
|
||||||
{
|
{
|
||||||
public SonarrCacheSearchRule(IOmbiContext ctx)
|
public SonarrCacheSearchRule(IExternalContext ctx)
|
||||||
{
|
{
|
||||||
_ctx = ctx;
|
_ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
|
|
||||||
public Task<RuleResult> Execute(SearchViewModel obj)
|
public Task<RuleResult> Execute(SearchViewModel obj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,12 +10,12 @@ namespace Ombi.Core.Rule.Rules
|
||||||
{
|
{
|
||||||
public class SonarrCacheRule
|
public class SonarrCacheRule
|
||||||
{
|
{
|
||||||
public SonarrCacheRule(IOmbiContext ctx)
|
public SonarrCacheRule(IExternalContext ctx)
|
||||||
{
|
{
|
||||||
_ctx = ctx;
|
_ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
|
|
||||||
public async Task<RuleResult> Execute(BaseRequest obj)
|
public async Task<RuleResult> Execute(BaseRequest obj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,8 +129,12 @@ namespace Ombi.DependencyInjection
|
||||||
|
|
||||||
public static void RegisterStore(this IServiceCollection services) {
|
public static void RegisterStore(this IServiceCollection services) {
|
||||||
services.AddEntityFrameworkSqlite().AddDbContext<OmbiContext>();
|
services.AddEntityFrameworkSqlite().AddDbContext<OmbiContext>();
|
||||||
|
services.AddEntityFrameworkSqlite().AddDbContext<SettingsContext>();
|
||||||
|
services.AddEntityFrameworkSqlite().AddDbContext<ExternalContext>();
|
||||||
|
|
||||||
services.AddScoped<IOmbiContext, OmbiContext>(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
|
services.AddScoped<IOmbiContext, OmbiContext>(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
|
||||||
|
services.AddScoped<ISettingsContext, SettingsContext>(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
|
||||||
|
services.AddScoped<IExternalContext, ExternalContext>(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6
|
||||||
services.AddTransient<ISettingsRepository, SettingsJsonRepository>();
|
services.AddTransient<ISettingsRepository, SettingsJsonRepository>();
|
||||||
services.AddTransient<ISettingsResolver, SettingsResolver>();
|
services.AddTransient<ISettingsResolver, SettingsResolver>();
|
||||||
services.AddTransient<IPlexContentRepository, PlexServerContentRepository>();
|
services.AddTransient<IPlexContentRepository, PlexServerContentRepository>();
|
||||||
|
@ -145,6 +149,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<ITokenRepository, TokenRepository>();
|
services.AddTransient<ITokenRepository, TokenRepository>();
|
||||||
services.AddTransient(typeof(ISettingsService<>), typeof(SettingsService<>));
|
services.AddTransient(typeof(ISettingsService<>), typeof(SettingsService<>));
|
||||||
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
|
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
|
||||||
|
services.AddTransient(typeof(IExternalRepository<>), typeof(ExternalRepository<>));
|
||||||
}
|
}
|
||||||
public static void RegisterServices(this IServiceCollection services)
|
public static void RegisterServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
public const string RequestMusic = nameof(RequestMusic);
|
public const string RequestMusic = nameof(RequestMusic);
|
||||||
public const string Disabled = nameof(Disabled);
|
public const string Disabled = nameof(Disabled);
|
||||||
public const string ReceivesNewsletter = nameof(ReceivesNewsletter);
|
public const string ReceivesNewsletter = nameof(ReceivesNewsletter);
|
||||||
|
public const string ManageOwnRequests = nameof(ManageOwnRequests);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -170,6 +170,24 @@ namespace Ombi.Notifications.Interfaces
|
||||||
{
|
{
|
||||||
return new NotificationMessageContent { Disabled = true };
|
return new NotificationMessageContent { Disabled = true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model.UserId.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
if (model.RequestType == RequestType.Movie)
|
||||||
|
{
|
||||||
|
model.UserId = MovieRequest.RequestedUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.RequestType == RequestType.Album)
|
||||||
|
{
|
||||||
|
model.UserId = AlbumRequest.RequestedUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.RequestType == RequestType.TvShow)
|
||||||
|
{
|
||||||
|
model.UserId = TvRequest.RequestedUserId;
|
||||||
|
}
|
||||||
|
}
|
||||||
var parsed = Parse(model, template, agent);
|
var parsed = Parse(model, template, agent);
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
|
@ -184,7 +202,7 @@ namespace Ombi.Notifications.Interfaces
|
||||||
protected UserNotificationPreferences GetUserPreference(string userId, NotificationAgent agent)
|
protected UserNotificationPreferences GetUserPreference(string userId, NotificationAgent agent)
|
||||||
{
|
{
|
||||||
return UserNotificationPreferences.GetAll()
|
return UserNotificationPreferences.GetAll()
|
||||||
.FirstOrDefault(x => x.Enabled && x.Agent == agent && x.UserId == userId);
|
.FirstOrDefault(x => x.Agent == agent && x.UserId == userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent)
|
private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent)
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Ombi.Notifications
|
||||||
LoadIssues(opts);
|
LoadIssues(opts);
|
||||||
if (pref != null)
|
if (pref != null)
|
||||||
{
|
{
|
||||||
UserPreference = pref.Enabled ? pref.Value : string.Empty;
|
UserPreference = pref.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
string title;
|
string title;
|
||||||
|
@ -268,6 +268,7 @@ namespace Ombi.Notifications
|
||||||
{nameof(IssueUser),IssueUser},
|
{nameof(IssueUser),IssueUser},
|
||||||
{nameof(UserName),UserName},
|
{nameof(UserName),UserName},
|
||||||
{nameof(Alias),Alias},
|
{nameof(Alias),Alias},
|
||||||
|
{nameof(UserPreference),UserPreference},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -42,7 +42,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato
|
||||||
public class CouchPotatoSync : ICouchPotatoSync
|
public class CouchPotatoSync : ICouchPotatoSync
|
||||||
{
|
{
|
||||||
public CouchPotatoSync(ISettingsService<CouchPotatoSettings> cpSettings,
|
public CouchPotatoSync(ISettingsService<CouchPotatoSettings> cpSettings,
|
||||||
ICouchPotatoApi api, ILogger<CouchPotatoSync> log, IOmbiContext ctx)
|
ICouchPotatoApi api, ILogger<CouchPotatoSync> log, IExternalContext ctx)
|
||||||
{
|
{
|
||||||
_settings = cpSettings;
|
_settings = cpSettings;
|
||||||
_api = api;
|
_api = api;
|
||||||
|
@ -54,7 +54,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato
|
||||||
private readonly ISettingsService<CouchPotatoSettings> _settings;
|
private readonly ISettingsService<CouchPotatoSettings> _settings;
|
||||||
private readonly ICouchPotatoApi _api;
|
private readonly ICouchPotatoApi _api;
|
||||||
private readonly ILogger<CouchPotatoSync> _log;
|
private readonly ILogger<CouchPotatoSync> _log;
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
|
|
||||||
public async Task Start()
|
public async Task Start()
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
|
||||||
{
|
{
|
||||||
public class LidarrAlbumSync : ILidarrAlbumSync
|
public class LidarrAlbumSync : ILidarrAlbumSync
|
||||||
{
|
{
|
||||||
public LidarrAlbumSync(ISettingsService<LidarrSettings> lidarr, ILidarrApi lidarrApi, ILogger<LidarrAlbumSync> log, IOmbiContext ctx,
|
public LidarrAlbumSync(ISettingsService<LidarrSettings> lidarr, ILidarrApi lidarrApi, ILogger<LidarrAlbumSync> log, IExternalContext ctx,
|
||||||
IBackgroundJobClient job, ILidarrAvailabilityChecker availability)
|
IBackgroundJobClient job, ILidarrAvailabilityChecker availability)
|
||||||
{
|
{
|
||||||
_lidarrSettings = lidarr;
|
_lidarrSettings = lidarr;
|
||||||
|
@ -35,7 +35,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
|
||||||
private readonly ISettingsService<LidarrSettings> _lidarrSettings;
|
private readonly ISettingsService<LidarrSettings> _lidarrSettings;
|
||||||
private readonly ILidarrApi _lidarrApi;
|
private readonly ILidarrApi _lidarrApi;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
private readonly IBackgroundJobClient _job;
|
private readonly IBackgroundJobClient _job;
|
||||||
private readonly ILidarrAvailabilityChecker _availability;
|
private readonly ILidarrAvailabilityChecker _availability;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
|
||||||
{
|
{
|
||||||
public class LidarrArtistSync : ILidarrArtistSync
|
public class LidarrArtistSync : ILidarrArtistSync
|
||||||
{
|
{
|
||||||
public LidarrArtistSync(ISettingsService<LidarrSettings> lidarr, ILidarrApi lidarrApi, ILogger<LidarrArtistSync> log, IOmbiContext ctx,
|
public LidarrArtistSync(ISettingsService<LidarrSettings> lidarr, ILidarrApi lidarrApi, ILogger<LidarrArtistSync> log, IExternalContext ctx,
|
||||||
IBackgroundJobClient background, ILidarrAlbumSync album)
|
IBackgroundJobClient background, ILidarrAlbumSync album)
|
||||||
{
|
{
|
||||||
_lidarrSettings = lidarr;
|
_lidarrSettings = lidarr;
|
||||||
|
@ -35,7 +35,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
|
||||||
private readonly ISettingsService<LidarrSettings> _lidarrSettings;
|
private readonly ISettingsService<LidarrSettings> _lidarrSettings;
|
||||||
private readonly ILidarrApi _lidarrApi;
|
private readonly ILidarrApi _lidarrApi;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
private readonly IBackgroundJobClient _job;
|
private readonly IBackgroundJobClient _job;
|
||||||
private readonly ILidarrAlbumSync _albumSync;
|
private readonly ILidarrAlbumSync _albumSync;
|
||||||
|
|
||||||
|
|
|
@ -70,4 +70,4 @@ namespace Ombi.Schedule.Jobs.Lidarr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
public class OmbiAutomaticUpdater : IOmbiAutomaticUpdater
|
public class OmbiAutomaticUpdater : IOmbiAutomaticUpdater
|
||||||
{
|
{
|
||||||
public OmbiAutomaticUpdater(ILogger<OmbiAutomaticUpdater> log, IChangeLogProcessor service,
|
public OmbiAutomaticUpdater(ILogger<OmbiAutomaticUpdater> log, IChangeLogProcessor service,
|
||||||
ISettingsService<UpdateSettings> s, IProcessProvider proc, IRepository<ApplicationConfiguration> appConfig)
|
ISettingsService<UpdateSettings> s, IProcessProvider proc, IApplicationConfigRepository appConfig)
|
||||||
{
|
{
|
||||||
Logger = log;
|
Logger = log;
|
||||||
Processor = service;
|
Processor = service;
|
||||||
|
@ -48,7 +48,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
private ISettingsService<UpdateSettings> Settings { get; }
|
private ISettingsService<UpdateSettings> Settings { get; }
|
||||||
private readonly IProcessProvider _processProvider;
|
private readonly IProcessProvider _processProvider;
|
||||||
private static PerformContext Ctx { get; set; }
|
private static PerformContext Ctx { get; set; }
|
||||||
private readonly IRepository<ApplicationConfiguration> _appConfig;
|
private readonly IApplicationConfigRepository _appConfig;
|
||||||
|
|
||||||
public string[] GetVersion()
|
public string[] GetVersion()
|
||||||
{
|
{
|
||||||
|
@ -252,9 +252,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
|
|
||||||
private string GetArgs(UpdateSettings settings)
|
private string GetArgs(UpdateSettings settings)
|
||||||
{
|
{
|
||||||
var config = _appConfig.GetAll();
|
var url = _appConfig.Get(ConfigurationTypes.Url);
|
||||||
var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url);
|
var storage = _appConfig.Get(ConfigurationTypes.StoragePath);
|
||||||
var storage = config.FirstOrDefault(x => x.Type == ConfigurationTypes.StoragePath);
|
|
||||||
|
|
||||||
var currentLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
var currentLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||||
var processName = (settings.ProcessName.HasValue() ? settings.ProcessName : "Ombi");
|
var processName = (settings.ProcessName.HasValue() ? settings.ProcessName : "Ombi");
|
||||||
|
@ -345,7 +344,6 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
|
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
_appConfig?.Dispose();
|
|
||||||
Settings?.Dispose();
|
Settings?.Dispose();
|
||||||
}
|
}
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Ombi.Schedule.Jobs.Radarr
|
||||||
{
|
{
|
||||||
public class RadarrSync : IRadarrSync
|
public class RadarrSync : IRadarrSync
|
||||||
{
|
{
|
||||||
public RadarrSync(ISettingsService<RadarrSettings> radarr, IRadarrApi radarrApi, ILogger<RadarrSync> log, IOmbiContext ctx)
|
public RadarrSync(ISettingsService<RadarrSettings> radarr, IRadarrApi radarrApi, ILogger<RadarrSync> log, IExternalContext ctx)
|
||||||
{
|
{
|
||||||
RadarrSettings = radarr;
|
RadarrSettings = radarr;
|
||||||
RadarrApi = radarrApi;
|
RadarrApi = radarrApi;
|
||||||
|
@ -28,7 +28,7 @@ namespace Ombi.Schedule.Jobs.Radarr
|
||||||
private ISettingsService<RadarrSettings> RadarrSettings { get; }
|
private ISettingsService<RadarrSettings> RadarrSettings { get; }
|
||||||
private IRadarrApi RadarrApi { get; }
|
private IRadarrApi RadarrApi { get; }
|
||||||
private ILogger<RadarrSync> Logger { get; }
|
private ILogger<RadarrSync> Logger { get; }
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
|
|
||||||
private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1);
|
private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
@ -17,7 +16,7 @@ namespace Ombi.Schedule.Jobs.SickRage
|
||||||
{
|
{
|
||||||
public class SickRageSync : ISickRageSync
|
public class SickRageSync : ISickRageSync
|
||||||
{
|
{
|
||||||
public SickRageSync(ISettingsService<SickRageSettings> s, ISickRageApi api, ILogger<SickRageSync> l, IOmbiContext ctx)
|
public SickRageSync(ISettingsService<SickRageSettings> s, ISickRageApi api, ILogger<SickRageSync> l, IExternalContext ctx)
|
||||||
{
|
{
|
||||||
_settings = s;
|
_settings = s;
|
||||||
_api = api;
|
_api = api;
|
||||||
|
@ -29,7 +28,7 @@ namespace Ombi.Schedule.Jobs.SickRage
|
||||||
private readonly ISettingsService<SickRageSettings> _settings;
|
private readonly ISettingsService<SickRageSettings> _settings;
|
||||||
private readonly ISickRageApi _api;
|
private readonly ISickRageApi _api;
|
||||||
private readonly ILogger<SickRageSync> _log;
|
private readonly ILogger<SickRageSync> _log;
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
|
|
||||||
public async Task Start()
|
public async Task Start()
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Ombi.Schedule.Jobs.Sonarr
|
||||||
{
|
{
|
||||||
public class SonarrSync : ISonarrSync
|
public class SonarrSync : ISonarrSync
|
||||||
{
|
{
|
||||||
public SonarrSync(ISettingsService<SonarrSettings> s, ISonarrApi api, ILogger<SonarrSync> l, IOmbiContext ctx)
|
public SonarrSync(ISettingsService<SonarrSettings> s, ISonarrApi api, ILogger<SonarrSync> l, IExternalContext ctx)
|
||||||
{
|
{
|
||||||
_settings = s;
|
_settings = s;
|
||||||
_api = api;
|
_api = api;
|
||||||
|
@ -31,7 +31,7 @@ namespace Ombi.Schedule.Jobs.Sonarr
|
||||||
private readonly ISettingsService<SonarrSettings> _settings;
|
private readonly ISettingsService<SonarrSettings> _settings;
|
||||||
private readonly ISonarrApi _api;
|
private readonly ISonarrApi _api;
|
||||||
private readonly ILogger<SonarrSync> _log;
|
private readonly ILogger<SonarrSync> _log;
|
||||||
private readonly IOmbiContext _ctx;
|
private readonly IExternalContext _ctx;
|
||||||
|
|
||||||
public async Task Start()
|
public async Task Start()
|
||||||
{
|
{
|
||||||
|
|
68
src/Ombi.Store/Context/ExternalContext.cs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Context
|
||||||
|
{
|
||||||
|
public sealed class ExternalContext : DbContext, IExternalContext
|
||||||
|
{
|
||||||
|
private static bool _created;
|
||||||
|
public ExternalContext()
|
||||||
|
{
|
||||||
|
if (_created) return;
|
||||||
|
|
||||||
|
_created = true;
|
||||||
|
Database.Migrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<PlexServerContent> PlexServerContent { get; set; }
|
||||||
|
public DbSet<PlexSeasonsContent> PlexSeasonsContent { get; set; }
|
||||||
|
public DbSet<PlexEpisode> PlexEpisode { get; set; }
|
||||||
|
public DbSet<RadarrCache> RadarrCache { get; set; }
|
||||||
|
public DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
|
||||||
|
public DbSet<EmbyContent> EmbyContent { get; set; }
|
||||||
|
public DbSet<EmbyEpisode> EmbyEpisode { get; set; }
|
||||||
|
|
||||||
|
public DbSet<SonarrCache> SonarrCache { get; set; }
|
||||||
|
public DbSet<LidarrArtistCache> LidarrArtistCache { get; set; }
|
||||||
|
public DbSet<LidarrAlbumCache> LidarrAlbumCache { get; set; }
|
||||||
|
public DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; }
|
||||||
|
public DbSet<SickRageCache> SickRageCache { get; set; }
|
||||||
|
public DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
var i = StoragePathSingleton.Instance;
|
||||||
|
if (string.IsNullOrEmpty(i.StoragePath))
|
||||||
|
{
|
||||||
|
i.StoragePath = string.Empty;
|
||||||
|
}
|
||||||
|
optionsBuilder.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "OmbiExternal.db")}");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Entity<PlexServerContent>().HasMany(x => x.Episodes)
|
||||||
|
.WithOne(x => x.Series)
|
||||||
|
.HasPrincipalKey(x => x.Key)
|
||||||
|
.HasForeignKey(x => x.GrandparentKey);
|
||||||
|
|
||||||
|
builder.Entity<EmbyEpisode>()
|
||||||
|
.HasOne(p => p.Series)
|
||||||
|
.WithMany(b => b.Episodes)
|
||||||
|
.HasPrincipalKey(x => x.EmbyId)
|
||||||
|
.HasForeignKey(p => p.ParentId);
|
||||||
|
|
||||||
|
base.OnModelCreating(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Seed()
|
||||||
|
{
|
||||||
|
// VACUUM;
|
||||||
|
Database.ExecuteSqlCommand("VACUUM;");
|
||||||
|
SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/Ombi.Store/Context/IDbContext.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Context
|
||||||
|
{
|
||||||
|
public interface IDbContext : IDisposable
|
||||||
|
{
|
||||||
|
EntityEntry Update(object entity);
|
||||||
|
EntityEntry<TEntity> Update<TEntity>(TEntity entity) where TEntity : class;
|
||||||
|
int SaveChanges();
|
||||||
|
void Seed();
|
||||||
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||||
|
DatabaseFacade Database { get; }
|
||||||
|
EntityEntry<T> Entry<T>(T entry) where T : class;
|
||||||
|
EntityEntry<TEntity> Attach<TEntity>(TEntity entity) where TEntity : class;
|
||||||
|
DbSet<TEntity> Set<TEntity>() where TEntity : class;
|
||||||
|
}
|
||||||
|
}
|
21
src/Ombi.Store/Context/IExternalContext.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Context
|
||||||
|
{
|
||||||
|
public interface IExternalContext : IDbContext
|
||||||
|
{
|
||||||
|
DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
|
||||||
|
DbSet<EmbyContent> EmbyContent { get; set; }
|
||||||
|
DbSet<EmbyEpisode> EmbyEpisode { get; set; }
|
||||||
|
DbSet<LidarrAlbumCache> LidarrAlbumCache { get; set; }
|
||||||
|
DbSet<LidarrArtistCache> LidarrArtistCache { get; set; }
|
||||||
|
DbSet<PlexEpisode> PlexEpisode { get; set; }
|
||||||
|
DbSet<PlexServerContent> PlexServerContent { get; set; }
|
||||||
|
DbSet<RadarrCache> RadarrCache { get; set; }
|
||||||
|
DbSet<SickRageCache> SickRageCache { get; set; }
|
||||||
|
DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
||||||
|
DbSet<SonarrCache> SonarrCache { get; set; }
|
||||||
|
DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,20 +9,15 @@ using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
namespace Ombi.Store.Context
|
namespace Ombi.Store.Context
|
||||||
{
|
{
|
||||||
public interface IOmbiContext : IDisposable
|
public interface IOmbiContext : IDbContext
|
||||||
{
|
{
|
||||||
int SaveChanges();
|
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
//DbSet<PlexServerContent> PlexServerContent { get; set; }
|
||||||
|
//DbSet<PlexEpisode> PlexEpisode { get; set; }
|
||||||
DbSet<GlobalSettings> Settings { get; set; }
|
DbSet<GlobalSettings> Settings { get; set; }
|
||||||
DbSet<PlexServerContent> PlexServerContent { get; set; }
|
//DbSet<RadarrCache> RadarrCache { get; set; }
|
||||||
DbSet<PlexEpisode> PlexEpisode { get; set; }
|
//DbSet<EmbyContent> EmbyContent { get; set; }
|
||||||
DbSet<RadarrCache> RadarrCache { get; set; }
|
//DbSet<EmbyEpisode> EmbyEpisode { get; set; }
|
||||||
DbSet<EmbyContent> EmbyContent { get; set; }
|
|
||||||
DbSet<EmbyEpisode> EmbyEpisode { get; set; }
|
|
||||||
DatabaseFacade Database { get; }
|
|
||||||
EntityEntry<T> Entry<T>(T entry) where T : class;
|
|
||||||
EntityEntry<TEntity> Attach<TEntity>(TEntity entity) where TEntity : class;
|
|
||||||
DbSet<TEntity> Set<TEntity>() where TEntity : class;
|
|
||||||
DbSet<NotificationTemplates> NotificationTemplates { get; set; }
|
DbSet<NotificationTemplates> NotificationTemplates { get; set; }
|
||||||
DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
||||||
DbSet<Votes> Votes { get; set; }
|
DbSet<Votes> Votes { get; set; }
|
||||||
|
@ -36,14 +31,12 @@ namespace Ombi.Store.Context
|
||||||
DbSet<IssueCategory> IssueCategories { get; set; }
|
DbSet<IssueCategory> IssueCategories { get; set; }
|
||||||
DbSet<Tokens> Tokens { get; set; }
|
DbSet<Tokens> Tokens { get; set; }
|
||||||
DbSet<SonarrCache> SonarrCache { get; set; }
|
DbSet<SonarrCache> SonarrCache { get; set; }
|
||||||
DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; }
|
//DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; }
|
||||||
EntityEntry Update(object entity);
|
//DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
|
||||||
EntityEntry<TEntity> Update<TEntity>(TEntity entity) where TEntity : class;
|
//DbSet<SickRageCache> SickRageCache { get; set; }
|
||||||
DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
|
//DbSet<LidarrArtistCache> LidarrArtistCache { get; set; }
|
||||||
DbSet<SickRageCache> SickRageCache { get; set; }
|
//DbSet<LidarrAlbumCache> LidarrAlbumCache { get; set; }
|
||||||
DbSet<LidarrArtistCache> LidarrArtistCache { get; set; }
|
//DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
||||||
DbSet<LidarrAlbumCache> LidarrAlbumCache { get; set; }
|
|
||||||
DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
|
||||||
DbSet<RequestLog> RequestLogs { get; set; }
|
DbSet<RequestLog> RequestLogs { get; set; }
|
||||||
DbSet<RecentlyAddedLog> RecentlyAddedLogs { get; set; }
|
DbSet<RecentlyAddedLog> RecentlyAddedLogs { get; set; }
|
||||||
DbSet<RequestSubscription> RequestSubscription { get; set; }
|
DbSet<RequestSubscription> RequestSubscription { get; set; }
|
||||||
|
|
11
src/Ombi.Store/Context/ISettingsContext.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Context
|
||||||
|
{
|
||||||
|
public interface ISettingsContext : IDbContext
|
||||||
|
{
|
||||||
|
DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
||||||
|
DbSet<GlobalSettings> Settings { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,9 +22,11 @@ namespace Ombi.Store.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbSet<NotificationTemplates> NotificationTemplates { get; set; }
|
public DbSet<NotificationTemplates> NotificationTemplates { get; set; }
|
||||||
public DbSet<GlobalSettings> Settings { get; set; }
|
public DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
||||||
public DbSet<PlexServerContent> PlexServerContent { get; set; }
|
public DbSet<PlexServerContent> PlexServerContent { get; set; }
|
||||||
|
public DbSet<PlexSeasonsContent> PlexSeasonsContent { get; set; }
|
||||||
public DbSet<PlexEpisode> PlexEpisode { get; set; }
|
public DbSet<PlexEpisode> PlexEpisode { get; set; }
|
||||||
|
public DbSet<GlobalSettings> Settings { get; set; }
|
||||||
public DbSet<RadarrCache> RadarrCache { get; set; }
|
public DbSet<RadarrCache> RadarrCache { get; set; }
|
||||||
public DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
|
public DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
|
||||||
public DbSet<EmbyContent> EmbyContent { get; set; }
|
public DbSet<EmbyContent> EmbyContent { get; set; }
|
||||||
|
@ -54,7 +56,6 @@ namespace Ombi.Store.Context
|
||||||
public DbSet<RequestSubscription> RequestSubscription { get; set; }
|
public DbSet<RequestSubscription> RequestSubscription { get; set; }
|
||||||
public DbSet<UserNotificationPreferences> UserNotificationPreferences { get; set; }
|
public DbSet<UserNotificationPreferences> UserNotificationPreferences { get; set; }
|
||||||
public DbSet<UserQualityProfiles> UserQualityProfileses { get; set; }
|
public DbSet<UserQualityProfiles> UserQualityProfileses { get; set; }
|
||||||
public DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
|
@ -85,39 +86,6 @@ namespace Ombi.Store.Context
|
||||||
|
|
||||||
public void Seed()
|
public void Seed()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Add the tokens
|
|
||||||
var fanArt = ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.FanartTv);
|
|
||||||
if (fanArt == null)
|
|
||||||
{
|
|
||||||
ApplicationConfigurations.Add(new ApplicationConfiguration
|
|
||||||
{
|
|
||||||
Type = ConfigurationTypes.FanartTv,
|
|
||||||
Value = "4b6d983efa54d8f45c68432521335f15"
|
|
||||||
});
|
|
||||||
SaveChanges();
|
|
||||||
}
|
|
||||||
var movieDb = ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.FanartTv);
|
|
||||||
if (movieDb == null)
|
|
||||||
{
|
|
||||||
ApplicationConfigurations.Add(new ApplicationConfiguration
|
|
||||||
{
|
|
||||||
Type = ConfigurationTypes.TheMovieDb,
|
|
||||||
Value = "b8eabaf5608b88d0298aa189dd90bf00"
|
|
||||||
});
|
|
||||||
SaveChanges();
|
|
||||||
}
|
|
||||||
var notification = ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.Notification);
|
|
||||||
if (notification == null)
|
|
||||||
{
|
|
||||||
ApplicationConfigurations.Add(new ApplicationConfiguration
|
|
||||||
{
|
|
||||||
Type = ConfigurationTypes.Notification,
|
|
||||||
Value = "4f0260c4-9c3d-41ab-8d68-27cb5a593f0e"
|
|
||||||
});
|
|
||||||
SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
// VACUUM;
|
// VACUUM;
|
||||||
Database.ExecuteSqlCommand("VACUUM;");
|
Database.ExecuteSqlCommand("VACUUM;");
|
||||||
|
|
||||||
|
@ -145,6 +113,16 @@ namespace Ombi.Store.Context
|
||||||
SaveChanges();
|
SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var manageOwnRequestsRole = Roles.Where(x => x.Name == OmbiRoles.ManageOwnRequests);
|
||||||
|
if (!manageOwnRequestsRole.Any())
|
||||||
|
{
|
||||||
|
Roles.Add(new IdentityRole(OmbiRoles.ManageOwnRequests)
|
||||||
|
{
|
||||||
|
NormalizedName = OmbiRoles.ManageOwnRequests.ToUpper()
|
||||||
|
});
|
||||||
|
SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we have the API User
|
// Make sure we have the API User
|
||||||
var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase));
|
var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase));
|
||||||
if (!apiUserExists)
|
if (!apiUserExists)
|
||||||
|
|
70
src/Ombi.Store/Context/SettingsContext.cs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Context
|
||||||
|
{
|
||||||
|
public sealed class SettingsContext : DbContext, ISettingsContext
|
||||||
|
{
|
||||||
|
private static bool _created;
|
||||||
|
public SettingsContext()
|
||||||
|
{
|
||||||
|
if (_created) return;
|
||||||
|
|
||||||
|
_created = true;
|
||||||
|
Database.Migrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<GlobalSettings> Settings { get; set; }
|
||||||
|
public DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
var i = StoragePathSingleton.Instance;
|
||||||
|
if (string.IsNullOrEmpty(i.StoragePath))
|
||||||
|
{
|
||||||
|
i.StoragePath = string.Empty;
|
||||||
|
}
|
||||||
|
optionsBuilder.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "OmbiSettings.db")}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Seed()
|
||||||
|
{
|
||||||
|
// Add the tokens
|
||||||
|
var fanArt = ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.FanartTv);
|
||||||
|
if (fanArt == null)
|
||||||
|
{
|
||||||
|
ApplicationConfigurations.Add(new ApplicationConfiguration
|
||||||
|
{
|
||||||
|
Type = ConfigurationTypes.FanartTv,
|
||||||
|
Value = "4b6d983efa54d8f45c68432521335f15"
|
||||||
|
});
|
||||||
|
SaveChanges();
|
||||||
|
}
|
||||||
|
var movieDb = ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.FanartTv);
|
||||||
|
if (movieDb == null)
|
||||||
|
{
|
||||||
|
ApplicationConfigurations.Add(new ApplicationConfiguration
|
||||||
|
{
|
||||||
|
Type = ConfigurationTypes.TheMovieDb,
|
||||||
|
Value = "b8eabaf5608b88d0298aa189dd90bf00"
|
||||||
|
});
|
||||||
|
SaveChanges();
|
||||||
|
}
|
||||||
|
var notification = ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.Notification);
|
||||||
|
if (notification == null)
|
||||||
|
{
|
||||||
|
ApplicationConfigurations.Add(new ApplicationConfiguration
|
||||||
|
{
|
||||||
|
Type = ConfigurationTypes.Notification,
|
||||||
|
Value = "4f0260c4-9c3d-41ab-8d68-27cb5a593f0e"
|
||||||
|
});
|
||||||
|
SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,13 +42,9 @@ namespace Ombi.Store.Entities
|
||||||
public PlexMediaTypeEntity Type { get; set; }
|
public PlexMediaTypeEntity Type { get; set; }
|
||||||
|
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only used for TV Shows
|
|
||||||
/// </summary>
|
|
||||||
public virtual ICollection<PlexSeasonsContent> Seasons { get; set; }
|
|
||||||
|
|
||||||
public ICollection<PlexEpisode> Episodes { get; set; }
|
public ICollection<PlexEpisode> Episodes { get; set; }
|
||||||
|
public ICollection<PlexSeasonsContent> Seasons { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Plex's internal ID for this item
|
/// Plex's internal ID for this item
|
||||||
|
|
312
src/Ombi.Store/Migrations/External/20181004134907_Inital.Designer.cs
generated
vendored
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.External
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ExternalContext))]
|
||||||
|
[Migration("20181004134907_Inital")]
|
||||||
|
partial class Inital
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CouchPotatoCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("EmbyContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ParentId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentId");
|
||||||
|
|
||||||
|
b.ToTable("EmbyEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<int>("ArtistId");
|
||||||
|
|
||||||
|
b.Property<string>("ForeignAlbumId");
|
||||||
|
|
||||||
|
b.Property<bool>("Monitored");
|
||||||
|
|
||||||
|
b.Property<decimal>("PercentOfTracks");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<int>("TrackCount");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LidarrAlbumCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ArtistId");
|
||||||
|
|
||||||
|
b.Property<string>("ArtistName");
|
||||||
|
|
||||||
|
b.Property<string>("ForeignArtistId");
|
||||||
|
|
||||||
|
b.Property<bool>("Monitored");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LidarrArtistCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("GrandparentKey");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GrandparentKey");
|
||||||
|
|
||||||
|
b.ToTable("PlexEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("PlexContentId");
|
||||||
|
|
||||||
|
b.Property<int?>("PlexServerContentId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlexServerContentId");
|
||||||
|
|
||||||
|
b.ToTable("PlexSeasonsContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<string>("Quality");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseYear");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PlexServerContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RadarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("ParentId")
|
||||||
|
.HasPrincipalKey("EmbyId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("GrandparentKey")
|
||||||
|
.HasPrincipalKey("Key")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent")
|
||||||
|
.WithMany("Seasons")
|
||||||
|
.HasForeignKey("PlexServerContentId");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
308
src/Ombi.Store/Migrations/External/20181004134907_Inital.cs
vendored
Normal file
|
@ -0,0 +1,308 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.External
|
||||||
|
{
|
||||||
|
public partial class Inital : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CouchPotatoCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
TheMovieDbId = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CouchPotatoCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "EmbyContent",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Title = table.Column<string>(nullable: true),
|
||||||
|
ProviderId = table.Column<string>(nullable: true),
|
||||||
|
EmbyId = table.Column<string>(nullable: false),
|
||||||
|
Type = table.Column<int>(nullable: false),
|
||||||
|
AddedAt = table.Column<DateTime>(nullable: false),
|
||||||
|
ImdbId = table.Column<string>(nullable: true),
|
||||||
|
TheMovieDbId = table.Column<string>(nullable: true),
|
||||||
|
TvDbId = table.Column<string>(nullable: true),
|
||||||
|
Url = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_EmbyContent", x => x.Id);
|
||||||
|
table.UniqueConstraint("AK_EmbyContent_EmbyId", x => x.EmbyId);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "LidarrAlbumCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
ArtistId = table.Column<int>(nullable: false),
|
||||||
|
ForeignAlbumId = table.Column<string>(nullable: true),
|
||||||
|
TrackCount = table.Column<int>(nullable: false),
|
||||||
|
ReleaseDate = table.Column<DateTime>(nullable: false),
|
||||||
|
Monitored = table.Column<bool>(nullable: false),
|
||||||
|
Title = table.Column<string>(nullable: true),
|
||||||
|
PercentOfTracks = table.Column<decimal>(nullable: false),
|
||||||
|
AddedAt = table.Column<DateTime>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "LidarrArtistCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
ArtistId = table.Column<int>(nullable: false),
|
||||||
|
ArtistName = table.Column<string>(nullable: true),
|
||||||
|
ForeignArtistId = table.Column<string>(nullable: true),
|
||||||
|
Monitored = table.Column<bool>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_LidarrArtistCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PlexServerContent",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Title = table.Column<string>(nullable: true),
|
||||||
|
ReleaseYear = table.Column<string>(nullable: true),
|
||||||
|
ImdbId = table.Column<string>(nullable: true),
|
||||||
|
TvDbId = table.Column<string>(nullable: true),
|
||||||
|
TheMovieDbId = table.Column<string>(nullable: true),
|
||||||
|
Type = table.Column<int>(nullable: false),
|
||||||
|
Url = table.Column<string>(nullable: true),
|
||||||
|
Key = table.Column<int>(nullable: false),
|
||||||
|
AddedAt = table.Column<DateTime>(nullable: false),
|
||||||
|
Quality = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_PlexServerContent", x => x.Id);
|
||||||
|
table.UniqueConstraint("AK_PlexServerContent_Key", x => x.Key);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "RadarrCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
TheMovieDbId = table.Column<int>(nullable: false),
|
||||||
|
HasFile = table.Column<bool>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_RadarrCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SickRageCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
TvDbId = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SickRageCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SickRageEpisodeCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
SeasonNumber = table.Column<int>(nullable: false),
|
||||||
|
EpisodeNumber = table.Column<int>(nullable: false),
|
||||||
|
TvDbId = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SickRageEpisodeCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SonarrCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
TvDbId = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SonarrCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SonarrEpisodeCache",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
SeasonNumber = table.Column<int>(nullable: false),
|
||||||
|
EpisodeNumber = table.Column<int>(nullable: false),
|
||||||
|
TvDbId = table.Column<int>(nullable: false),
|
||||||
|
HasFile = table.Column<bool>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SonarrEpisodeCache", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "EmbyEpisode",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Title = table.Column<string>(nullable: true),
|
||||||
|
EmbyId = table.Column<string>(nullable: true),
|
||||||
|
EpisodeNumber = table.Column<int>(nullable: false),
|
||||||
|
SeasonNumber = table.Column<int>(nullable: false),
|
||||||
|
ParentId = table.Column<string>(nullable: true),
|
||||||
|
ProviderId = table.Column<string>(nullable: true),
|
||||||
|
AddedAt = table.Column<DateTime>(nullable: false),
|
||||||
|
TvDbId = table.Column<string>(nullable: true),
|
||||||
|
ImdbId = table.Column<string>(nullable: true),
|
||||||
|
TheMovieDbId = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_EmbyEpisode", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_EmbyEpisode_EmbyContent_ParentId",
|
||||||
|
column: x => x.ParentId,
|
||||||
|
principalTable: "EmbyContent",
|
||||||
|
principalColumn: "EmbyId",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PlexEpisode",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
EpisodeNumber = table.Column<int>(nullable: false),
|
||||||
|
SeasonNumber = table.Column<int>(nullable: false),
|
||||||
|
Key = table.Column<int>(nullable: false),
|
||||||
|
Title = table.Column<string>(nullable: true),
|
||||||
|
ParentKey = table.Column<int>(nullable: false),
|
||||||
|
GrandparentKey = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_PlexEpisode", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_PlexEpisode_PlexServerContent_GrandparentKey",
|
||||||
|
column: x => x.GrandparentKey,
|
||||||
|
principalTable: "PlexServerContent",
|
||||||
|
principalColumn: "Key",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PlexSeasonsContent",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
PlexContentId = table.Column<int>(nullable: false),
|
||||||
|
SeasonNumber = table.Column<int>(nullable: false),
|
||||||
|
SeasonKey = table.Column<int>(nullable: false),
|
||||||
|
ParentKey = table.Column<int>(nullable: false),
|
||||||
|
PlexServerContentId = table.Column<int>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_PlexSeasonsContent", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_PlexSeasonsContent_PlexServerContent_PlexServerContentId",
|
||||||
|
column: x => x.PlexServerContentId,
|
||||||
|
principalTable: "PlexServerContent",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_EmbyEpisode_ParentId",
|
||||||
|
table: "EmbyEpisode",
|
||||||
|
column: "ParentId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PlexEpisode_GrandparentKey",
|
||||||
|
table: "PlexEpisode",
|
||||||
|
column: "GrandparentKey");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PlexSeasonsContent_PlexServerContentId",
|
||||||
|
table: "PlexSeasonsContent",
|
||||||
|
column: "PlexServerContentId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CouchPotatoCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "EmbyEpisode");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "LidarrAlbumCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "LidarrArtistCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PlexEpisode");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PlexSeasonsContent");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "RadarrCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SickRageCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SickRageEpisodeCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SonarrCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SonarrEpisodeCache");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "EmbyContent");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PlexServerContent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
310
src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs
vendored
Normal file
|
@ -0,0 +1,310 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.External
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ExternalContext))]
|
||||||
|
partial class ExternalContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CouchPotatoCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("EmbyContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ParentId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentId");
|
||||||
|
|
||||||
|
b.ToTable("EmbyEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<int>("ArtistId");
|
||||||
|
|
||||||
|
b.Property<string>("ForeignAlbumId");
|
||||||
|
|
||||||
|
b.Property<bool>("Monitored");
|
||||||
|
|
||||||
|
b.Property<decimal>("PercentOfTracks");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<int>("TrackCount");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LidarrAlbumCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ArtistId");
|
||||||
|
|
||||||
|
b.Property<string>("ArtistName");
|
||||||
|
|
||||||
|
b.Property<string>("ForeignArtistId");
|
||||||
|
|
||||||
|
b.Property<bool>("Monitored");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LidarrArtistCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("GrandparentKey");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GrandparentKey");
|
||||||
|
|
||||||
|
b.ToTable("PlexEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("PlexContentId");
|
||||||
|
|
||||||
|
b.Property<int?>("PlexServerContentId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlexServerContentId");
|
||||||
|
|
||||||
|
b.ToTable("PlexSeasonsContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<string>("Quality");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseYear");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PlexServerContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RadarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("ParentId")
|
||||||
|
.HasPrincipalKey("EmbyId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("GrandparentKey")
|
||||||
|
.HasPrincipalKey("Key")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent")
|
||||||
|
.WithMany("Seasons")
|
||||||
|
.HasForeignKey("PlexServerContentId");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/Ombi.Store/Migrations/Settings/20181004132516_Inital.Designer.cs
generated
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.Settings
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SettingsContext))]
|
||||||
|
[Migration("20181004132516_Inital")]
|
||||||
|
partial class Inital
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ApplicationConfiguration");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content");
|
||||||
|
|
||||||
|
b.Property<string>("SettingsName");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("GlobalSettings");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
src/Ombi.Store/Migrations/Settings/20181004132516_Inital.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.Settings
|
||||||
|
{
|
||||||
|
public partial class Inital : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ApplicationConfiguration",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Type = table.Column<int>(nullable: false),
|
||||||
|
Value = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ApplicationConfiguration", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "GlobalSettings",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Content = table.Column<string>(nullable: true),
|
||||||
|
SettingsName = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_GlobalSettings", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ApplicationConfiguration");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "GlobalSettings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.Settings
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SettingsContext))]
|
||||||
|
partial class SettingsContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.3-rtm-32065");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ApplicationConfiguration");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content");
|
||||||
|
|
||||||
|
b.Property<string>("SettingsName");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("GlobalSettings");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,16 +8,20 @@ namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
public class ApplicationConfigRepository : IApplicationConfigRepository
|
public class ApplicationConfigRepository : IApplicationConfigRepository
|
||||||
{
|
{
|
||||||
public ApplicationConfigRepository(IOmbiContext ctx)
|
public ApplicationConfigRepository(ISettingsContext ctx)
|
||||||
{
|
{
|
||||||
Ctx = ctx;
|
Ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IOmbiContext Ctx { get; }
|
private ISettingsContext Ctx { get; }
|
||||||
|
|
||||||
public async Task<ApplicationConfiguration> Get(ConfigurationTypes type)
|
public Task<ApplicationConfiguration> GetAsync(ConfigurationTypes type)
|
||||||
{
|
{
|
||||||
return await Ctx.ApplicationConfigurations.FirstOrDefaultAsync(x => x.Type == type);
|
return Ctx.ApplicationConfigurations.FirstOrDefaultAsync(x => x.Type == type);
|
||||||
|
}
|
||||||
|
public ApplicationConfiguration Get(ConfigurationTypes type)
|
||||||
|
{
|
||||||
|
return Ctx.ApplicationConfigurations.FirstOrDefault(x => x.Type == type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
105
src/Ombi.Store/Repository/BaseRepository.cs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
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 BaseRepository<T, U> : IRepository<T> where T : Entity where U : IDbContext
|
||||||
|
{
|
||||||
|
public BaseRepository(U ctx)
|
||||||
|
{
|
||||||
|
_ctx = ctx;
|
||||||
|
_db = _ctx.Set<T>();
|
||||||
|
}
|
||||||
|
public DbSet<T> _db { get; }
|
||||||
|
private readonly U _ctx;
|
||||||
|
|
||||||
|
public async Task<T> Find(object key)
|
||||||
|
{
|
||||||
|
return await _db.FindAsync(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQueryable<T> GetAll()
|
||||||
|
{
|
||||||
|
return _db.AsQueryable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T> FirstOrDefaultAsync(Expression<Func<T,bool>> predicate)
|
||||||
|
{
|
||||||
|
return await _db.FirstOrDefaultAsync(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddRange(IEnumerable<T> content, bool save = true)
|
||||||
|
{
|
||||||
|
_db.AddRange(content);
|
||||||
|
if (save)
|
||||||
|
{
|
||||||
|
await _ctx.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T> Add(T content)
|
||||||
|
{
|
||||||
|
await _db.AddAsync(content);
|
||||||
|
await _ctx.SaveChangesAsync();
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Delete(T request)
|
||||||
|
{
|
||||||
|
_db.Remove(request);
|
||||||
|
await _ctx.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteRange(IEnumerable<T> req)
|
||||||
|
{
|
||||||
|
_db.RemoveRange(req);
|
||||||
|
await _ctx.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> SaveChangesAsync()
|
||||||
|
{
|
||||||
|
return await _ctx.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>(
|
||||||
|
IQueryable<TEntity> source, Expression<Func<TEntity, TProperty>> navigationPropertyPath)
|
||||||
|
where TEntity : class
|
||||||
|
{
|
||||||
|
return source.Include(navigationPropertyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ExecuteSql(string sql)
|
||||||
|
{
|
||||||
|
await _ctx.Database.ExecuteSqlCommandAsync(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
// Protected implementation of Dispose pattern.
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_ctx?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,15 +35,15 @@ using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
public class EmbyContentRepository : Repository<EmbyContent>, IEmbyContentRepository
|
public class EmbyContentRepository : ExternalRepository<EmbyContent>, IEmbyContentRepository
|
||||||
{
|
{
|
||||||
|
|
||||||
public EmbyContentRepository(IOmbiContext db):base(db)
|
public EmbyContentRepository(IExternalContext db):base(db)
|
||||||
{
|
{
|
||||||
Db = db;
|
Db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IOmbiContext Db { get; }
|
private IExternalContext Db { get; }
|
||||||
|
|
||||||
|
|
||||||
public async Task<EmbyContent> GetByImdbId(string imdbid)
|
public async Task<EmbyContent> GetByImdbId(string imdbid)
|
||||||
|
|
12
src/Ombi.Store/Repository/ExternalRepository.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Repository
|
||||||
|
{
|
||||||
|
public class ExternalRepository<T> : BaseRepository<T, IExternalContext>, IExternalRepository<T> where T : Entity
|
||||||
|
{
|
||||||
|
public ExternalRepository(IExternalContext ctx) : base(ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
public interface IApplicationConfigRepository
|
public interface IApplicationConfigRepository
|
||||||
{
|
{
|
||||||
Task<ApplicationConfiguration> Get(ConfigurationTypes type);
|
Task<ApplicationConfiguration> GetAsync(ConfigurationTypes type);
|
||||||
|
ApplicationConfiguration Get(ConfigurationTypes type);
|
||||||
}
|
}
|
||||||
}
|
}
|
30
src/Ombi.Store/Repository/IExternalRepository.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
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.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Repository
|
||||||
|
{
|
||||||
|
public interface IExternalRepository<T> : IDisposable where T : Entity
|
||||||
|
{
|
||||||
|
Task<T> Find(object key);
|
||||||
|
IQueryable<T> GetAll();
|
||||||
|
Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate);
|
||||||
|
Task AddRange(IEnumerable<T> content, bool save = true);
|
||||||
|
Task<T> Add(T content);
|
||||||
|
Task DeleteRange(IEnumerable<T> req);
|
||||||
|
Task Delete(T request);
|
||||||
|
Task<int> SaveChangesAsync();
|
||||||
|
|
||||||
|
IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>(
|
||||||
|
IQueryable<TEntity> source, Expression<Func<TEntity, TProperty>> navigationPropertyPath)
|
||||||
|
where TEntity : class;
|
||||||
|
|
||||||
|
Task ExecuteSql(string sql);
|
||||||
|
DbSet<T> _db { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
public interface IPlexContentRepository : IRepository<PlexServerContent>
|
public interface IPlexContentRepository : IExternalRepository<PlexServerContent>
|
||||||
{
|
{
|
||||||
Task<bool> ContentExists(string providerId);
|
Task<bool> ContentExists(string providerId);
|
||||||
Task<PlexServerContent> Get(string providerId);
|
Task<PlexServerContent> Get(string providerId);
|
||||||
|
|
|
@ -36,15 +36,15 @@ using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
public class PlexServerContentRepository : Repository<PlexServerContent>, IPlexContentRepository
|
public class PlexServerContentRepository : ExternalRepository<PlexServerContent>, IPlexContentRepository
|
||||||
{
|
{
|
||||||
|
|
||||||
public PlexServerContentRepository(IOmbiContext db) : base(db)
|
public PlexServerContentRepository(IExternalContext db) : base(db)
|
||||||
{
|
{
|
||||||
Db = db;
|
Db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IOmbiContext Db { get; }
|
private IExternalContext Db { get; }
|
||||||
|
|
||||||
|
|
||||||
public async Task<bool> ContentExists(string providerId)
|
public async Task<bool> ContentExists(string providerId)
|
||||||
|
|
|
@ -1,105 +1,12 @@
|
||||||
using System;
|
using Ombi.Store.Context;
|
||||||
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;
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
public class Repository<T> : IRepository<T> where T : Entity
|
public class Repository<T> : BaseRepository<T,IOmbiContext>, IRepository<T> where T : Entity
|
||||||
{
|
{
|
||||||
public Repository(IOmbiContext ctx)
|
public Repository(IOmbiContext ctx) : base(ctx)
|
||||||
{
|
{
|
||||||
_ctx = ctx;
|
|
||||||
_db = _ctx.Set<T>();
|
|
||||||
}
|
|
||||||
public DbSet<T> _db { get; }
|
|
||||||
private readonly IOmbiContext _ctx;
|
|
||||||
|
|
||||||
public async Task<T> Find(object key)
|
|
||||||
{
|
|
||||||
return await _db.FindAsync(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IQueryable<T> GetAll()
|
|
||||||
{
|
|
||||||
return _db.AsQueryable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<T> FirstOrDefaultAsync(Expression<Func<T,bool>> predicate)
|
|
||||||
{
|
|
||||||
return await _db.FirstOrDefaultAsync(predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AddRange(IEnumerable<T> content, bool save = true)
|
|
||||||
{
|
|
||||||
_db.AddRange(content);
|
|
||||||
if (save)
|
|
||||||
{
|
|
||||||
await _ctx.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<T> Add(T content)
|
|
||||||
{
|
|
||||||
await _db.AddAsync(content);
|
|
||||||
await _ctx.SaveChangesAsync();
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Delete(T request)
|
|
||||||
{
|
|
||||||
_db.Remove(request);
|
|
||||||
await _ctx.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRange(IEnumerable<T> req)
|
|
||||||
{
|
|
||||||
_db.RemoveRange(req);
|
|
||||||
await _ctx.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> SaveChangesAsync()
|
|
||||||
{
|
|
||||||
return await _ctx.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IIncludableQueryable<TEntity, TProperty> Include<TEntity, TProperty>(
|
|
||||||
IQueryable<TEntity> source, Expression<Func<TEntity, TProperty>> navigationPropertyPath)
|
|
||||||
where TEntity : class
|
|
||||||
{
|
|
||||||
return source.Include(navigationPropertyPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ExecuteSql(string sql)
|
|
||||||
{
|
|
||||||
await _ctx.Database.ExecuteSqlCommandAsync(sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private bool _disposed;
|
|
||||||
// Protected implementation of Dispose pattern.
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
_ctx?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,13 +12,13 @@ namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
public class SettingsJsonRepository : ISettingsRepository
|
public class SettingsJsonRepository : ISettingsRepository
|
||||||
{
|
{
|
||||||
public SettingsJsonRepository(IOmbiContext ctx, ICacheService mem)
|
public SettingsJsonRepository(ISettingsContext ctx, ICacheService mem)
|
||||||
{
|
{
|
||||||
Db = ctx;
|
Db = ctx;
|
||||||
_cache = mem;
|
_cache = mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IOmbiContext Db { get; }
|
private ISettingsContext Db { get; }
|
||||||
private readonly ICacheService _cache;
|
private readonly ICacheService _cache;
|
||||||
|
|
||||||
public GlobalSettings Insert(GlobalSettings entity)
|
public GlobalSettings Insert(GlobalSettings entity)
|
||||||
|
|
14
src/Ombi/Attributes/UserAttribute.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ombi.Attributes
|
||||||
|
{
|
||||||
|
public class UserAttribute : AuthorizeAttribute
|
||||||
|
{
|
||||||
|
public UserAttribute()
|
||||||
|
{
|
||||||
|
Roles = "ManageOwnRequests";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -186,7 +186,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isAdmin || isRequestUser(request)">
|
<div *ngIf="isAdmin || isRequestUser(request)">
|
||||||
<form id="removeBtn" class="col-md-6">
|
<form id="removeBtn">
|
||||||
<button (click)="removeRequest(request)" style="text-align: right" class="btn btn-sm btn-danger-outline delete">
|
<button (click)="removeRequest(request)" style="text-align: right" class="btn btn-sm btn-danger-outline delete">
|
||||||
<i class="fa fa-minus"></i> {{ 'Requests.Remove' | translate }}
|
<i class="fa fa-minus"></i> {{ 'Requests.Remove' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
<div class="form-group" *ngFor="let u of users">
|
<div class="form-group" *ngFor="let u of users">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<input type="checkbox" id="user{{u.user.id}}" [(ngModel)]="u.selected" (click)="selectSingleUser(u)">
|
<input type="checkbox" id="user{{u.user.id}}" [(ngModel)]="u.selected">
|
||||||
<label for="user{{u.user.id}}">{{u.user.userName}}</label>
|
<label for="user{{u.user.id}}">{{u.user.userName}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -38,10 +38,6 @@ export class MassEmailComponent implements OnInit {
|
||||||
this.users.forEach(u => u.selected = !u.selected);
|
this.users.forEach(u => u.selected = !u.selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
public selectSingleUser(user: IMassEmailUserModel) {
|
|
||||||
user.selected = !user.selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public send() {
|
public send() {
|
||||||
if(!this.subject) {
|
if(!this.subject) {
|
||||||
this.missingSubject = true;
|
this.missingSubject = true;
|
||||||
|
|
|
@ -32,16 +32,16 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let vm of currentVotes">
|
<tr *ngFor="let vm of currentVotes">
|
||||||
<td class="vcenter">
|
<td class="vcenter">
|
||||||
<button class="btn btn-info-outline col-md-6" (click)="upvote(vm)"><i class="fa fa-thumbs-o-up"
|
<button id="{{vm.requestId}}upvote" class="btn btn-info-outline col-md-6" (click)="upvote(vm)"><i class="fa fa-thumbs-o-up"
|
||||||
aria-hidden="true"></i></button>
|
aria-hidden="true"></i></button>
|
||||||
<button class="btn btn-info-outline col-md-6" (click)="downvote(vm)" ><i class="fa fa-thumbs-o-down"
|
<button id="{{vm.requestId}}downvote" class="btn btn-info-outline col-md-6" (click)="downvote(vm)" ><i class="fa fa-thumbs-o-down"
|
||||||
aria-hidden="true"></i></button>
|
aria-hidden="true"></i></button>
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 10%"> <img *ngIf="vm.image" class="img-responsive poster" style="max-width: 100%;
|
<td style="width: 10%"> <img *ngIf="vm.image" class="img-responsive poster" style="max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
width: 100%;"
|
width: 100%;"
|
||||||
(click)="toggle($event, vm.image)" src="{{vm.image}}" alt="poster"></td>
|
(click)="toggle($event, vm.image)" src="{{vm.image}}" alt="poster"></td>
|
||||||
<td class="vcenter">{{vm.title}}</td>
|
<td class="vcenter" [attr.data-test]='vm.requestId'>{{vm.title}}</td>
|
||||||
<td class="vcenter" [innerHTML]="vm.description"></td>
|
<td class="vcenter" [innerHTML]="vm.description"></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let vm of completedVotes">
|
<tr *ngFor="let vm of completedVotes">
|
||||||
<td class="vcenter">
|
<td class="vcenter">
|
||||||
<button class="btn btn-info-outline col-md-6" [ngClass]="{'btn-success-outline': vm.myVote == VoteType.Upvote, 'btn-info-outline': vm.myVote != VoteType.Upvote}"
|
<button id="{{vm.requestId}}upvote" class="btn btn-info-outline col-md-6" [ngClass]="{'btn-success-outline': vm.myVote == VoteType.Upvote, 'btn-info-outline': vm.myVote != VoteType.Upvote}"
|
||||||
(click)="upvote(vm)" [disabled]="vm.myVote == VoteType.Upvote"><i class="fa fa-thumbs-o-up"
|
(click)="upvote(vm)" [disabled]="vm.myVote == VoteType.Upvote"><i class="fa fa-thumbs-o-up"
|
||||||
aria-hidden="true"></i></button>
|
aria-hidden="true"></i></button>
|
||||||
<button class="btn btn-info-outline col-md-6" [ngClass]="{'btn-danger-outline': vm.myVote == VoteType.Downvote, 'btn-info-outline': vm.myVote != VoteType.Downvote}"
|
<button id="{{vm.requestId}}downvote" class="btn btn-info-outline col-md-6" [ngClass]="{'btn-danger-outline': vm.myVote == VoteType.Downvote, 'btn-info-outline': vm.myVote != VoteType.Downvote}"
|
||||||
(click)="downvote(vm)" [disabled]="vm.myVote == VoteType.Downvote"><i class="fa fa-thumbs-o-down"
|
(click)="downvote(vm)" [disabled]="vm.myVote == VoteType.Downvote"><i class="fa fa-thumbs-o-down"
|
||||||
aria-hidden="true"></i></button>
|
aria-hidden="true"></i></button>
|
||||||
</td>
|
</td>
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
height: auto;
|
height: auto;
|
||||||
width: 100%;"
|
width: 100%;"
|
||||||
(click)="toggle($event, vm.image)" src="{{vm.image}}" alt="poster"></td>
|
(click)="toggle($event, vm.image)" src="{{vm.image}}" alt="poster"></td>
|
||||||
<td class="vcenter">{{vm.title}}</td>
|
<td class="vcenter" [attr.data-test]='vm.requestId'>{{vm.title}}</td>
|
||||||
<td class="vcenter" [innerHTML]="vm.description"></td>
|
<td class="vcenter" [innerHTML]="vm.description"></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -240,6 +240,7 @@ namespace Ombi.Controllers
|
||||||
await CreateRole(OmbiRoles.RequestTv);
|
await CreateRole(OmbiRoles.RequestTv);
|
||||||
await CreateRole(OmbiRoles.Disabled);
|
await CreateRole(OmbiRoles.Disabled);
|
||||||
await CreateRole(OmbiRoles.ReceivesNewsletter);
|
await CreateRole(OmbiRoles.ReceivesNewsletter);
|
||||||
|
await CreateRole(OmbiRoles.ManageOwnRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CreateRole(string role)
|
private async Task CreateRole(string role)
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.Get(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
||||||
|
|
||||||
var images = await FanartTvApi.GetTvImages(tvdbid, key.Value);
|
var images = await FanartTvApi.GetTvImages(tvdbid, key.Value);
|
||||||
if (images == null)
|
if (images == null)
|
||||||
|
@ -64,7 +64,7 @@ namespace Ombi.Controllers
|
||||||
[HttpGet("poster/movie/{movieDbId}")]
|
[HttpGet("poster/movie/{movieDbId}")]
|
||||||
public async Task<string> GetMoviePoster(string movieDbId)
|
public async Task<string> GetMoviePoster(string movieDbId)
|
||||||
{
|
{
|
||||||
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.Get(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
||||||
|
|
||||||
var images = await FanartTvApi.GetMovieImages(movieDbId, key.Value);
|
var images = await FanartTvApi.GetMovieImages(movieDbId, key.Value);
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.Get(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
||||||
|
|
||||||
var images = await FanartTvApi.GetTvImages(tvdbid, key.Value);
|
var images = await FanartTvApi.GetTvImages(tvdbid, key.Value);
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ namespace Ombi.Controllers
|
||||||
[HttpGet("background/movie/{movieDbId}")]
|
[HttpGet("background/movie/{movieDbId}")]
|
||||||
public async Task<string> GetMovieBackground(string movieDbId)
|
public async Task<string> GetMovieBackground(string movieDbId)
|
||||||
{
|
{
|
||||||
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.Get(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
||||||
|
|
||||||
var images = await FanartTvApi.GetMovieImages(movieDbId, key.Value);
|
var images = await FanartTvApi.GetMovieImages(movieDbId, key.Value);
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.Get(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
||||||
|
|
||||||
var images = await FanartTvApi.GetTvImages(tvdbid, key.Value);
|
var images = await FanartTvApi.GetTvImages(tvdbid, key.Value);
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ namespace Ombi.Controllers
|
||||||
var movieUrl = string.Empty;
|
var movieUrl = string.Empty;
|
||||||
var tvUrl = string.Empty;
|
var tvUrl = string.Empty;
|
||||||
|
|
||||||
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.Get(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1));
|
||||||
|
|
||||||
if (moviesArray.Length > 0)
|
if (moviesArray.Length > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,10 +4,13 @@ using Ombi.Core.Engine;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
using Ombi.Attributes;
|
using Ombi.Attributes;
|
||||||
using Ombi.Core.Models;
|
using Ombi.Core.Models;
|
||||||
using Ombi.Core.Models.UI;
|
using Ombi.Core.Models.UI;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||||
|
|
||||||
namespace Ombi.Controllers
|
namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
|
@ -16,12 +19,16 @@ namespace Ombi.Controllers
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
||||||
public class MusicRequestController : Controller
|
public class MusicRequestController : Controller
|
||||||
{
|
{
|
||||||
public MusicRequestController(IMusicRequestEngine engine)
|
public MusicRequestController(IMusicRequestEngine engine, IVoteEngine voteEngine, ILogger<MusicRequestController> log)
|
||||||
{
|
{
|
||||||
_engine = engine;
|
_engine = engine;
|
||||||
|
_voteEngine = voteEngine;
|
||||||
|
_log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IMusicRequestEngine _engine;
|
private readonly IMusicRequestEngine _engine;
|
||||||
|
private readonly IVoteEngine _voteEngine;
|
||||||
|
private readonly ILogger _log;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets album requests.
|
/// Gets album requests.
|
||||||
|
@ -66,9 +73,19 @@ namespace Ombi.Controllers
|
||||||
/// <param name="album">The album.</param>
|
/// <param name="album">The album.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<RequestEngineResult> Request([FromBody] MusicAlbumRequestViewModel album)
|
public async Task<RequestEngineResult> RequestAlbum([FromBody] MusicAlbumRequestViewModel album)
|
||||||
{
|
{
|
||||||
return await _engine.RequestAlbum(album);
|
var result = await _engine.RequestAlbum(album);
|
||||||
|
if (result.Result)
|
||||||
|
{
|
||||||
|
var voteResult = await _voteEngine.UpVote(result.RequestId, RequestType.Album);
|
||||||
|
if (voteResult.IsError)
|
||||||
|
{
|
||||||
|
_log.LogError("Couldn't automatically add the vote for the album {0} because {1}", album.ForeignAlbumId, voteResult.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -88,7 +105,7 @@ namespace Ombi.Controllers
|
||||||
/// <param name="requestId">The request identifier.</param>
|
/// <param name="requestId">The request identifier.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpDelete("{requestId:int}")]
|
[HttpDelete("{requestId:int}")]
|
||||||
[PowerUser]
|
[Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")]
|
||||||
public async Task DeleteRequest(int requestId)
|
public async Task DeleteRequest(int requestId)
|
||||||
{
|
{
|
||||||
await _engine.RemoveAlbumRequest(requestId);
|
await _engine.RemoveAlbumRequest(requestId);
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Attributes;
|
using Ombi.Attributes;
|
||||||
using Ombi.Core.Models.UI;
|
using Ombi.Core.Models.UI;
|
||||||
using Ombi.Models;
|
using Ombi.Models;
|
||||||
|
@ -21,14 +22,19 @@ namespace Ombi.Controllers
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
||||||
public class RequestController : Controller
|
public class RequestController : Controller
|
||||||
{
|
{
|
||||||
public RequestController(IMovieRequestEngine engine, ITvRequestEngine tvRequestEngine)
|
public RequestController(IMovieRequestEngine engine, ITvRequestEngine tvRequestEngine, IVoteEngine vote,
|
||||||
|
ILogger<RequestController> log)
|
||||||
{
|
{
|
||||||
MovieRequestEngine = engine;
|
MovieRequestEngine = engine;
|
||||||
TvRequestEngine = tvRequestEngine;
|
TvRequestEngine = tvRequestEngine;
|
||||||
|
VoteEngine = vote;
|
||||||
|
Log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMovieRequestEngine MovieRequestEngine { get; }
|
private IMovieRequestEngine MovieRequestEngine { get; }
|
||||||
private ITvRequestEngine TvRequestEngine { get; }
|
private ITvRequestEngine TvRequestEngine { get; }
|
||||||
|
private IVoteEngine VoteEngine { get; }
|
||||||
|
private ILogger Log { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets movie requests.
|
/// Gets movie requests.
|
||||||
|
@ -75,7 +81,17 @@ namespace Ombi.Controllers
|
||||||
[HttpPost("movie")]
|
[HttpPost("movie")]
|
||||||
public async Task<RequestEngineResult> RequestMovie([FromBody] MovieRequestViewModel movie)
|
public async Task<RequestEngineResult> RequestMovie([FromBody] MovieRequestViewModel movie)
|
||||||
{
|
{
|
||||||
return await MovieRequestEngine.RequestMovie(movie);
|
var result = await MovieRequestEngine.RequestMovie(movie);
|
||||||
|
if (result.Result)
|
||||||
|
{
|
||||||
|
var voteResult = await VoteEngine.UpVote(result.RequestId, RequestType.Movie);
|
||||||
|
if (voteResult.IsError)
|
||||||
|
{
|
||||||
|
Log.LogError("Couldn't automatically add the vote for the movie {0} because {1}", movie.TheMovieDbId, voteResult.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -95,12 +111,24 @@ namespace Ombi.Controllers
|
||||||
/// <param name="requestId">The request identifier.</param>
|
/// <param name="requestId">The request identifier.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpDelete("movie/{requestId:int}")]
|
[HttpDelete("movie/{requestId:int}")]
|
||||||
[PowerUser]
|
[Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")]
|
||||||
public async Task DeleteRequest(int requestId)
|
public async Task DeleteRequest(int requestId)
|
||||||
{
|
{
|
||||||
await MovieRequestEngine.RemoveMovieRequest(requestId);
|
await MovieRequestEngine.RemoveMovieRequest(requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the specified movie request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requestId">The request identifier.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpDelete("movie/all")]
|
||||||
|
[PowerUser]
|
||||||
|
public async Task DeleteAllRequests()
|
||||||
|
{
|
||||||
|
await MovieRequestEngine.RemoveAllMovieRequests();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the specified movie request.
|
/// Updates the specified movie request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -249,7 +277,17 @@ namespace Ombi.Controllers
|
||||||
[HttpPost("tv")]
|
[HttpPost("tv")]
|
||||||
public async Task<RequestEngineResult> RequestTv([FromBody] TvRequestViewModel tv)
|
public async Task<RequestEngineResult> RequestTv([FromBody] TvRequestViewModel tv)
|
||||||
{
|
{
|
||||||
return await TvRequestEngine.RequestTvShow(tv);
|
var result = await TvRequestEngine.RequestTvShow(tv);
|
||||||
|
if (result.Result)
|
||||||
|
{
|
||||||
|
var voteResult = await VoteEngine.UpVote(result.RequestId, RequestType.TvShow);
|
||||||
|
if (voteResult.IsError)
|
||||||
|
{
|
||||||
|
Log.LogError("Couldn't automatically add the vote for the tv {0} because {1}", tv.TvDbId, voteResult.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -269,7 +307,7 @@ namespace Ombi.Controllers
|
||||||
/// <param name="requestId">The request identifier.</param>
|
/// <param name="requestId">The request identifier.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpDelete("tv/{requestId:int}")]
|
[HttpDelete("tv/{requestId:int}")]
|
||||||
[PowerUser]
|
[Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")]
|
||||||
public async Task DeleteTvRequest(int requestId)
|
public async Task DeleteTvRequest(int requestId)
|
||||||
{
|
{
|
||||||
await TvRequestEngine.RemoveTvRequest(requestId);
|
await TvRequestEngine.RemoveTvRequest(requestId);
|
||||||
|
@ -380,7 +418,7 @@ namespace Ombi.Controllers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="requestId">The model.</param>
|
/// <param name="requestId">The model.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[PowerUser]
|
[Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")]
|
||||||
[HttpDelete("tv/child/{requestId:int}")]
|
[HttpDelete("tv/child/{requestId:int}")]
|
||||||
public async Task<bool> DeleteChildRequest(int requestId)
|
public async Task<bool> DeleteChildRequest(int requestId)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,7 +45,9 @@ namespace Ombi
|
||||||
var urlValue = string.Empty;
|
var urlValue = string.Empty;
|
||||||
var instance = StoragePathSingleton.Instance;
|
var instance = StoragePathSingleton.Instance;
|
||||||
instance.StoragePath = storagePath ?? string.Empty;
|
instance.StoragePath = storagePath ?? string.Empty;
|
||||||
using (var ctx = new OmbiContext())
|
// Check if we need to migrate the settings
|
||||||
|
CheckAndMigrate();
|
||||||
|
using (var ctx = new SettingsContext())
|
||||||
{
|
{
|
||||||
var config = ctx.ApplicationConfigurations.ToList();
|
var config = ctx.ApplicationConfigurations.ToList();
|
||||||
var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url);
|
var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url);
|
||||||
|
@ -82,7 +84,7 @@ namespace Ombi
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value))
|
else if (baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value))
|
||||||
{
|
{
|
||||||
dbBaseUrl.Value = baseUrl;
|
dbBaseUrl.Value = baseUrl;
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
|
@ -96,6 +98,139 @@ namespace Ombi
|
||||||
BuildWebHost(args).Run();
|
BuildWebHost(args).Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is to remove the Settings from the Ombi.db to the "new"
|
||||||
|
/// OmbiSettings.db
|
||||||
|
///
|
||||||
|
/// Ombi is hitting a limitation with SQLite where there is a lot of database activity
|
||||||
|
/// and SQLite does not handle concurrency at all, causing db locks.
|
||||||
|
///
|
||||||
|
/// Splitting it all out into it's own DB helps with this.
|
||||||
|
/// </summary>
|
||||||
|
private static void CheckAndMigrate()
|
||||||
|
{
|
||||||
|
var doneGlobal = false;
|
||||||
|
var doneConfig = false;
|
||||||
|
using (var ombi = new OmbiContext())
|
||||||
|
using (var settings = new SettingsContext())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (ombi.Settings.Any())
|
||||||
|
{
|
||||||
|
// OK migrate it!
|
||||||
|
var allSettings = ombi.Settings.ToList();
|
||||||
|
settings.Settings.AddRange(allSettings);
|
||||||
|
doneGlobal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for any application settings
|
||||||
|
|
||||||
|
if (ombi.ApplicationConfigurations.Any())
|
||||||
|
{
|
||||||
|
// OK migrate it!
|
||||||
|
var allSettings = ombi.ApplicationConfigurations.ToList();
|
||||||
|
settings.ApplicationConfigurations.AddRange(allSettings);
|
||||||
|
doneConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.SaveChanges();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now delete the old stuff
|
||||||
|
if (doneGlobal)
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM GlobalSettings");
|
||||||
|
if (doneConfig)
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM ApplicationConfiguration");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now migrate all the external stuff
|
||||||
|
using (var ombi = new OmbiContext())
|
||||||
|
using (var external = new ExternalContext())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ombi.PlexEpisode.Any())
|
||||||
|
{
|
||||||
|
external.PlexEpisode.AddRange(ombi.PlexEpisode.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM PlexEpisode");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ombi.PlexSeasonsContent.Any())
|
||||||
|
{
|
||||||
|
external.PlexSeasonsContent.AddRange(ombi.PlexSeasonsContent.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM PlexSeasonsContent");
|
||||||
|
}
|
||||||
|
if (ombi.PlexServerContent.Any())
|
||||||
|
{
|
||||||
|
external.PlexServerContent.AddRange(ombi.PlexServerContent.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM PlexServerContent");
|
||||||
|
}
|
||||||
|
if (ombi.EmbyEpisode.Any())
|
||||||
|
{
|
||||||
|
external.EmbyEpisode.AddRange(ombi.EmbyEpisode.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM EmbyEpisode");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ombi.EmbyContent.Any())
|
||||||
|
{
|
||||||
|
external.EmbyContent.AddRange(ombi.EmbyContent.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM EmbyContent");
|
||||||
|
}
|
||||||
|
if (ombi.RadarrCache.Any())
|
||||||
|
{
|
||||||
|
external.RadarrCache.AddRange(ombi.RadarrCache.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM RadarrCache");
|
||||||
|
}
|
||||||
|
if (ombi.SonarrCache.Any())
|
||||||
|
{
|
||||||
|
external.SonarrCache.AddRange(ombi.SonarrCache.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM SonarrCache");
|
||||||
|
}
|
||||||
|
if (ombi.LidarrAlbumCache.Any())
|
||||||
|
{
|
||||||
|
external.LidarrAlbumCache.AddRange(ombi.LidarrAlbumCache.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM LidarrAlbumCache");
|
||||||
|
}
|
||||||
|
if (ombi.LidarrArtistCache.Any())
|
||||||
|
{
|
||||||
|
external.LidarrArtistCache.AddRange(ombi.LidarrArtistCache.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM LidarrArtistCache");
|
||||||
|
}
|
||||||
|
if (ombi.SickRageEpisodeCache.Any())
|
||||||
|
{
|
||||||
|
external.SickRageEpisodeCache.AddRange(ombi.SickRageEpisodeCache.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM SickRageEpisodeCache");
|
||||||
|
}
|
||||||
|
if (ombi.SickRageCache.Any())
|
||||||
|
{
|
||||||
|
external.SickRageCache.AddRange(ombi.SickRageCache.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM SickRageCache");
|
||||||
|
}
|
||||||
|
if (ombi.CouchPotatoCache.Any())
|
||||||
|
{
|
||||||
|
external.CouchPotatoCache.AddRange(ombi.CouchPotatoCache.ToList());
|
||||||
|
ombi.Database.ExecuteSqlCommand("DELETE FROM CouchPotatoCache");
|
||||||
|
}
|
||||||
|
|
||||||
|
external.SaveChanges();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static void DeleteSchedulesDb()
|
private static void DeleteSchedulesDb()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -177,7 +177,7 @@ namespace Ombi
|
||||||
|
|
||||||
// Check if it's in the startup args
|
// Check if it's in the startup args
|
||||||
var appConfig = serviceProvider.GetService<IApplicationConfigRepository>();
|
var appConfig = serviceProvider.GetService<IApplicationConfigRepository>();
|
||||||
var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result;
|
var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl);
|
||||||
if (baseUrl != null)
|
if (baseUrl != null)
|
||||||
{
|
{
|
||||||
if (baseUrl.Value.HasValue())
|
if (baseUrl.Value.HasValue())
|
||||||
|
|
4
src/Ombi/cypress/fixtures/login.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"username": "automation",
|
||||||
|
"password": "password"
|
||||||
|
}
|
140
src/Ombi/cypress/integration/vote.feature.spec.js
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/// <reference types="Cypress" />
|
||||||
|
|
||||||
|
describe('Voting Feature', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.login('automation', 'password').then(() => {
|
||||||
|
|
||||||
|
cy.removeAllMovieRequests();
|
||||||
|
|
||||||
|
cy.createUser('basicUser', 'password', [{
|
||||||
|
value: "requestmovie",
|
||||||
|
Enabled: "true",
|
||||||
|
}, {
|
||||||
|
value: "requesttv",
|
||||||
|
Enabled: "true",
|
||||||
|
}, {
|
||||||
|
value: "requestmusic",
|
||||||
|
Enabled: "true",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
cy.createUser('basicUser2', 'password', [{
|
||||||
|
value: "requestmovie",
|
||||||
|
Enabled: "true",
|
||||||
|
}, {
|
||||||
|
value: "requesttv",
|
||||||
|
Enabled: "true",
|
||||||
|
}, {
|
||||||
|
value: "requestmusic",
|
||||||
|
Enabled: "true",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Enable voting
|
||||||
|
cy.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/api/v1/Settings/vote',
|
||||||
|
body: {
|
||||||
|
Enabled: true,
|
||||||
|
MovieVoteMax: 2,
|
||||||
|
MusicVoteMax: 2,
|
||||||
|
TvShowVoteMax: 2,
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ' + window.localStorage.getItem('id_token'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Login as regular user
|
||||||
|
cy.login('basicUser', 'password').then(() => {
|
||||||
|
|
||||||
|
cy.visit('/vote');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Make sure we can load the page
|
||||||
|
///
|
||||||
|
it('Loads votes page', function () {
|
||||||
|
// cy.login('basicUser','password');
|
||||||
|
cy.contains("Vote");
|
||||||
|
});
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Make sure that when we request a movie it automatically get's upvoted
|
||||||
|
///
|
||||||
|
it('Request Movie automatically upvotes when I am the requestor', function () {
|
||||||
|
cy.requestMovie(335983).then(() => {
|
||||||
|
cy.visit('/vote');
|
||||||
|
cy.get('#completedVotes').click();
|
||||||
|
cy.contains('Venom').should('have.attr', 'data-test').then(($id) => {
|
||||||
|
cy.get('#' + $id + 'upvote').should('have.attr', 'disabled');
|
||||||
|
cy.get('#' + $id + 'downvote').should('not.have.attr', 'disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Make sure that when we request a tv show it automatically get's upvoted
|
||||||
|
///
|
||||||
|
it('Request TV automatically upvotes when I am the requestor', function () {
|
||||||
|
cy.requestAllTv(305288).then(() => {
|
||||||
|
cy.visit('/vote');
|
||||||
|
cy.get('#completedVotes').click();
|
||||||
|
cy.contains('Stranger Things').should('have.attr', 'data-test').then(($id) => {
|
||||||
|
cy.get('#' + $id + 'upvote').should('have.attr', 'disabled');
|
||||||
|
cy.get('#' + $id + 'downvote').should('not.have.attr', 'disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Upvotes a movie with a different user, the votes should eq 2
|
||||||
|
/// Meaning it should be approved now
|
||||||
|
///
|
||||||
|
it.only('Upvote Movie to be approved', function () {
|
||||||
|
cy.login('basicUser2', 'password').then(() => {
|
||||||
|
cy.requestMovie(439079).then(() => {
|
||||||
|
cy.login('basicUser', 'password').then(() => {
|
||||||
|
|
||||||
|
cy.visit('/vote');
|
||||||
|
cy.contains('The Nun').should('have.attr', 'data-test').then(($id) => {
|
||||||
|
cy.get('#' + $id + 'upvote').click();
|
||||||
|
cy.verifyNotification('Voted!');
|
||||||
|
|
||||||
|
// Verify it's in the completed panel
|
||||||
|
cy.get('#completedVotes').click(); cy.contains('The Nun').should('have.attr', 'data-test').then(($id) => {
|
||||||
|
cy.get('#' + $id + 'upvote').should('have.attr', 'disabled');
|
||||||
|
cy.get('#' + $id + 'downvote').should('not.have.attr', 'disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.only('Downvote Movie', function () {
|
||||||
|
cy.login('basicUser2', 'password').then(() => {
|
||||||
|
cy.requestMovie(439079).then(() => {
|
||||||
|
cy.login('basicUser', 'password').then(() => {
|
||||||
|
|
||||||
|
cy.visit('/vote');
|
||||||
|
cy.contains('The Nun').should('have.attr', 'data-test').then(($id) => {
|
||||||
|
cy.get('#' + $id + 'downvote').click();
|
||||||
|
cy.verifyNotification('Voted!');
|
||||||
|
|
||||||
|
// Verify it's in the completed panel
|
||||||
|
cy.get('#completedVotes').click(); cy.contains('The Nun').should('have.attr', 'data-test').then(($id) => {
|
||||||
|
cy.get('#' + $id + 'upvote').should('not.have.attr', 'disabled');
|
||||||
|
cy.get('#' + $id + 'downvote').should('have.attr', 'disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
|
@ -1,7 +1,9 @@
|
||||||
|
/// <reference types="Cypress" />
|
||||||
|
|
||||||
describe('Wizard Setup Tests', function() {
|
describe('Wizard Setup Tests', function() {
|
||||||
it('Setup Wizard User', function() {
|
it('Setup Wizard User', function() {
|
||||||
cy.visit('http://localhost:3577/');
|
cy.visit('/');
|
||||||
cy.url().should('include', '/Wizard')
|
cy.url().should('include', 'Wizard')
|
||||||
|
|
||||||
cy.get('[data-test=nextbtn]').click();
|
cy.get('[data-test=nextbtn]').click();
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||||
|
|
||||||
Cypress.Commands.add('login', (username, password) => {
|
Cypress.Commands.add('login', (username, password) => {
|
||||||
|
cy.clearLocalStorage();
|
||||||
cy.request({
|
cy.request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/api/v1/token',
|
url: '/api/v1/token',
|
||||||
|
@ -34,9 +35,12 @@ Cypress.Commands.add('login', (username, password) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
window.localStorage.setItem('id_token', resp.body.access_token)
|
window.localStorage.setItem('id_token', resp.body.access_token);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Cypress.Commands.add('removeLogin', () => {
|
||||||
|
window.localStorage.removeItem('id_token');
|
||||||
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('createUser', (username, password, claims) => {
|
Cypress.Commands.add('createUser', (username, password, claims) => {
|
||||||
cy.request({
|
cy.request({
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
// ***********************************************************
|
// ***********************************************************
|
||||||
|
|
||||||
// Import commands.js using ES2015 syntax:
|
// Import commands.js using ES2015 syntax:
|
||||||
import './commands'
|
import './commands';
|
||||||
|
import './request.commands';
|
||||||
|
|
||||||
// Alternatively you can use CommonJS syntax:
|
// Alternatively you can use CommonJS syntax:
|
||||||
// require('./commands')
|
// require('./commands')
|
||||||
|
|
50
src/Ombi/cypress/support/request.commands.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
Cypress.Commands.add('requestGenericMovie', () => {
|
||||||
|
cy.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/api/v1/request/movie',
|
||||||
|
body: {
|
||||||
|
TheMovieDbId: 299536
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ' + window.localStorage.getItem('id_token'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('requestMovie', (movieId) => {
|
||||||
|
cy.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/api/v1/request/movie',
|
||||||
|
body: {
|
||||||
|
TheMovieDbId: movieId
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ' + window.localStorage.getItem('id_token'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('requestAllTv', (tvId) => {
|
||||||
|
cy.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/api/v1/request/tv',
|
||||||
|
body: {
|
||||||
|
TvDbId: tvId,
|
||||||
|
RequestAll: true
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ' + window.localStorage.getItem('id_token'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('removeAllMovieRequests', () => {
|
||||||
|
cy.request({
|
||||||
|
method: 'DELETE',
|
||||||
|
url: '/api/v1/request/movie/all',
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ' + window.localStorage.getItem('id_token'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
|
@ -4,6 +4,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"vendor": "gulp vendor",
|
"vendor": "gulp vendor",
|
||||||
|
"main": "gulp main",
|
||||||
"lint": "tslint -p .",
|
"lint": "tslint -p .",
|
||||||
"publish": "gulp publish",
|
"publish": "gulp publish",
|
||||||
"restore": "dotnet restore && yarn install",
|
"restore": "dotnet restore && yarn install",
|
||||||
|
@ -90,7 +91,8 @@
|
||||||
"zone.js": "^0.8.26"
|
"zone.js": "^0.8.26"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/tapable": "1.0.0"
|
"@types/tapable": "1.0.0",
|
||||||
|
"cypress/**/@types/sinon": "4.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cypress": "^3.1.0"
|
"cypress": "^3.1.0"
|
||||||
|
|
|
@ -28,9 +28,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"types": [
|
|
||||||
"cypress"
|
|
||||||
],
|
|
||||||
"include": [
|
"include": [
|
||||||
"ClientApp/**/*",
|
"ClientApp/**/*",
|
||||||
"typings/**/*",
|
"typings/**/*",
|
||||||
|
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 722 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 695 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"Login": {
|
"Login": {
|
||||||
"SignInButton": "Connexion",
|
"SignInButton": "Se connecter",
|
||||||
"UsernamePlaceholder": "Nom d’utilisateur",
|
"UsernamePlaceholder": "Nom d’utilisateur",
|
||||||
"PasswordPlaceholder": "Mot de passe",
|
"PasswordPlaceholder": "Mot de passe",
|
||||||
"RememberMe": "Se souvenir de moi",
|
"RememberMe": "Se souvenir de moi",
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
"Common": {
|
"Common": {
|
||||||
"ContinueButton": "Continuer",
|
"ContinueButton": "Continuer",
|
||||||
"Available": "Disponible",
|
"Available": "Disponible",
|
||||||
"PartiallyAvailable": "Partially Available",
|
"PartiallyAvailable": "Partiellement disponible",
|
||||||
"Monitored": "Monitored",
|
"Monitored": "Suivi",
|
||||||
"NotAvailable": "Non disponible",
|
"NotAvailable": "Non disponible",
|
||||||
"ProcessingRequest": "En cours de traitement",
|
"ProcessingRequest": "En cours de traitement",
|
||||||
"PendingApproval": "En attente d'approbation",
|
"PendingApproval": "En attente d'approbation",
|
||||||
|
@ -37,10 +37,10 @@
|
||||||
"OnlineParagraph": "Le serveur média est actuellement en ligne",
|
"OnlineParagraph": "Le serveur média est actuellement en ligne",
|
||||||
"PartiallyOnlineHeading": "Partiellement en ligne",
|
"PartiallyOnlineHeading": "Partiellement en ligne",
|
||||||
"PartiallyOnlineParagraph": "Le serveur média est partiellement en ligne.",
|
"PartiallyOnlineParagraph": "Le serveur média est partiellement en ligne.",
|
||||||
"MultipleServersUnavailable": "Il y a {{serversUnavailable}} serveurs hors ligne sur {{totalServers}}.",
|
"MultipleServersUnavailable": "Il y a {{serversUnavailable}} serveurs hors-ligne sur {{totalServers}}.",
|
||||||
"SingleServerUnavailable": "Il y a {{serversUnavailable}} serveur hors ligne sur {{totalServers}}.",
|
"SingleServerUnavailable": "Il y a {{serversUnavailable}} serveur hors-ligne sur {{totalServers}}.",
|
||||||
"OfflineHeading": "Actuellement hors ligne",
|
"OfflineHeading": "Actuellement hors-ligne",
|
||||||
"OfflineParagraph": "Le serveur média est actuellement hors ligne.",
|
"OfflineParagraph": "Le serveur média est actuellement hors-ligne.",
|
||||||
"CheckPageForUpdates": "Consultez cette page pour voir les mises à jour du site."
|
"CheckPageForUpdates": "Consultez cette page pour voir les mises à jour du site."
|
||||||
},
|
},
|
||||||
"NavigationBar": {
|
"NavigationBar": {
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
"Paragraph": "Vous voulez regarder quelque chose qui n'est pas disponible actuellement ? Pas de problème, recherchez-le ci-dessous et demandez-le !",
|
"Paragraph": "Vous voulez regarder quelque chose qui n'est pas disponible actuellement ? Pas de problème, recherchez-le ci-dessous et demandez-le !",
|
||||||
"MoviesTab": "Films",
|
"MoviesTab": "Films",
|
||||||
"TvTab": "TV",
|
"TvTab": "TV",
|
||||||
"MusicTab": "Music",
|
"MusicTab": "Musique",
|
||||||
"Suggestions": "Suggestions",
|
"Suggestions": "Suggestions",
|
||||||
"NoResults": "Désolé, nous n'avons trouvé aucun résultat !",
|
"NoResults": "Désolé, nous n'avons trouvé aucun résultat !",
|
||||||
"DigitalDate": "Sortie numérique: {{date}}",
|
"DigitalDate": "Sortie numérique: {{date}}",
|
||||||
|
@ -103,13 +103,13 @@
|
||||||
"Paragraph": "Vous pouvez voir ci-dessous vos demandes et celles des autres, ainsi que leur statut de téléchargement et d'approbation.",
|
"Paragraph": "Vous pouvez voir ci-dessous vos demandes et celles des autres, ainsi que leur statut de téléchargement et d'approbation.",
|
||||||
"MoviesTab": "Films",
|
"MoviesTab": "Films",
|
||||||
"TvTab": "Émissions",
|
"TvTab": "Émissions",
|
||||||
"MusicTab": "Music",
|
"MusicTab": "Musique",
|
||||||
"RequestedBy": "Demandé par :",
|
"RequestedBy": "Demandé par :",
|
||||||
"Status": "Statut :",
|
"Status": "Statut :",
|
||||||
"RequestStatus": "Statut de la demande :",
|
"RequestStatus": "Statut de la demande :",
|
||||||
"Denied": " Refusé :",
|
"Denied": " Refusé :",
|
||||||
"TheatricalRelease": "Sortie en salle: {{date}}",
|
"TheatricalRelease": "Sortie en salle: {{date}}",
|
||||||
"ReleaseDate": "Released: {{date}}",
|
"ReleaseDate": "Sortie : {{date}}",
|
||||||
"TheatricalReleaseSort": "Sortie en salle",
|
"TheatricalReleaseSort": "Sortie en salle",
|
||||||
"DigitalRelease": "Sortie numérique: {{date}}",
|
"DigitalRelease": "Sortie numérique: {{date}}",
|
||||||
"RequestDate": "Date de la demande :",
|
"RequestDate": "Date de la demande :",
|
||||||
|
@ -136,11 +136,11 @@
|
||||||
"SortStatusAsc": "Statut ▲",
|
"SortStatusAsc": "Statut ▲",
|
||||||
"SortStatusDesc": "Statut ▼",
|
"SortStatusDesc": "Statut ▼",
|
||||||
"Remaining": {
|
"Remaining": {
|
||||||
"Quota": "{{remaining}}/{{total}} requests remaining",
|
"Quota": "{{remaining}}/{{total}} demande(s) restante(s)",
|
||||||
"NextDays": "Another request will be added in {{time}} days",
|
"NextDays": "Une autre demande sera ajoutée dans {{time}} jours",
|
||||||
"NextHours": "Another request will be added in {{time}} hours",
|
"NextHours": "Une autre demande sera ajoutée dans {{time}} heures",
|
||||||
"NextMinutes": "Another request will be added in {{time}} minutes",
|
"NextMinutes": "Une autre demande sera ajoutée dans {{time}} minutes",
|
||||||
"NextMinute": "Another request will be added in {{time}} minute"
|
"NextMinute": "Une autre demande sera ajoutée dans {{time}} minute"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Issues": {
|
"Issues": {
|
||||||
|
@ -170,15 +170,15 @@
|
||||||
"PendingApproval": "En attente de validation"
|
"PendingApproval": "En attente de validation"
|
||||||
},
|
},
|
||||||
"UserManagment": {
|
"UserManagment": {
|
||||||
"TvRemaining": "TV: {{remaining}}/{{total}} remaining",
|
"TvRemaining": "TV : {{remaining}}/{{total}} restant(s)",
|
||||||
"MovieRemaining": "Movies: {{remaining}}/{{total}} remaining",
|
"MovieRemaining": "Films : {{remaining}}/{{total}} restant(s)",
|
||||||
"MusicRemaining": "Music: {{remaining}}/{{total}} remaining",
|
"MusicRemaining": "Musique : {{remaining}}/{{total}} restant(s)",
|
||||||
"TvDue": "TV: {{date}}",
|
"TvDue": "TV : {{date}}",
|
||||||
"MovieDue": "Movie: {{date}}",
|
"MovieDue": "Film : {{date}}",
|
||||||
"MusicDue": "Music: {{date}}"
|
"MusicDue": "Musique : {{date}}"
|
||||||
},
|
},
|
||||||
"Votes": {
|
"Votes": {
|
||||||
"CompletedVotesTab": "Voted",
|
"CompletedVotesTab": "Voté",
|
||||||
"VotesTab": "Votes Needed"
|
"VotesTab": "Votes nécessaires"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -210,13 +210,9 @@
|
||||||
"@types/chai" "*"
|
"@types/chai" "*"
|
||||||
"@types/sinon" "*"
|
"@types/sinon" "*"
|
||||||
|
|
||||||
"@types/sinon@*":
|
"@types/sinon@*", "@types/sinon@4.0.0", "@types/sinon@4.3.3":
|
||||||
version "5.0.4"
|
version "4.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.4.tgz#a765b390b373cf01a3b19b0c97f9eb4bb2a168b1"
|
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.3.3.tgz#97cbbfddc3282b5fd40c7abf80b99db426fd4237"
|
||||||
|
|
||||||
"@types/sinon@4.0.0":
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.0.0.tgz#9a93ffa4ee1329e85166278a5ed99f81dc4c8362"
|
|
||||||
|
|
||||||
"@types/sizzle@*":
|
"@types/sizzle@*":
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
|
|