From 8b9c37562846a2e78a492bd17349f617892798ec Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Wed, 4 Apr 2018 13:48:40 +0100 Subject: [PATCH 001/325] Made a start on the VoteEngine !wip --- src/Ombi.Core/Engine/VoteEngine.cs | 96 ++++++++++++++++++++++++++ src/Ombi.Store/Context/IOmbiContext.cs | 1 + src/Ombi.Store/Context/OmbiContext.cs | 1 + src/Ombi.Store/Entities/Votes.cs | 25 +++++++ src/Ombi/Startup.cs | 2 + 5 files changed, 125 insertions(+) create mode 100644 src/Ombi.Core/Engine/VoteEngine.cs create mode 100644 src/Ombi.Store/Entities/Votes.cs diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs new file mode 100644 index 000000000..5c132075e --- /dev/null +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Rule.Interfaces; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Core.Engine +{ + public class VoteEngine : BaseEngine + { + public VoteEngine(IRepository votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r) : base(user, um, r) + { + _voteRepository = votes; + } + + private readonly IRepository _voteRepository; + + public async Task GetVotesForMovie(int requestId) + { + return await _voteRepository.GetAll().FirstOrDefaultAsync(x => x.RequestType == RequestType.Movie && x.RequestId == requestId); + } + public IQueryable GetVotesForMovie(IEnumerable requestIds) + { + return _voteRepository.GetAll().Where(x => x.RequestType == RequestType.Movie && requestIds.Contains(x.RequestId)); + } + + public async Task GetVotesForTv(int requestId) + { + return await _voteRepository.GetAll().FirstOrDefaultAsync(x => x.RequestType == RequestType.TvShow && x.RequestId == requestId); + } + + public IQueryable GetVotesForTv(IEnumerable requestIds) + { + return _voteRepository.GetAll().Where(x => x.RequestType == RequestType.TvShow && requestIds.Contains(x.RequestId)); + } + + public async Task UpvoteMovie(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.Movie, + UserId = user.Id, + VoteType = VoteType.Upvote + }); + } + + public async Task DownvoteMovie(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.Movie, + UserId = user.Id, + VoteType = VoteType.Downvote + }); + } + + public async Task UpvoteTv(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.TvShow, + UserId = user.Id, + VoteType = VoteType.Upvote + }); + } + + public async Task DownvoteTv(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.TvShow, + UserId = user.Id, + VoteType = VoteType.Downvote + }); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/IOmbiContext.cs b/src/Ombi.Store/Context/IOmbiContext.cs index 55d7db563..03e528412 100644 --- a/src/Ombi.Store/Context/IOmbiContext.cs +++ b/src/Ombi.Store/Context/IOmbiContext.cs @@ -25,6 +25,7 @@ namespace Ombi.Store.Context DbSet Set() where TEntity : class; DbSet NotificationTemplates { get; set; } DbSet ApplicationConfigurations { get; set; } + DbSet Votes { get; set; } void Seed(); DbSet Audit { get; set; } DbSet MovieRequests { get; set; } diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index e4c9be516..6a408144f 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -39,6 +39,7 @@ namespace Ombi.Store.Context public DbSet IssueComments { get; set; } public DbSet RequestLogs { get; set; } public DbSet RecentlyAddedLogs { get; set; } + public DbSet Votes { get; set; } public DbSet Audit { get; set; } diff --git a/src/Ombi.Store/Entities/Votes.cs b/src/Ombi.Store/Entities/Votes.cs new file mode 100644 index 000000000..61e5651da --- /dev/null +++ b/src/Ombi.Store/Entities/Votes.cs @@ -0,0 +1,25 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + [Table("Votes")] + public class Votes : Entity + { + public int RequestId { get; set; } + public VoteType VoteType { get; set; } + public RequestType RequestType { get; set; } + public string UserId { get; set; } + public DateTime Date { get; set; } + public bool Deleted { get; set; } + + [ForeignKey(nameof(UserId))] + public OmbiUser User { get; set; } + } + + public enum VoteType + { + Upvote = 0, + Downvote = 1 + } +} \ No newline at end of file diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 1d7d67550..a3cb7f4be 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -169,6 +169,8 @@ namespace Ombi { // Generate a API Key settings.ApiKey = Guid.NewGuid().ToString("N"); + var userManager = app.ApplicationServices.GetService(); + userManager.CreateAsync(new OmbiUser {UserName = "API User", UserType = UserType.LocalUser}).Wait(); ombiService.SaveSettings(settings); } if (settings.BaseUrl.HasValue()) From 3120aae34b05b770aa10e271f74e8600801bb8a4 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 21 Sep 2018 22:07:29 +0100 Subject: [PATCH 002/325] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d0faf5b4..d0d86a692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## (unreleased) +## v3.0.3776 (2018-09-21) ### **New Features** From 938547fd75ca79d8f9c3ab0d09f7f3fc1ca2fd7b Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 22 Sep 2018 22:53:32 +0100 Subject: [PATCH 003/325] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4485d3d2b..5bb60935c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v3.0.3776 (2018-09-21) +## v3.0.3786 (2018-09-22) ### **Fixes** From 7fe01206c9297f91438dd5edcadd2e2d41627809 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 23 Sep 2018 22:02:34 +0100 Subject: [PATCH 004/325] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5bf0fb75..cb87ae237 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v3.0.3786 (2018-09-22) +## v3.0.3795 (2018-09-23) ### **Fixes** From 5b6283f6b834048415a330866979bf1143a689da Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 27 Sep 2018 13:18:19 +0100 Subject: [PATCH 005/325] Revert "Feature/purge issues" --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 - src/Ombi.Schedule.Tests/IssuesPurgeTests.cs | 85 ------------------- .../Jobs/Lidarr/LidarrAvailabilityChecker.cs | 2 +- src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs | 9 -- src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs | 63 -------------- .../Settings/Models/IssueSettings.cs | 3 - .../Settings/Models/JobSettings.cs | 1 - .../Settings/Models/JobSettingsHelper.cs | 5 -- src/Ombi.Store/Entities/Requests/Issues.cs | 1 - .../ClientApp/app/interfaces/ISettings.ts | 3 - .../music/musicrequests.component.html | 2 +- .../app/settings/issues/issues.component.html | 14 --- .../app/settings/issues/issues.component.ts | 6 +- .../app/settings/jobs/jobs.component.html | 9 +- .../app/settings/jobs/jobs.component.ts | 1 - .../usermanagement-user.component.html | 12 +-- src/Ombi/Controllers/SettingsController.cs | 3 +- 17 files changed, 12 insertions(+), 208 deletions(-) delete mode 100644 src/Ombi.Schedule.Tests/IssuesPurgeTests.cs delete mode 100644 src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs delete mode 100644 src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 3af06b476..334b94675 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -191,7 +191,6 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); } } } diff --git a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs deleted file mode 100644 index 932022cd8..000000000 --- a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Moq; -using NUnit.Framework; -using Ombi.Core.Settings; -using Ombi.Schedule.Jobs.Ombi; -using Ombi.Settings.Settings.Models; -using Ombi.Store.Entities.Requests; -using Ombi.Store.Repository; -using System.Threading.Tasks; - -namespace Ombi.Schedule.Tests -{ - [TestFixture] - public class IssuesPurgeTests - { - - [SetUp] - public void Setup() - { - Repo = new Mock>(); - Settings = new Mock>(); - Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings()); - Job = new IssuesPurge(Repo.Object, Settings.Object); - } - - public Mock> Repo { get; set; } - public Mock> Settings { get; set; } - public IssuesPurge Job { get; set; } - - [Test] - public async Task DoesNotRun_WhenDisabled() - { - await Job.Start(); - Repo.Verify(x => x.GetAll(),Times.Never); - } - - [Test] - public async Task Deletes_Correct_Issue() - { - var issues = new List() - { - new Issues - { - Status = IssueStatus.Resolved, - ResovledDate = DateTime.Now.AddDays(-5).AddHours(-1) - } - }; - - Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); - Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); - await Job.Start(); - - Assert.That(issues.First().Status, Is.EqualTo(IssueStatus.Deleted)); - Repo.Verify(x => x.SaveChangesAsync(), Times.Once); - } - - [Test] - public async Task DoesNot_Delete_AnyIssues() - { - var issues = new List() - { - new Issues - { - Status = IssueStatus.Resolved, - ResovledDate = DateTime.Now.AddDays(-2) - }, - new Issues - { - Status = IssueStatus.Resolved, - ResovledDate = DateTime.Now.AddDays(-6) - } - }; - - Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); - Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); - await Job.Start(); - - Assert.That(issues[0].Status, Is.Not.EqualTo(IssueStatus.Deleted)); - Assert.That(issues[1].Status, Is.EqualTo(IssueStatus.Deleted)); - Repo.Verify(x => x.SaveChangesAsync(), Times.Once); - } - } -} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs index 9db24784d..d5ba14a6d 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -43,7 +43,7 @@ namespace Ombi.Schedule.Jobs.Lidarr var cachedAlbum = await _cachedAlbums.FirstOrDefaultAsync(x => x.ForeignAlbumId.Equals(request.ForeignAlbumId)); if (cachedAlbum != null) { - if (cachedAlbum.FullyAvailable) + if (cachedAlbum.Monitored && cachedAlbum.FullyAvailable) { request.Available = true; request.MarkedAsAvailable = DateTime.Now; diff --git a/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs deleted file mode 100644 index fbd1e3aaf..000000000 --- a/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace Ombi.Schedule.Jobs.Ombi -{ - public interface IIssuesPurge : IBaseJob - { - Task Start(); - } -} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs deleted file mode 100644 index 92ca31071..000000000 --- a/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Ombi.Core.Settings; -using Ombi.Settings.Settings.Models; -using Ombi.Store.Entities.Requests; -using Ombi.Store.Repository; - -namespace Ombi.Schedule.Jobs.Ombi -{ - public class IssuesPurge : IIssuesPurge - { - public IssuesPurge(IRepository issuesRepo, ISettingsService issueSettings) - { - _issuesRepository = issuesRepo; - _settings = issueSettings; - _settings.ClearCache(); - } - - private readonly IRepository _issuesRepository; - private readonly ISettingsService _settings; - - public async Task Start() - { - var settings = await _settings.GetSettingsAsync(); - if (!settings.DeleteIssues) - { - return; - } - - var now = DateTime.Now.AddDays(-settings.DaysAfterResolvedToDelete).Date; - var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved); - var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date <= now); - - foreach (var d in toDelete) - { - d.Status = IssueStatus.Deleted; - } - - await _issuesRepository.SaveChangesAsync(); - } - - private bool _disposed; - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - _issuesRepository?.Dispose(); - _settings?.Dispose(); - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - } -} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/IssueSettings.cs b/src/Ombi.Settings/Settings/Models/IssueSettings.cs index d7a35c0d9..e025c82d1 100644 --- a/src/Ombi.Settings/Settings/Models/IssueSettings.cs +++ b/src/Ombi.Settings/Settings/Models/IssueSettings.cs @@ -4,8 +4,5 @@ { public bool Enabled { get; set; } public bool EnableInProgress { get; set; } - - public bool DeleteIssues { get; set; } - public int DaysAfterResolvedToDelete { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index 8b283cdf7..48c721e29 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -14,6 +14,5 @@ public string RefreshMetadata { get; set; } public string Newsletter { get; set; } public string LidarrArtistSync { get; set; } - public string IssuesPurge { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index 4491ca27a..0f8fec5fd 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -57,11 +57,6 @@ namespace Ombi.Settings.Settings.Models return Get(s.LidarrArtistSync, Cron.Hourly(40)); } - public static string IssuePurge(JobSettings s) - { - return Get(s.IssuesPurge, Cron.Daily()); - } - private static string Get(string settings, string defaultCron) { return settings.HasValue() ? settings : defaultCron; diff --git a/src/Ombi.Store/Entities/Requests/Issues.cs b/src/Ombi.Store/Entities/Requests/Issues.cs index 9fbc6a83e..b1021e362 100644 --- a/src/Ombi.Store/Entities/Requests/Issues.cs +++ b/src/Ombi.Store/Entities/Requests/Issues.cs @@ -29,6 +29,5 @@ namespace Ombi.Store.Entities.Requests Pending = 0, InProgress = 1, Resolved = 2, - Deleted = 3, } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 7a889e722..db4db935e 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -144,14 +144,11 @@ export interface IJobSettings { newsletter: string; plexRecentlyAddedSync: string; lidarrArtistSync: string; - issuesPurge: string; } export interface IIssueSettings extends ISettings { enabled: boolean; enableInProgress: boolean; - deleteIssues: boolean; - daysAfterResolvedToDelete: number; } export interface IAuthenticationSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index f6ad4bb2a..c89c2be0a 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -59,7 +59,7 @@

- {{request.title | truncate: 36}} + {{request.title}}

diff --git a/src/Ombi/ClientApp/app/settings/issues/issues.component.html b/src/Ombi/ClientApp/app/settings/issues/issues.component.html index ee780a1a1..e30d84e26 100644 --- a/src/Ombi/ClientApp/app/settings/issues/issues.component.html +++ b/src/Ombi/ClientApp/app/settings/issues/issues.component.html @@ -18,20 +18,6 @@
-
-
- - -
-
- -
-
- - -
-
-
diff --git a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts index 37ead870a..c8a85e8e1 100644 --- a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts +++ b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts @@ -21,10 +21,8 @@ export class IssuesComponent implements OnInit { public ngOnInit() { this.settingsService.getIssueSettings().subscribe(x => { this.form = this.fb.group({ - enabled: [x.enabled], - enableInProgress: [x.enableInProgress], - deleteIssues: [x.deleteIssues], - daysAfterResolvedToDelete: [x.daysAfterResolvedToDelete], + enabled: [x.enabled], + enableInProgress: [x.enableInProgress], }); }); this.getCategories(); diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index 1365710f0..a4dcd6fb3 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -85,19 +85,12 @@
-
+
The Newsletter is required
- -
- - - The Issues Purge is required - -
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index d8ce106ae..756d6ba89 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -35,7 +35,6 @@ export class JobsComponent implements OnInit { newsletter: [x.newsletter, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], lidarrArtistSync: [x.lidarrArtistSync, Validators.required], - issuesPurge: [x.issuesPurge, Validators.required], }); }); } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 6f3ae63ee..0d13b17c3 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -144,7 +144,7 @@
-
+
@@ -162,7 +162,7 @@
-
+
@@ -179,7 +179,7 @@
-
+
-
+
+ +
+
+ +

Vote limits tell Ombi how many votes the request needs before approval.

+

e.g. If the Movie vote limit is 10, it requires 10 Upvotes from 10 different users before it will be approved.

+
+ + + + The limit needs to be greater than or equal to 1 +
+
+ + + The limit needs to be greater than or equal to 1 +
+
+ + + The limit needs to be greater than or equal to 1 +
+ +
+
+ +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/vote/vote.component.ts b/src/Ombi/ClientApp/app/settings/vote/vote.component.ts new file mode 100644 index 000000000..d99239b96 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/vote/vote.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { NotificationService, SettingsService } from "../../services"; + +@Component({ + templateUrl: "./vote.component.html", +}) +export class VoteComponent implements OnInit { + + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private readonly fb: FormBuilder, + private notificationService: NotificationService) { } + + public ngOnInit() { + this.settingsService.getVoteSettings().subscribe(x => { + this.form = this.fb.group({ + enabled: [x.enabled], + movieVoteMax: [x.movieVoteMax, Validators.min(1)], + musicVoteMax: [x.musicVoteMax, Validators.min(1)], + tvShowVoteMax: [x.tvShowVoteMax, Validators.min(1)], + }); + }); + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + + this.settingsService.saveVoteSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Vote settings"); + } else { + this.notificationService.success("There was an error when saving the Vote settings"); + } + }); + } +} diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 9785af553..b523250a6 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -599,12 +599,11 @@ namespace Ombi.Controllers /// - /// Save the Issues settings. + /// Save the Vote settings. /// /// The settings. /// [HttpPost("Issues")] - [AllowAnonymous] public async Task IssueSettings([FromBody]IssueSettings settings) { return await Save(settings); @@ -629,6 +628,35 @@ namespace Ombi.Controllers return issues.Enabled; } + /// + /// Save the Vote settings. + /// + /// The settings. + /// + [HttpPost("vote")] + public async Task VoteSettings([FromBody]VoteSettings settings) + { + return await Save(settings); + } + + /// + /// Gets the Vote Settings. + /// + /// + [HttpGet("vote")] + public async Task VoteSettings() + { + return await Get(); + } + + [AllowAnonymous] + [HttpGet("voteenabled")] + public async Task VoteEnabled() + { + var vote = await Get(); + return vote.Enabled; + } + /// /// Saves the email notification settings. /// diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index ffdd87b53..2d86d4471 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -172,8 +172,6 @@ namespace Ombi { // Generate a API Key settings.ApiKey = Guid.NewGuid().ToString("N"); - var userManager = app.ApplicationServices.GetService(); - userManager.CreateAsync(new OmbiUser {UserName = "API User", UserType = UserType.LocalUser}).Wait(); ombiService.SaveSettings(settings); } diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index cbe2c034e..1fd65e663 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -50,6 +50,7 @@ "Requests": "Requests", "UserManagement": "User Management", "Issues":"Issues", + "Vote":"Vote", "Donate": "Donate!", "DonateLibraryMaintainer": "Donate to Library Maintainer", "DonateTooltip": From 9f696bfc7d3358135d12fdfa903091ccca2dede5 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 3 Oct 2018 15:03:41 +0100 Subject: [PATCH 014/325] Do not show available, approved stuff on the vote page !wip --- src/Ombi.Core/Engine/VoteEngine.cs | 34 +++++++++++++------ .../ClientApp/app/vote/vote.component.html | 4 +-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index ced3b8f53..6f399f45b 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -44,6 +44,10 @@ namespace Ombi.Core.Engine var musicRequestsTask = _musicRequestEngine.GetRequests(); foreach (var r in movieRequests) { + if (r.Available || r.Approved || (r.Denied ?? false)) + { + continue; + } // Make model var votes = GetVotes(r.Id, RequestType.Movie); var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); @@ -63,6 +67,10 @@ namespace Ombi.Core.Engine foreach (var r in await musicRequestsTask) { + if (r.Available || r.Approved || (r.Denied ?? false)) + { + continue; + } // Make model var votes = GetVotes(r.Id, RequestType.Album); var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); @@ -90,6 +98,10 @@ namespace Ombi.Core.Engine var finalsb = new StringBuilder(); foreach (var childRequests in r.ChildRequests) { + if (childRequests.Available || childRequests.Approved || (childRequests.Denied ?? false)) + { + continue; + } foreach (var epInformation in childRequests.SeasonRequests.OrderBy(x => x.SeasonNumber)) { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); @@ -97,18 +109,18 @@ namespace Ombi.Core.Engine finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); finalsb.Append("
"); } + vm.Add(new VoteViewModel + { + Upvotes = upVotes, + Downvotes = downVotes, + RequestId = childRequests.Id, + RequestType = RequestType.TvShow, + Title = r.Title, + Image = r.PosterPath, + Background = r.Background, + Description = finalsb.ToString() + }); } - vm.Add(new VoteViewModel - { - Upvotes = upVotes, - Downvotes = downVotes, - RequestId = r.Id, - RequestType = RequestType.TvShow, - Title = r.Title, - Image = r.PosterPath, - Background = r.Background, - Description = finalsb.ToString() - }); } return vm; diff --git a/src/Ombi/ClientApp/app/vote/vote.component.html b/src/Ombi/ClientApp/app/vote/vote.component.html index eaeb3ca5e..4f322352d 100644 --- a/src/Ombi/ClientApp/app/vote/vote.component.html +++ b/src/Ombi/ClientApp/app/vote/vote.component.html @@ -14,8 +14,8 @@ - - + + x.VoteType == VoteType.Upvote).CountAsync(); var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); + var myVote = await votes.FirstOrDefaultAsync(x => x.UserId == user.Id && !x.Deleted); vm.Add(new VoteViewModel { Upvotes = upVotes, @@ -84,24 +90,27 @@ namespace Ombi.Core.Engine Title = r.Title, Image = r.Cover, Background = r.Cover, - Description = r.ArtistName + Description = r.ArtistName, + AlreadyVoted = myVote != null, + MyVote = myVote?.VoteType ?? VoteType.Downvote }); } foreach (var r in await tvRequestsTask) { - // Make model - var votes = GetVotes(r.Id, RequestType.TvShow); - var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); - var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); - var finalsb = new StringBuilder(); foreach (var childRequests in r.ChildRequests) { + var finalsb = new StringBuilder(); if (childRequests.Available || childRequests.Approved || (childRequests.Denied ?? false)) { continue; } + var votes = GetVotes(childRequests.Id, RequestType.TvShow); + // Make model + var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); + var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); + var myVote = await votes.FirstOrDefaultAsync(x => x.UserId == user.Id && !x.Deleted); foreach (var epInformation in childRequests.SeasonRequests.OrderBy(x => x.SeasonNumber)) { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); @@ -118,7 +127,9 @@ namespace Ombi.Core.Engine Title = r.Title, Image = r.PosterPath, Background = r.Background, - Description = finalsb.ToString() + Description = finalsb.ToString(), + AlreadyVoted = myVote != null, + MyVote = myVote?.VoteType ?? VoteType.Downvote }); } } @@ -209,7 +220,7 @@ namespace Ombi.Core.Engine { var user = await GetUser(); var currentVote = await GetVoteForUser(requestId, user.Id); - if (currentVote != null && currentVote.VoteType == VoteType.Upvote) + if (currentVote != null && currentVote.VoteType == VoteType.Downvote) { return new VoteEngineResult { ErrorMessage = "You have already voted!" }; } diff --git a/src/Ombi.Core/Models/UI/VoteViewModel.cs b/src/Ombi.Core/Models/UI/VoteViewModel.cs index 71d6c95a9..f58db3dbc 100644 --- a/src/Ombi.Core/Models/UI/VoteViewModel.cs +++ b/src/Ombi.Core/Models/UI/VoteViewModel.cs @@ -12,5 +12,7 @@ namespace Ombi.Core.Models.UI public int Downvotes { get; set; } public string Title { get; set; } public string Description { get; set; } + public bool AlreadyVoted { get; set; } + public VoteType MyVote { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/IVote.ts b/src/Ombi/ClientApp/app/interfaces/IVote.ts index fb772fea6..e6aaf9607 100644 --- a/src/Ombi/ClientApp/app/interfaces/IVote.ts +++ b/src/Ombi/ClientApp/app/interfaces/IVote.ts @@ -7,6 +7,8 @@ downvotes: number; title: string; description: string; + alreadyVoted: boolean; + myVote: VoteType; } export interface IVoteEngineResult { @@ -21,3 +23,8 @@ export enum RequestTypes { Movie = 1, Album = 2, } + +export enum VoteType { + Upvote = 0, + Downvote = 1, +} diff --git a/src/Ombi/ClientApp/app/vote/vote.component.html b/src/Ombi/ClientApp/app/vote/vote.component.html index 4f322352d..6d8f8a797 100644 --- a/src/Ombi/ClientApp/app/vote/vote.component.html +++ b/src/Ombi/ClientApp/app/vote/vote.component.html @@ -1,35 +1,92 @@

Vote

-
- - - - - - - - - - - - - - - - - - -
TitleDescription
- - - poster{{vm.title}}
+ + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
TitleDescription
+ + + poster{{vm.title}}
+
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
TitleDescription
+ + + poster{{vm.title}}
+
+ +
+ - poster - \ No newline at end of file + poster + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/vote/vote.component.ts b/src/Ombi/ClientApp/app/vote/vote.component.ts index 908c1759a..ffab837cd 100644 --- a/src/Ombi/ClientApp/app/vote/vote.component.ts +++ b/src/Ombi/ClientApp/app/vote/vote.component.ts @@ -3,7 +3,7 @@ import { Component, OnInit, ViewChild } from "@angular/core"; import { OverlayPanel } from "primeng/primeng"; import { NotificationService, VoteService } from "../services"; -import { IVoteEngineResult, IVoteViewModel, RequestTypes } from "../interfaces"; +import { IVoteEngineResult, IVoteViewModel, RequestTypes, VoteType } from "../interfaces"; @Component({ templateUrl: "vote.component.html", @@ -11,7 +11,12 @@ import { IVoteEngineResult, IVoteViewModel, RequestTypes } from "../interfaces"; }) export class VoteComponent implements OnInit { + public showCurrent: boolean = true; + public showCompleted: boolean; public viewModel: IVoteViewModel[]; + public currentVotes: IVoteViewModel[]; + public completedVotes: IVoteViewModel[]; + public VoteType = VoteType; public panelImage: string; @ViewChild("op") public overlayPanel: OverlayPanel; @@ -19,8 +24,19 @@ export class VoteComponent implements OnInit { public async ngOnInit() { this.viewModel = await this.voteService.getModel(); + this.filterLists(); } + public selectCurrentTab() { + this.showCurrent = true; + this.showCompleted = false; + } + + public selectCompletedVotesTab() { + this.showCurrent = false; + this.showCompleted = true; + } + public toggle(event: any, image: string) { this.panelImage = image; this.overlayPanel.toggle(event); @@ -44,6 +60,9 @@ export class VoteComponent implements OnInit { this.notificationSerivce.error(result.errorMessage); } else { this.notificationSerivce.success("Voted!"); + vm.alreadyVoted = true; + vm.myVote = VoteType.Upvote; + this.filterLists(); } } @@ -64,7 +83,19 @@ export class VoteComponent implements OnInit { if(result.isError) { this.notificationSerivce.error(result.errorMessage); } else { - this.notificationSerivce.success("Voted!"); + this.notificationSerivce.success("Voted!"); + vm.alreadyVoted = true; + vm.myVote = VoteType.Downvote; + this.filterLists(); } } + + private filterLists() { + this.completedVotes = this.viewModel.filter(vm => { + return vm.alreadyVoted; + }); + this.currentVotes = this.viewModel.filter(vm => { + return !vm.alreadyVoted; + }); + } } diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 1fd65e663..93f6c39f0 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -194,5 +194,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } From a7cd9c565d1cf365a0f58c6c47d883954f8c949e Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:53:56 +0100 Subject: [PATCH 016/325] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 17c671217..0229b3603 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -48,6 +48,7 @@ "Requests": "Anmodninger", "UserManagement": "Brugeradministration", "Issues": "Problemer", + "Vote": "Vote", "Donate": "Donér!", "DonateLibraryMaintainer": "Donér til vedligeholder af bibliotek", "DonateTooltip": "Sådan overbeviser jeg min kone om, at jeg skal bruge min fritid på at udvikle Ombi :)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 10e6145ff074f7e070143195a2ca3cd74755a374 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:53:57 +0100 Subject: [PATCH 017/325] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 60d54fe8c..18a1d319d 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -48,6 +48,7 @@ "Requests": "Verzoeklijst", "UserManagement": "Gebruikersbeheer", "Issues": "Problemen", + "Vote": "Vote", "Donate": "Doneer!", "DonateLibraryMaintainer": "Doneren aan bibliotheek beheerder", "DonateTooltip": "Zo heb ik mijn vrouw overtuigd dat ik Ombi mag ontwikkelen ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From ad78a3947170b9f51155ae15252903338fce8905 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:53:58 +0100 Subject: [PATCH 018/325] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 0834653f8..c20dffdb0 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -48,6 +48,7 @@ "Requests": "Demandes", "UserManagement": "Gestion des utilisateurs", "Issues": "Problèmes", + "Vote": "Vote", "Donate": "Faire un don !", "DonateLibraryMaintainer": "Faire un don au mainteneur de la bibliothèque", "DonateTooltip": "C’est pour convaincre ma femme de me laisser passer mon temps libre à développer Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 7218aeff775271d426fa1d37b54e5f43a0f38701 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:00 +0100 Subject: [PATCH 019/325] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 2da1aab4e..d5b9e62be 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -48,6 +48,7 @@ "Requests": "Anfragen", "UserManagement": "Benutzerverwaltung", "Issues": "Probleme", + "Vote": "Vote", "Donate": "Spenden!", "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 1b097b9147ec8a53d502dc4253987071c17233aa Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:02 +0100 Subject: [PATCH 020/325] New translations en.json (Italian) --- src/Ombi/wwwroot/translations/it.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 25f706303..0ade93919 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -48,6 +48,7 @@ "Requests": "Richieste", "UserManagement": "Gestione degli utenti", "Issues": "Problemi", + "Vote": "Vote", "Donate": "Fai una donazione!", "DonateLibraryMaintainer": "Dona al manutentore della libreria", "DonateTooltip": "Questo è come convinco mia moglie a farmi spendere il mio tempo libero nello sviluppo di Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 35a28ef62ea843e7037050d4e268897fc5aafbf9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:03 +0100 Subject: [PATCH 021/325] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 87df0181f..80cd9e31a 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -48,6 +48,7 @@ "Requests": "Forespørsler", "UserManagement": "Brukeradministrasjon", "Issues": "Mangler", + "Vote": "Vote", "Donate": "Doner!", "DonateLibraryMaintainer": "Doner til vedlikeholderen av biblioteket", "DonateTooltip": "Dette er hvordan jeg overbevise min kone til å la meg bruke min fritid til å utvikle Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 7f4c251104dce16615ce43c3cf57a5f43cbc968a Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:05 +0100 Subject: [PATCH 022/325] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 8e180e5bb..3aba4da41 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -48,6 +48,7 @@ "Requests": "Zgłoszenia", "UserManagement": "Zarządzanie użytkownikami", "Issues": "Problemy", + "Vote": "Vote", "Donate": "Wesprzyj!", "DonateLibraryMaintainer": "Wesprzyj właściciela biblioteki", "DonateTooltip": "W ten sposób przekonuję moją żonę by spędzać mój wolny czas rozwijając Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 9ec631ca14aaf629e70a525e217b1ceca185a5ee Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:07 +0100 Subject: [PATCH 023/325] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index e547d0066..eaf45cac9 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -48,6 +48,7 @@ "Requests": "Solicitações", "UserManagement": "Gerenciador de Usuário", "Issues": "Problemas", + "Vote": "Vote", "Donate": "Fazer uma doação!", "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", "DonateTooltip": "É assim que eu convenço a minha mulher a deixar-me passar o meu tempo livre desenvolvendo Ombi;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 6f220940a93c66a61006d4fd9f9490995428ecd7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:08 +0100 Subject: [PATCH 024/325] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index a49ea5140..dc7637e79 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -48,6 +48,7 @@ "Requests": "Solicitudes", "UserManagement": "Gestión de usuarios", "Issues": "Incidencias", + "Vote": "Vote", "Donate": "¡Donar!", "DonateLibraryMaintainer": "Donate to Library Maintainer", "DonateTooltip": "Para que mi esposa me deje desarrollar Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From bd4f423220d0ae24eda95c74af92165cf7088442 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:09 +0100 Subject: [PATCH 025/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 26a85fe10..8d2e8374a 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -48,6 +48,7 @@ "Requests": "Förfrågningar", "UserManagement": "Användarhantering", "Issues": "Problem", + "Vote": "Vote", "Donate": "Donera!", "DonateLibraryMaintainer": "Donera till bibliotekets utvecklare", "DonateTooltip": "Det är så här jag övertygar min fru att jag vill spendera min fritid att utveckla Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 9d8caf43584c4e896f65e2d9cbc9dc0072c977a3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 14:31:40 +0100 Subject: [PATCH 026/325] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index d5b9e62be..c3646221d 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -48,7 +48,7 @@ "Requests": "Anfragen", "UserManagement": "Benutzerverwaltung", "Issues": "Probleme", - "Vote": "Vote", + "Vote": "Bewerten", "Donate": "Spenden!", "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", @@ -66,27 +66,27 @@ "Danish": "Dänisch", "Dutch": "Niederländisch", "Norwegian": "Norwegisch", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" + "BrazillianPortuguese": "Portugiesisch (Brasilien)", + "Polish": "Polnisch", + "Swedish": "Schwedisch" }, "OpenMobileApp": "Mobile App", - "RecentlyAdded": "Recently Added" + "RecentlyAdded": "Kürzlich hinzugefügt" }, "Search": { "Title": "Suche", "Paragraph": "Möchtest du etwas sehen, das nicht verfügbar ist? Kein Problem, benutze einfach die Suchbox und fordere es an!", "MoviesTab": "Filme", "TvTab": "Serien", - "MusicTab": "Music", + "MusicTab": "Musik", "Suggestions": "Vorschläge", "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", + "TheatricalRelease": "Kinostart: {{date}}", "ViewOnPlex": "In Plex anschauen", "ViewOnEmby": "In Emby anschauen", "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", - "Similar": "Similar", + "Similar": "Ähnliche", "Movies": { "PopularMovies": "Beliebte Filme", "UpcomingMovies": "Kommende Filme", @@ -116,14 +116,14 @@ "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download und Genehmigungsstatus.", "MoviesTab": "Filme", "TvTab": "Serien", - "MusicTab": "Music", + "MusicTab": "Musik", "RequestedBy": "Angefordert von:", "Status": "Status:", "RequestStatus": "Anfrage Status:", "Denied": " Abgelehnt:", - "TheatricalRelease": "Theatrical Release: {{date}}", + "TheatricalRelease": "Kinostart: {{date}}", "ReleaseDate": "Veröffentlicht: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", + "TheatricalReleaseSort": "Kinostart", "DigitalRelease": "Digital Release: {{date}}", "RequestDate": "Datum der Anfrage:", "QualityOverride": "Qualitäts Überschreiben:", @@ -140,10 +140,10 @@ "GridStatus": "Status", "ReportIssue": "Problem melden", "Filter": "Filter", - "Sort": "Sort", + "Sort": "Sortieren", "SeasonNumberHeading": "Staffel: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", @@ -180,18 +180,18 @@ "FilterHeaderAvailability": "Verfügbarkeit", "FilterHeaderRequestStatus": "Status", "Approved": "Bestätigt", - "PendingApproval": "Pending Approval" + "PendingApproval": "Genehmigung ausstehend" }, "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film: {{date}}", + "MusicDue": "Musik: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Bewertet", + "VotesTab": "Erforderliche Bewertungen" } } \ No newline at end of file From 618ee16d9d139d2a5635be638f910c5da37cc267 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 4 Oct 2018 14:35:05 +0100 Subject: [PATCH 027/325] The settings have now been split out of the main db. Next is the External stuff e.g. Plex/Emby/Sonarr/Radarr stuff --- src/Ombi.Api.Notifications/OneSignalApi.cs | 2 +- src/Ombi.DependencyInjection/IocExtensions.cs | 2 + .../Jobs/Ombi/OmbiAutomaticUpdater.cs | 10 ++- src/Ombi.Store/Context/IDbContext.cs | 22 ++++++ src/Ombi.Store/Context/IOmbiContext.cs | 14 +--- src/Ombi.Store/Context/ISettingsContext.cs | 11 +++ src/Ombi.Store/Context/OmbiContext.cs | 37 +--------- src/Ombi.Store/Context/SettingsContext.cs | 70 +++++++++++++++++++ .../20181004132516_Inital.Designer.cs | 50 +++++++++++++ .../Settings/20181004132516_Inital.cs | 47 +++++++++++++ .../Settings/SettingsContextModelSnapshot.cs | 48 +++++++++++++ .../Repository/ApplicationConfigRepository.cs | 12 ++-- .../IApplicationConfigRepository.cs | 3 +- .../Repository/SettingsJsonRepository.cs | 4 +- src/Ombi/Controllers/ImagesController.cs | 12 ++-- src/Ombi/Program.cs | 51 +++++++++++++- src/Ombi/Startup.cs | 2 +- 17 files changed, 328 insertions(+), 69 deletions(-) create mode 100644 src/Ombi.Store/Context/IDbContext.cs create mode 100644 src/Ombi.Store/Context/ISettingsContext.cs create mode 100644 src/Ombi.Store/Context/SettingsContext.cs create mode 100644 src/Ombi.Store/Migrations/Settings/20181004132516_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/Settings/20181004132516_Inital.cs create mode 100644 src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs diff --git a/src/Ombi.Api.Notifications/OneSignalApi.cs b/src/Ombi.Api.Notifications/OneSignalApi.cs index 8d5fc04a9..ee5c7e44a 100644 --- a/src/Ombi.Api.Notifications/OneSignalApi.cs +++ b/src/Ombi.Api.Notifications/OneSignalApi.cs @@ -26,7 +26,7 @@ namespace Ombi.Api.Notifications { 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 body = new OneSignalNotificationBody diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 3af06b476..53c212ea1 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -128,8 +128,10 @@ namespace Ombi.DependencyInjection public static void RegisterStore(this IServiceCollection services) { services.AddEntityFrameworkSqlite().AddDbContext(); + services.AddEntityFrameworkSqlite().AddDbContext(); services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 + services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs index 72f0ef6f5..5ec8978b6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs @@ -33,7 +33,7 @@ namespace Ombi.Schedule.Jobs.Ombi public class OmbiAutomaticUpdater : IOmbiAutomaticUpdater { public OmbiAutomaticUpdater(ILogger log, IChangeLogProcessor service, - ISettingsService s, IProcessProvider proc, IRepository appConfig) + ISettingsService s, IProcessProvider proc, IApplicationConfigRepository appConfig) { Logger = log; Processor = service; @@ -48,7 +48,7 @@ namespace Ombi.Schedule.Jobs.Ombi private ISettingsService Settings { get; } private readonly IProcessProvider _processProvider; private static PerformContext Ctx { get; set; } - private readonly IRepository _appConfig; + private readonly IApplicationConfigRepository _appConfig; public string[] GetVersion() { @@ -252,9 +252,8 @@ namespace Ombi.Schedule.Jobs.Ombi private string GetArgs(UpdateSettings settings) { - var config = _appConfig.GetAll(); - var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); - var storage = config.FirstOrDefault(x => x.Type == ConfigurationTypes.StoragePath); + var url = _appConfig.Get(ConfigurationTypes.Url); + var storage = _appConfig.Get(ConfigurationTypes.StoragePath); var currentLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); var processName = (settings.ProcessName.HasValue() ? settings.ProcessName : "Ombi"); @@ -345,7 +344,6 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _appConfig?.Dispose(); Settings?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Store/Context/IDbContext.cs b/src/Ombi.Store/Context/IDbContext.cs new file mode 100644 index 000000000..d84aaaa3d --- /dev/null +++ b/src/Ombi.Store/Context/IDbContext.cs @@ -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 Update(TEntity entity) where TEntity : class; + int SaveChanges(); + void Seed(); + Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); + DatabaseFacade Database { get; } + EntityEntry Entry(T entry) where T : class; + EntityEntry Attach(TEntity entity) where TEntity : class; + DbSet Set() where TEntity : class; + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/IOmbiContext.cs b/src/Ombi.Store/Context/IOmbiContext.cs index 2c4d809b4..f21a3f0db 100644 --- a/src/Ombi.Store/Context/IOmbiContext.cs +++ b/src/Ombi.Store/Context/IOmbiContext.cs @@ -9,23 +9,17 @@ using Ombi.Store.Entities.Requests; namespace Ombi.Store.Context { - public interface IOmbiContext : IDisposable + public interface IOmbiContext : IDbContext { - int SaveChanges(); - Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); - DbSet Settings { get; set; } + DbSet PlexServerContent { get; set; } DbSet PlexEpisode { get; set; } + DbSet Settings { get; set; } DbSet RadarrCache { get; set; } DbSet EmbyContent { get; set; } DbSet EmbyEpisode { get; set; } - DatabaseFacade Database { get; } - EntityEntry Entry(T entry) where T : class; - EntityEntry Attach(TEntity entity) where TEntity : class; - DbSet Set() where TEntity : class; DbSet NotificationTemplates { get; set; } DbSet ApplicationConfigurations { get; set; } - void Seed(); DbSet Audit { get; set; } DbSet MovieRequests { get; set; } DbSet AlbumRequests { get; set; } @@ -36,8 +30,6 @@ namespace Ombi.Store.Context DbSet Tokens { get; set; } DbSet SonarrCache { get; set; } DbSet SonarrEpisodeCache { get; set; } - EntityEntry Update(object entity); - EntityEntry Update(TEntity entity) where TEntity : class; DbSet CouchPotatoCache { get; set; } DbSet SickRageCache { get; set; } DbSet LidarrArtistCache { get; set; } diff --git a/src/Ombi.Store/Context/ISettingsContext.cs b/src/Ombi.Store/Context/ISettingsContext.cs new file mode 100644 index 000000000..3c209c68a --- /dev/null +++ b/src/Ombi.Store/Context/ISettingsContext.cs @@ -0,0 +1,11 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities; + +namespace Ombi.Store.Context +{ + public interface ISettingsContext : IDbContext + { + DbSet ApplicationConfigurations { get; set; } + DbSet Settings { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index f34b4c57c..6660ee7d6 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -22,9 +22,10 @@ namespace Ombi.Store.Context } public DbSet NotificationTemplates { get; set; } - public DbSet Settings { get; set; } + public DbSet ApplicationConfigurations { get; set; } public DbSet PlexServerContent { get; set; } public DbSet PlexEpisode { get; set; } + public DbSet Settings { get; set; } public DbSet RadarrCache { get; set; } public DbSet CouchPotatoCache { get; set; } public DbSet EmbyContent { get; set; } @@ -53,7 +54,6 @@ namespace Ombi.Store.Context public DbSet RequestSubscription { get; set; } public DbSet UserNotificationPreferences { get; set; } public DbSet UserQualityProfileses { get; set; } - public DbSet ApplicationConfigurations { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -84,39 +84,6 @@ namespace Ombi.Store.Context 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; Database.ExecuteSqlCommand("VACUUM;"); diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs new file mode 100644 index 000000000..af5c91d20 --- /dev/null +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -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 Settings { get; set; } + public DbSet 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(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Migrations/Settings/20181004132516_Inital.Designer.cs b/src/Ombi.Store/Migrations/Settings/20181004132516_Inital.Designer.cs new file mode 100644 index 000000000..60b9f9adc --- /dev/null +++ b/src/Ombi.Store/Migrations/Settings/20181004132516_Inital.Designer.cs @@ -0,0 +1,50 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/Settings/20181004132516_Inital.cs b/src/Ombi.Store/Migrations/Settings/20181004132516_Inital.cs new file mode 100644 index 000000000..956e0a14a --- /dev/null +++ b/src/Ombi.Store/Migrations/Settings/20181004132516_Inital.cs @@ -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(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Type = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationConfiguration", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "GlobalSettings", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Content = table.Column(nullable: true), + SettingsName = table.Column(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"); + } + } +} diff --git a/src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs b/src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs new file mode 100644 index 000000000..2f072d3dd --- /dev/null +++ b/src/Ombi.Store/Migrations/Settings/SettingsContextModelSnapshot.cs @@ -0,0 +1,48 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Repository/ApplicationConfigRepository.cs b/src/Ombi.Store/Repository/ApplicationConfigRepository.cs index 3b4476454..31ec3313c 100644 --- a/src/Ombi.Store/Repository/ApplicationConfigRepository.cs +++ b/src/Ombi.Store/Repository/ApplicationConfigRepository.cs @@ -8,16 +8,20 @@ namespace Ombi.Store.Repository { public class ApplicationConfigRepository : IApplicationConfigRepository { - public ApplicationConfigRepository(IOmbiContext ctx) + public ApplicationConfigRepository(ISettingsContext ctx) { Ctx = ctx; } - private IOmbiContext Ctx { get; } + private ISettingsContext Ctx { get; } - public async Task Get(ConfigurationTypes type) + public Task 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); } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IApplicationConfigRepository.cs b/src/Ombi.Store/Repository/IApplicationConfigRepository.cs index 9e35bde7e..6aa76e357 100644 --- a/src/Ombi.Store/Repository/IApplicationConfigRepository.cs +++ b/src/Ombi.Store/Repository/IApplicationConfigRepository.cs @@ -5,6 +5,7 @@ namespace Ombi.Store.Repository { public interface IApplicationConfigRepository { - Task Get(ConfigurationTypes type); + Task GetAsync(ConfigurationTypes type); + ApplicationConfiguration Get(ConfigurationTypes type); } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/SettingsJsonRepository.cs b/src/Ombi.Store/Repository/SettingsJsonRepository.cs index 248413ccc..66cf57b18 100644 --- a/src/Ombi.Store/Repository/SettingsJsonRepository.cs +++ b/src/Ombi.Store/Repository/SettingsJsonRepository.cs @@ -12,13 +12,13 @@ namespace Ombi.Store.Repository { public class SettingsJsonRepository : ISettingsRepository { - public SettingsJsonRepository(IOmbiContext ctx, ICacheService mem) + public SettingsJsonRepository(ISettingsContext ctx, ICacheService mem) { Db = ctx; _cache = mem; } - private IOmbiContext Db { get; } + private ISettingsContext Db { get; } private readonly ICacheService _cache; public GlobalSettings Insert(GlobalSettings entity) diff --git a/src/Ombi/Controllers/ImagesController.cs b/src/Ombi/Controllers/ImagesController.cs index 6c05cdd3a..acbdfb9bc 100644 --- a/src/Ombi/Controllers/ImagesController.cs +++ b/src/Ombi/Controllers/ImagesController.cs @@ -39,7 +39,7 @@ namespace Ombi.Controllers { 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); if (images == null) @@ -64,7 +64,7 @@ namespace Ombi.Controllers [HttpGet("poster/movie/{movieDbId}")] public async Task 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); @@ -98,7 +98,7 @@ namespace Ombi.Controllers { 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); @@ -128,7 +128,7 @@ namespace Ombi.Controllers [HttpGet("background/movie/{movieDbId}")] public async Task 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); @@ -157,7 +157,7 @@ namespace Ombi.Controllers { 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); @@ -189,7 +189,7 @@ namespace Ombi.Controllers var movieUrl = 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) { diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 7e9fa6f78..c0382f8de 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -45,7 +45,9 @@ namespace Ombi var urlValue = string.Empty; var instance = StoragePathSingleton.Instance; 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 url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); @@ -82,7 +84,7 @@ namespace Ombi ctx.SaveChanges(); } } - else if(baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) + else if (baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) { dbBaseUrl.Value = baseUrl; ctx.SaveChanges(); @@ -96,6 +98,51 @@ namespace Ombi BuildWebHost(args).Run(); } + 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("TRUNCATE TABLE GlobalSettings"); + if(doneConfig) + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE ApplicationConfiguration"); + + } + + } + private static void DeleteSchedulesDb() { try diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 2d86d4471..cad5da907 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -177,7 +177,7 @@ namespace Ombi // Check if it's in the startup args var appConfig = serviceProvider.GetService(); - var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result; + var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl); if (baseUrl != null) { if (baseUrl.Value.HasValue()) From 69b573a393c585dc3442cf449ca7399d3532ff1a Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 4 Oct 2018 14:38:47 +0100 Subject: [PATCH 028/325] some comments detaling why we move out the setting !wip --- src/Ombi/Program.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index c0382f8de..a3d06d073 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -98,6 +98,15 @@ namespace Ombi BuildWebHost(args).Run(); } + /// + /// 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. + /// private static void CheckAndMigrate() { var doneGlobal = false; From 479ca819d75f61144f7049c7f16feeca26b2a503 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 4 Oct 2018 14:48:21 +0100 Subject: [PATCH 029/325] Added in the external repo so we can rip out external stuff --- src/Ombi.DependencyInjection/IocExtensions.cs | 3 + src/Ombi.Store/Context/ExternalContext.cs | 67 +++++++++++ src/Ombi.Store/Context/IExternalContext.cs | 21 ++++ src/Ombi.Store/Repository/BaseRepository.cs | 105 ++++++++++++++++++ .../Repository/ExternalRepository.cs | 12 ++ .../Repository/IExternalRepository.cs | 30 +++++ src/Ombi.Store/Repository/Repository.cs | 99 +---------------- 7 files changed, 241 insertions(+), 96 deletions(-) create mode 100644 src/Ombi.Store/Context/ExternalContext.cs create mode 100644 src/Ombi.Store/Context/IExternalContext.cs create mode 100644 src/Ombi.Store/Repository/BaseRepository.cs create mode 100644 src/Ombi.Store/Repository/ExternalRepository.cs create mode 100644 src/Ombi.Store/Repository/IExternalRepository.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 53c212ea1..ff93141e5 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -129,9 +129,11 @@ namespace Ombi.DependencyInjection public static void RegisterStore(this IServiceCollection services) { services.AddEntityFrameworkSqlite().AddDbContext(); services.AddEntityFrameworkSqlite().AddDbContext(); + services.AddEntityFrameworkSqlite().AddDbContext(); services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 + services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -146,6 +148,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(typeof(ISettingsService<>), typeof(SettingsService<>)); services.AddTransient(typeof(IRepository<>), typeof(Repository<>)); + services.AddTransient(typeof(IExternalRepository<>), typeof(ExternalRepository<>)); } public static void RegisterServices(this IServiceCollection services) { diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs new file mode 100644 index 000000000..e77013d42 --- /dev/null +++ b/src/Ombi.Store/Context/ExternalContext.cs @@ -0,0 +1,67 @@ +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 { get; set; } + public DbSet PlexEpisode { get; set; } + public DbSet RadarrCache { get; set; } + public DbSet CouchPotatoCache { get; set; } + public DbSet EmbyContent { get; set; } + public DbSet EmbyEpisode { get; set; } + + public DbSet SonarrCache { get; set; } + public DbSet LidarrArtistCache { get; set; } + public DbSet LidarrAlbumCache { get; set; } + public DbSet SonarrEpisodeCache { get; set; } + public DbSet SickRageCache { get; set; } + public DbSet 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, "ExternalOmbi.db")}"); + } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity().HasMany(x => x.Episodes) + .WithOne(x => x.Series) + .HasPrincipalKey(x => x.Key) + .HasForeignKey(x => x.GrandparentKey); + + builder.Entity() + .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(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/IExternalContext.cs b/src/Ombi.Store/Context/IExternalContext.cs new file mode 100644 index 000000000..3f5d79a79 --- /dev/null +++ b/src/Ombi.Store/Context/IExternalContext.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities; + +namespace Ombi.Store.Context +{ + public interface IExternalContext : IDbContext + { + DbSet CouchPotatoCache { get; set; } + DbSet EmbyContent { get; set; } + DbSet EmbyEpisode { get; set; } + DbSet LidarrAlbumCache { get; set; } + DbSet LidarrArtistCache { get; set; } + DbSet PlexEpisode { get; set; } + DbSet PlexServerContent { get; set; } + DbSet RadarrCache { get; set; } + DbSet SickRageCache { get; set; } + DbSet SickRageEpisodeCache { get; set; } + DbSet SonarrCache { get; set; } + DbSet SonarrEpisodeCache { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs new file mode 100644 index 000000000..1679035dd --- /dev/null +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -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 : IRepository where T : Entity where U : IDbContext + { + public BaseRepository(U ctx) + { + _ctx = ctx; + _db = _ctx.Set(); + } + public DbSet _db { get; } + private readonly U _ctx; + + public async Task Find(object key) + { + return await _db.FindAsync(key); + } + + public IQueryable GetAll() + { + return _db.AsQueryable(); + } + + public async Task FirstOrDefaultAsync(Expression> predicate) + { + return await _db.FirstOrDefaultAsync(predicate); + } + + public async Task AddRange(IEnumerable content, bool save = true) + { + _db.AddRange(content); + if (save) + { + await _ctx.SaveChangesAsync(); + } + } + + public async Task 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 req) + { + _db.RemoveRange(req); + await _ctx.SaveChangesAsync(); + } + + public async Task SaveChangesAsync() + { + return await _ctx.SaveChangesAsync(); + } + + public IIncludableQueryable Include( + IQueryable source, Expression> 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); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/ExternalRepository.cs b/src/Ombi.Store/Repository/ExternalRepository.cs new file mode 100644 index 000000000..d7494afd4 --- /dev/null +++ b/src/Ombi.Store/Repository/ExternalRepository.cs @@ -0,0 +1,12 @@ +using Ombi.Store.Context; +using Ombi.Store.Entities; + +namespace Ombi.Store.Repository +{ + public class ExternalRepository : BaseRepository, IExternalRepository where T : Entity + { + public ExternalRepository(IExternalContext ctx) : base(ctx) + { + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IExternalRepository.cs b/src/Ombi.Store/Repository/IExternalRepository.cs new file mode 100644 index 000000000..de8b6db67 --- /dev/null +++ b/src/Ombi.Store/Repository/IExternalRepository.cs @@ -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 : IDisposable where T : Entity + { + Task Find(object key); + IQueryable GetAll(); + Task FirstOrDefaultAsync(Expression> predicate); + Task AddRange(IEnumerable content, bool save = true); + Task Add(T content); + Task DeleteRange(IEnumerable req); + Task Delete(T request); + Task SaveChangesAsync(); + + IIncludableQueryable Include( + IQueryable source, Expression> navigationPropertyPath) + where TEntity : class; + + Task ExecuteSql(string sql); + DbSet _db { get; } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Repository/Repository.cs b/src/Ombi.Store/Repository/Repository.cs index 8c07c2371..9d49ded58 100644 --- a/src/Ombi.Store/Repository/Repository.cs +++ b/src/Ombi.Store/Repository/Repository.cs @@ -1,105 +1,12 @@ -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.Context; using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class Repository : IRepository where T : Entity + public class Repository : BaseRepository, IRepository where T : Entity { - public Repository(IOmbiContext ctx) + public Repository(IOmbiContext ctx) : base(ctx) { - _ctx = ctx; - _db = _ctx.Set(); - } - public DbSet _db { get; } - private readonly IOmbiContext _ctx; - - public async Task Find(object key) - { - return await _db.FindAsync(key); - } - - public IQueryable GetAll() - { - return _db.AsQueryable(); - } - - public async Task FirstOrDefaultAsync(Expression> predicate) - { - return await _db.FirstOrDefaultAsync(predicate); - } - - public async Task AddRange(IEnumerable content, bool save = true) - { - _db.AddRange(content); - if (save) - { - await _ctx.SaveChangesAsync(); - } - } - - public async Task 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 req) - { - _db.RemoveRange(req); - await _ctx.SaveChangesAsync(); - } - - public async Task SaveChangesAsync() - { - return await _ctx.SaveChangesAsync(); - } - - public IIncludableQueryable Include( - IQueryable source, Expression> 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); } } } \ No newline at end of file From 26da9d242c5ad9eeb4ab8dad963c1f34b925616d Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 4 Oct 2018 14:49:24 +0100 Subject: [PATCH 030/325] ExternalContext migrations --- .../20181004134907_Inital.Designer.cs | 312 ++++++++++++++++++ .../External/20181004134907_Inital.cs | 308 +++++++++++++++++ .../External/ExternalContextModelSnapshot.cs | 310 +++++++++++++++++ 3 files changed, 930 insertions(+) create mode 100644 src/Ombi.Store/Migrations/External/20181004134907_Inital.Designer.cs create mode 100644 src/Ombi.Store/Migrations/External/20181004134907_Inital.cs create mode 100644 src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs diff --git a/src/Ombi.Store/Migrations/External/20181004134907_Inital.Designer.cs b/src/Ombi.Store/Migrations/External/20181004134907_Inital.Designer.cs new file mode 100644 index 000000000..776d3e082 --- /dev/null +++ b/src/Ombi.Store/Migrations/External/20181004134907_Inital.Designer.cs @@ -0,0 +1,312 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("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 + } + } +} diff --git a/src/Ombi.Store/Migrations/External/20181004134907_Inital.cs b/src/Ombi.Store/Migrations/External/20181004134907_Inital.cs new file mode 100644 index 000000000..bc4dc509e --- /dev/null +++ b/src/Ombi.Store/Migrations/External/20181004134907_Inital.cs @@ -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(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TheMovieDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CouchPotatoCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EmbyContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + EmbyId = table.Column(nullable: false), + Type = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + Url = table.Column(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(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ArtistId = table.Column(nullable: false), + ForeignAlbumId = table.Column(nullable: true), + TrackCount = table.Column(nullable: false), + ReleaseDate = table.Column(nullable: false), + Monitored = table.Column(nullable: false), + Title = table.Column(nullable: true), + PercentOfTracks = table.Column(nullable: false), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "LidarrArtistCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ArtistId = table.Column(nullable: false), + ArtistName = table.Column(nullable: true), + ForeignArtistId = table.Column(nullable: true), + Monitored = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LidarrArtistCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PlexServerContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + ReleaseYear = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + Type = table.Column(nullable: false), + Url = table.Column(nullable: true), + Key = table.Column(nullable: false), + AddedAt = table.Column(nullable: false), + Quality = table.Column(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(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TheMovieDbId = table.Column(nullable: false), + HasFile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RadarrCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SickRageCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SickRageCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SickRageEpisodeCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SickRageEpisodeCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SonarrCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TvDbId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SonarrCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SonarrEpisodeCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + TvDbId = table.Column(nullable: false), + HasFile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SonarrEpisodeCache", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EmbyEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + EmbyId = table.Column(nullable: true), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + ParentId = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false), + TvDbId = table.Column(nullable: true), + ImdbId = table.Column(nullable: true), + TheMovieDbId = table.Column(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(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EpisodeNumber = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + Key = table.Column(nullable: false), + Title = table.Column(nullable: true), + ParentKey = table.Column(nullable: false), + GrandparentKey = table.Column(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(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PlexContentId = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + SeasonKey = table.Column(nullable: false), + ParentKey = table.Column(nullable: false), + PlexServerContentId = table.Column(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"); + } + } +} diff --git a/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs b/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs new file mode 100644 index 000000000..4e97b5514 --- /dev/null +++ b/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs @@ -0,0 +1,310 @@ +// +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("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("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 + } + } +} From ca483618651c20e1e55161a7da84ef0347fae3e8 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 4 Oct 2018 15:05:43 +0100 Subject: [PATCH 031/325] Done the migration for the external db !wip --- .../Rules/Request/SonarrCacheRequestRule.cs | 4 +- .../Rules/Search/SonarrCacheSearchRule.cs | 4 +- src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs | 4 +- .../Jobs/Couchpotato/CouchPotatoSync.cs | 4 +- .../Jobs/Lidarr/LidarrAlbumSync.cs | 4 +- .../Jobs/Lidarr/LidarrArtistSync.cs | 4 +- src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 4 +- .../Jobs/SickRage/SickRageSync.cs | 5 +- src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 4 +- src/Ombi.Store/Context/IOmbiContext.cs | 22 +++--- src/Ombi.Store/Entities/PlexServerContent.cs | 14 ---- .../Repository/EmbyContentRepository.cs | 6 +- .../Repository/IPlexContentRepository.cs | 2 +- .../Repository/PlexContentRepository.cs | 6 +- src/Ombi/Program.cs | 78 ++++++++++++++++++- 15 files changed, 112 insertions(+), 53 deletions(-) diff --git a/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs index 65750a64b..625407f3c 100644 --- a/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/SonarrCacheRequestRule.cs @@ -7,12 +7,12 @@ namespace Ombi.Core.Rule.Rules.Request { public class SonarrCacheRequestRule : BaseRequestRule, IRules { - public SonarrCacheRequestRule(IOmbiContext ctx) + public SonarrCacheRequestRule(IExternalContext ctx) { _ctx = ctx; } - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; public Task Execute(BaseRequest obj) { diff --git a/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs b/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs index f9c5cd09d..03bdbe091 100644 --- a/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/SonarrCacheSearchRule.cs @@ -34,12 +34,12 @@ namespace Ombi.Core.Rule.Rules.Search { public class SonarrCacheSearchRule : BaseSearchRule, IRules { - public SonarrCacheSearchRule(IOmbiContext ctx) + public SonarrCacheSearchRule(IExternalContext ctx) { _ctx = ctx; } - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; public Task Execute(SearchViewModel obj) { diff --git a/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs b/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs index c851afb4b..7eac05d56 100644 --- a/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs @@ -10,12 +10,12 @@ namespace Ombi.Core.Rule.Rules { public class SonarrCacheRule { - public SonarrCacheRule(IOmbiContext ctx) + public SonarrCacheRule(IExternalContext ctx) { _ctx = ctx; } - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; public async Task Execute(BaseRequest obj) { diff --git a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs index 8606de371..5e9f13534 100644 --- a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs +++ b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs @@ -42,7 +42,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato public class CouchPotatoSync : ICouchPotatoSync { public CouchPotatoSync(ISettingsService cpSettings, - ICouchPotatoApi api, ILogger log, IOmbiContext ctx) + ICouchPotatoApi api, ILogger log, IExternalContext ctx) { _settings = cpSettings; _api = api; @@ -54,7 +54,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato private readonly ISettingsService _settings; private readonly ICouchPotatoApi _api; private readonly ILogger _log; - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; public async Task Start() { diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index 2e32b6478..d19fe561a 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -20,7 +20,7 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrAlbumSync : ILidarrAlbumSync { - public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IOmbiContext ctx, + public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IExternalContext ctx, IBackgroundJobClient job, ILidarrAvailabilityChecker availability) { _lidarrSettings = lidarr; @@ -35,7 +35,7 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; private readonly IBackgroundJobClient _job; private readonly ILidarrAvailabilityChecker _availability; diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs index ac6264e3d..4117ee44a 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs @@ -20,7 +20,7 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrArtistSync : ILidarrArtistSync { - public LidarrArtistSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IOmbiContext ctx, + public LidarrArtistSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IExternalContext ctx, IBackgroundJobClient background, ILidarrAlbumSync album) { _lidarrSettings = lidarr; @@ -35,7 +35,7 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; private readonly IBackgroundJobClient _job; private readonly ILidarrAlbumSync _albumSync; diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 0aea8cdc2..5c954def8 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -16,7 +16,7 @@ namespace Ombi.Schedule.Jobs.Radarr { public class RadarrSync : IRadarrSync { - public RadarrSync(ISettingsService radarr, IRadarrApi radarrApi, ILogger log, IOmbiContext ctx) + public RadarrSync(ISettingsService radarr, IRadarrApi radarrApi, ILogger log, IExternalContext ctx) { RadarrSettings = radarr; RadarrApi = radarrApi; @@ -28,7 +28,7 @@ namespace Ombi.Schedule.Jobs.Radarr private ISettingsService RadarrSettings { get; } private IRadarrApi RadarrApi { get; } private ILogger Logger { get; } - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; private static readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1); diff --git a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs index d2330197d..92e0c2d55 100644 --- a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs +++ b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -17,7 +16,7 @@ namespace Ombi.Schedule.Jobs.SickRage { public class SickRageSync : ISickRageSync { - public SickRageSync(ISettingsService s, ISickRageApi api, ILogger l, IOmbiContext ctx) + public SickRageSync(ISettingsService s, ISickRageApi api, ILogger l, IExternalContext ctx) { _settings = s; _api = api; @@ -29,7 +28,7 @@ namespace Ombi.Schedule.Jobs.SickRage private readonly ISettingsService _settings; private readonly ISickRageApi _api; private readonly ILogger _log; - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; public async Task Start() { diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index ec5502581..e4c00c726 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -19,7 +19,7 @@ namespace Ombi.Schedule.Jobs.Sonarr { public class SonarrSync : ISonarrSync { - public SonarrSync(ISettingsService s, ISonarrApi api, ILogger l, IOmbiContext ctx) + public SonarrSync(ISettingsService s, ISonarrApi api, ILogger l, IExternalContext ctx) { _settings = s; _api = api; @@ -31,7 +31,7 @@ namespace Ombi.Schedule.Jobs.Sonarr private readonly ISettingsService _settings; private readonly ISonarrApi _api; private readonly ILogger _log; - private readonly IOmbiContext _ctx; + private readonly IExternalContext _ctx; public async Task Start() { diff --git a/src/Ombi.Store/Context/IOmbiContext.cs b/src/Ombi.Store/Context/IOmbiContext.cs index f21a3f0db..e34e1d648 100644 --- a/src/Ombi.Store/Context/IOmbiContext.cs +++ b/src/Ombi.Store/Context/IOmbiContext.cs @@ -12,12 +12,12 @@ namespace Ombi.Store.Context public interface IOmbiContext : IDbContext { - DbSet PlexServerContent { get; set; } - DbSet PlexEpisode { get; set; } + //DbSet PlexServerContent { get; set; } + //DbSet PlexEpisode { get; set; } DbSet Settings { get; set; } - DbSet RadarrCache { get; set; } - DbSet EmbyContent { get; set; } - DbSet EmbyEpisode { get; set; } + //DbSet RadarrCache { get; set; } + //DbSet EmbyContent { get; set; } + //DbSet EmbyEpisode { get; set; } DbSet NotificationTemplates { get; set; } DbSet ApplicationConfigurations { get; set; } DbSet Audit { get; set; } @@ -29,12 +29,12 @@ namespace Ombi.Store.Context DbSet IssueCategories { get; set; } DbSet Tokens { get; set; } DbSet SonarrCache { get; set; } - DbSet SonarrEpisodeCache { get; set; } - DbSet CouchPotatoCache { get; set; } - DbSet SickRageCache { get; set; } - DbSet LidarrArtistCache { get; set; } - DbSet LidarrAlbumCache { get; set; } - DbSet SickRageEpisodeCache { get; set; } + //DbSet SonarrEpisodeCache { get; set; } + //DbSet CouchPotatoCache { get; set; } + //DbSet SickRageCache { get; set; } + //DbSet LidarrArtistCache { get; set; } + //DbSet LidarrAlbumCache { get; set; } + //DbSet SickRageEpisodeCache { get; set; } DbSet RequestLogs { get; set; } DbSet RecentlyAddedLogs { get; set; } DbSet RequestSubscription { get; set; } diff --git a/src/Ombi.Store/Entities/PlexServerContent.cs b/src/Ombi.Store/Entities/PlexServerContent.cs index 14028cb57..eff872b60 100644 --- a/src/Ombi.Store/Entities/PlexServerContent.cs +++ b/src/Ombi.Store/Entities/PlexServerContent.cs @@ -42,11 +42,6 @@ namespace Ombi.Store.Entities public PlexMediaTypeEntity Type { get; set; } public string Url { get; set; } - - /// - /// Only used for TV Shows - /// - public virtual ICollection Seasons { get; set; } public ICollection Episodes { get; set; } @@ -67,15 +62,6 @@ namespace Ombi.Store.Entities public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); } - [Table("PlexSeasonsContent")] - public class PlexSeasonsContent : Entity - { - public int PlexContentId { get; set; } - public int SeasonNumber { get; set; } - public int SeasonKey { get; set; } - public int ParentKey { get; set; } - } - public enum PlexMediaTypeEntity { Movie = 0, diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index c4377f929..4d32e8da2 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -35,15 +35,15 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class EmbyContentRepository : Repository, IEmbyContentRepository + public class EmbyContentRepository : ExternalRepository, IEmbyContentRepository { - public EmbyContentRepository(IOmbiContext db):base(db) + public EmbyContentRepository(IExternalContext db):base(db) { Db = db; } - private IOmbiContext Db { get; } + private IExternalContext Db { get; } public async Task GetByImdbId(string imdbid) diff --git a/src/Ombi.Store/Repository/IPlexContentRepository.cs b/src/Ombi.Store/Repository/IPlexContentRepository.cs index 381a89fa3..7bce2e75a 100644 --- a/src/Ombi.Store/Repository/IPlexContentRepository.cs +++ b/src/Ombi.Store/Repository/IPlexContentRepository.cs @@ -7,7 +7,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IPlexContentRepository : IRepository + public interface IPlexContentRepository : IExternalRepository { Task ContentExists(string providerId); Task Get(string providerId); diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index e452eeb7d..2c9c28d09 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -36,15 +36,15 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class PlexServerContentRepository : Repository, IPlexContentRepository + public class PlexServerContentRepository : ExternalRepository, IPlexContentRepository { - public PlexServerContentRepository(IOmbiContext db) : base(db) + public PlexServerContentRepository(IExternalContext db) : base(db) { Db = db; } - private IOmbiContext Db { get; } + private IExternalContext Db { get; } public async Task ContentExists(string providerId) diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index a3d06d073..6b6b07492 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -143,13 +143,87 @@ namespace Ombi } // Now delete the old stuff - if(doneGlobal) + if (doneGlobal) ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE GlobalSettings"); - if(doneConfig) + if (doneConfig) ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE 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("TRUNCATE TABLE PlexEpisode"); + } + + if (ombi.PlexServerContent.Any()) + { + external.PlexServerContent.AddRange(ombi.PlexServerContent.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE PlexServerContent"); + } + if (ombi.EmbyEpisode.Any()) + { + external.EmbyEpisode.AddRange(ombi.EmbyEpisode.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE EmbyEpisode"); + } + + if (ombi.EmbyContent.Any()) + { + external.EmbyContent.AddRange(ombi.EmbyContent.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE EmbyContent"); + } + if (ombi.RadarrCache.Any()) + { + external.RadarrCache.AddRange(ombi.RadarrCache.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE RadarrCache"); + } + if (ombi.SonarrCache.Any()) + { + external.SonarrCache.AddRange(ombi.SonarrCache.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE SonarrCache"); + } + if (ombi.LidarrAlbumCache.Any()) + { + external.LidarrAlbumCache.AddRange(ombi.LidarrAlbumCache.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE LidarrAlbumCache"); + } + if (ombi.LidarrArtistCache.Any()) + { + external.LidarrArtistCache.AddRange(ombi.LidarrArtistCache.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE LidarrArtistCache"); + } + if (ombi.SickRageEpisodeCache.Any()) + { + external.SickRageEpisodeCache.AddRange(ombi.SickRageEpisodeCache.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE SickRageEpisodeCache"); + } + if (ombi.SickRageCache.Any()) + { + external.SickRageCache.AddRange(ombi.SickRageCache.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE SickRageCache"); + } + if (ombi.CouchPotatoCache.Any()) + { + external.CouchPotatoCache.AddRange(ombi.CouchPotatoCache.ToList()); + ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE CouchPotatoCache"); + } + + external.SaveChanges(); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } + } private static void DeleteSchedulesDb() From a40af63a9c6cfff9955d12085e3644799cecda8e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 4 Oct 2018 15:10:31 +0100 Subject: [PATCH 032/325] Fixed build !wip --- src/Ombi.Store/Entities/PlexServerContent.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Ombi.Store/Entities/PlexServerContent.cs b/src/Ombi.Store/Entities/PlexServerContent.cs index eff872b60..17d8ceffb 100644 --- a/src/Ombi.Store/Entities/PlexServerContent.cs +++ b/src/Ombi.Store/Entities/PlexServerContent.cs @@ -44,6 +44,7 @@ namespace Ombi.Store.Entities public string Url { get; set; } public ICollection Episodes { get; set; } + public ICollection Seasons { get; set; } /// /// Plex's internal ID for this item @@ -62,6 +63,15 @@ namespace Ombi.Store.Entities public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); } + [Table("PlexSeasonsContent")] + public class PlexSeasonsContent : Entity + { + public int PlexContentId { get; set; } + public int SeasonNumber { get; set; } + public int SeasonKey { get; set; } + public int ParentKey { get; set; } + } + public enum PlexMediaTypeEntity { Movie = 0, From 8540bd6ffbeac6660de81d8002c19af560df96dc Mon Sep 17 00:00:00 2001 From: ImgBotApp Date: Thu, 4 Oct 2018 14:52:45 +0000 Subject: [PATCH 033/325] [ImgBot] optimizes images *Total -- 84.51kb -> 54.82kb (35.13%) /src/Ombi/wwwroot/images/default_tv_poster.png -- 1.73kb -> 0.68kb (60.87%) /src/Ombi/wwwroot/images/default_movie_poster.png -- 1.65kb -> 0.71kb (57.15%) /src/Ombi/wwwroot/images/default-music-placeholder.png -- 78.88kb -> 51.19kb (35.1%) /src/Ombi/wwwroot/images/favicon/apple-touch-icon.png -- 2.25kb -> 2.24kb (0.3%) --- .../images/default-music-placeholder.png | Bin 80771 -> 52419 bytes .../wwwroot/images/default_movie_poster.png | Bin 1685 -> 722 bytes src/Ombi/wwwroot/images/default_tv_poster.png | Bin 1776 -> 695 bytes .../images/favicon/apple-touch-icon.png | Bin 2304 -> 2297 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Ombi/wwwroot/images/default-music-placeholder.png b/src/Ombi/wwwroot/images/default-music-placeholder.png index f6decc9e07d9189eb9336f0f050605e01b01f6db..4cff17018415abd32454c8fa1accc231b77e36f6 100644 GIT binary patch literal 52419 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

UUD6$UC<->tdA8PRNsV(`3QoVA=O@ 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

<1N>bM;KKgRSg=u3~yJG^ynu+8y?WpH`;Er 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 literal 1685 zcmeAS@N?(olHy`uVBq!ia0vp^Cm0wQbvW37thQf&_AxN9#dx|nhE&XXd)MDzDq80F zL*t5{{xK7>axU-q_ILjhy;;k0V#ong(>C9n;y>TcRBr!{9U9FC7hEZgUAKPy>9oz2N3ZUcz5BDX>_Uy5{^px& zg8BbUzw-L)sT?!y&p-d%@P4`G|8xI;tv+g#2^mm8;lT*mq2z`OVFPiJklx^Z2ehb`4aO7_j`|1VjJ98Nzq ziu+lm`TqWX{lgDGJh=bdUuA;roqPA}ZZ?O6hN?~Wl#tSm3gzYH zOV_>LbT_a5_xFn#AwX}hUh{UXu!r~Sue)mg|Eqnz@%HW8MU|B|SN8rY+pQbFzphru zUDN)WwG5y4{`>ZaPTdomt{+uZQITP@?QUMVok0J~ou*5FAGU`l*UXnso-Fwo5gI!8 z)`IDu{>-}c_o4i{q^(!pe?MJgcmL<2`zb~*QxwwE(}C_#KhDnl7p?U$vM_s-&JKO7W#)iK^>&8k&}e6QcVTUU7J?g~$9 zrcBM=Svq3fa~G@qt=nJo=f}qd#*u&P>Ys~hE>_cbR?yulX?n9%_4Sh{Pc){7-0qph z@ucz_G)*P&U%Iqk*0i#s!s3+L-{-SteN%Mvy(Q@34K!&__4mB><))GAuRs0#{5<>q zGru1mZdaFnw`$d?pFb-fr^ZQtDP!5xelus=_1EmDpMHAqe`40|yVIT)?flGWFV|nb z&(66TV$br3>K!|GX3CVme{>}$_ImH*clo(SKOrvcm4Wx>weSTSu&S_fqj2p zZT21J-s8#AU&ZDmZG95!`_Bhn2y6j!K>=x!_3883)w?B5fE+SAe0S5;K8J4`-mf^B zZObuxUw`1_|9%SWCNg}dj~+dG(B9#Adb3QQ10OJ@{bX5T?xO&AO**5VSog8Q^2KUz zIaF@snC-V?EZZ7o+BfS;>D`^Zzs?6vj(xT3-`mM~=CjXc>%H|YoM~QR^WyuR<`vzG z)lNSCy*YcqM0uNL7W?^zyDV1z7BZXdyYls}k25C*ty;Z$b>81s&3uJjtfPe(JPIi& c&j0YFdh=h>L~KMCQA_Y%b8IS)MMAAr-gY-aPBYY$(EZ!OqXP?+0_%mf3yAGxq!! z-ud3iC{y!#!M;?5ZswhwPpoCwPcpL58a#P7VaoNO^5ttRk2WnSetX8Uwdu*NxiVav zzBykDm~e?-bD_f5E|!)vm)D(1RJ^>;SC|6>oZwYF{Ktgv^LJ~8lo@p?GmdHL?(I_z zYp?LBe4UtcG3u`Ur_$5RESDyCr@s%$Ui_razc){Mw>jXErLzpB2CM zTVulZ8xwYZ&G>7>BLD6A`(>Pw^ZwnnE?V9|W8iX5|L`K`HM@Hz=>j88wZt`|BqgyV z)hf9t6-Y4{85mmV8XD*tn1mRbSeY7G8Chr>7+4t?Xm8rkjiMnpKP5A*61Rq^_Z;Rx w4U!-mg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4hf>INMr>mdKI;Vst021=#+5i9m literal 1776 zcmeAS@N?(olHy`uVBq!ia0vp^Cm0wQbvT%SEY2C(FM*U~iEBhjaDG}zd16s2gJVj5 zQmTSyZen_BP-l zO)W`OsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~DO*S+!QZTpF zGc+@>G&0dqFfuSS*EcZNH#F8YFtjo-vof|+fC43;ZAB?*RzWUqP`iLUTcwPWk^(Dz z{qpj1y>er{{GxPyLrY6beFGzXBO_g)3fZE`@j@w*YQzUNJP7fB~jokyxN_sAmB35=^15FMg%Dxp39RB|)hO_hL1; zIHa;5RX-@TIKQ+g85nVC${?!>telHd6HD@oLh|!-V4)b0kzbNuoRMFk;OwlR5uTZs zl3!k|30CgwYvq|&T#}fVoa*Ufs{}MaFEca6%FM*V$kfEu*x1s*($LV=!qLdW)zQSn z+1SzCz{Sbc5~kNBKe;qFHLnDwHwB^B1gBn5O2{n$+U$~Alv$RV;#QQOs{r<~RVHq? z7~(V!sy799yBiO3djj(>Wj6+5Kc& z-Lg|`mm~G2%U{@X#JgdGfY>3XL`9tz)q1Rudu9rqma}8`ceyFN<)w9o)+i&OooDey! z*KM&u`n=~Kw~9Utl2{k2yZ+T`gDi;~a<5riL@yjTRCVChyk%@+*POTMvu&%aZ@ZdR zx-;h1r$E0+N0T1j=QZ4MrzSzug{Y8fVdeiIW*^}@>4?Fhtb5jfmfQ{M*bsO5Wr@*- z4YR_hEp2SQx@VEbs#R4}GY_vweDLF5Yy9MsD%ZNhW-ZJ8#}#({YuWC*IcD!>{V_Te z{q^^|9&*r<0+{(ORQ@Dylq8^mODt z#fC-{YMuVH{NCLS_4nVF9qJ0c;qtt)&PHy2&B9fywB~%TvHKk+u@)G_aqHKfUWb`> jI8G1w)b;;eKLay^g>(Pw(m4fvpgPFY)z4*}Q$iB}QrLNN diff --git a/src/Ombi/wwwroot/images/favicon/apple-touch-icon.png b/src/Ombi/wwwroot/images/favicon/apple-touch-icon.png index 1e6943041824a47d37fc45aac84e1400fc5af52b..069c32adb48d915543551fba5f73cad0fdbf5f4b 100644 GIT binary patch delta 2269 zcmZuyc{J3E9v^WVh7{S?v2S6Fv5h@rUoMiJhG8t(%_LL#$&w01?;^#s8zMxMVF))A zl8i}eq8eft`&jS2bJctAyz|a^-|so!?eqPd&!3-E!F_=|1OUa@xjTbE1Z5B?H3I}X z03G#35C{(gff#5I2zeg_5{)Y%xtSaRXI-51fAlt#XWN3fBc_~uoEk)*uJSE`47I=Qu*Lll|v_A z?&sWu2ADDnGZ-4xsuxaIf39^ulkTdFotfBC`U3axrlV!_^Smi3+O47K%3245E1mLI z`YWFB)Fh>dCIO}ILciTB=5K$uN|d^A&3^iVdAMwMjtuZnQ&Cb)(n5a*?e)H!^J`_$Oh ze$)d}NM0Ukn3@QxFY|Qf5#_n5Ply<@VwF6?u0WzE#Kw9=UizC~(__fkOrBY^(+J^( z>W-S?9{@@{ns;clq?!vK?3~6bAE&ffQv6gEv?9JK(GPk0cti6&74)$K+WJy>doiT~ zTj!G^d~-dtIzPg4bIv4^?AyC%N?NrNdv3 zARFC8mfls&NlZG%5||cS?z;v?TTgt&4LB=fSs4TdVrq08MwDHWr(My{U6sOrXK>R1 z-K~};iC=0tcjy?06aIRLEMEnQMQ$wj3H(RXhjvtDzD*b@#CDpSH7are_p z_#yZ{bQN+JRIi)aiwt*mwx0h~l>ju|g<$T>sZzXkn{US>YxLhfAeb1+{Ym9eAB(C> z%C@wt^P9fZUv+$Q-5eEL@=E0^h>VOPSO;TL??ghe$yVOY)T0Tz$y4}uFWTp#3UCsBmwTmQ(R!MEt)Sg zABUN!;L!7*9%5oY57h(7yTWwDN%coXssY^#?F+2WNS3n=ku}HR@+-$?C^<&CZS@Ly zA@Ac-Q(eWK-$LyvbKuI3$8Ic%)yBh=W;~C$z(BDv=DAGG)cC>PaLvNIeJk)K_pGza z`9)b5Kef>|o;r?kJ#<}bf^(6K(cD^|W0O_K%Lrk)99gv{R0a@K5jehUt+_*$;g;4u zh1Gg);v@~rniGGPv{7-f(~|6ik=%U0r_*3doVuSle3AS5;83}9Z5f4l!-A2gmhlye zFlbv9l#2X%j<~YH{|ptgU@D=E9%UWY3`!Rvqm51Y1CVksiiGbx&Ha5sTV>1s5^6uL zo)u?SqxHVt8gTty;TPO{eOUWqdxa-KT;$L!&2F0iuuv?QSxbtIOY077-Y|2d`Dhjv zwe0%4vKzTWCd{4J?G5Cr)%7afR*wxK!%{!Bh(+y*^Y>|ciL(m_ti2t zH5L-eH#Eq z7jWVcr~!i^VK9x>mhAswM8}3iV3U6`{x89IjoaXe O0J67sK{cI4r~M7Vb0Nk6 delta 2267 zcmV<12qgFU5r7hqG=BkeQb$4nuFf3k0000#P)t-s0@k8l zF9co$TIvX5r?~tJ&;a66+_})luBd}P`9)|26uA&~4z$8qp?(266FEoiRA|}a0@2DF zp{2%!Lf;0haDTy2w?LP1MvmC%cV$jrsx__ku#$KyC%p-M~8tjWGYPkDu^vfHCsd-51Aau*8pqolL_DQRaL%v@Cu9UZF z(2~#I*p|f{O^rFl{f3%m7F%T!v>sQ!hcFA>Gh#Od!_^@*O?(qN1zPe$8JJVHW^{O0 zX3RdIHgAX|$}JP1H9rW0I1x5%GBE$9c7gkv@PDMx3DAM&=mcnXg7YFmJ?eS6-6+*g z0};2!UGW%N9Ss6j)rpS!9J|z%HM3v*Hll777+N0-?V#5Z?ov$cDyOz50o%=3?%zf zuYai5N>j`Hf+^j?pk)}k-dcB$dQf$S9+??zsFomT%}II zK+v3=st}<5aYt06(u9lJpNbNkL@G@rNa-jgR@Cf^y7Cn58y7u|?}`9uMaobQl1@$& zO8}UODi6J;rh=@ghq2ilkub8_6J7(Y0j>JfJ!Po=nW-!Ds9?jayBYIHQd|RV1~7kG ztf{Jby#65bze+VNubD`J*4IG$T7Qp#v(}&Wth@L_(8tv8_40|2hXV$1S)zJvsL7T(vPHn5DNB`ls&q5*eNl_p)`8IJL4=zNuCuA* zq5o}!i>+Je2Axo!w%9@b8_$z^R@&@yva}`;Xq^Y`JpH0uY67H&Od+UDXy#_!5%H+; zmO5?3JDkhQWOnl&6&Gao^?&%xOt|0Mek=jw4_&Ap3a|Dsn4-cW0TYD0+=jyS;3Hbb{rUFKYLQsSX+) zzy8P_q4Pb&by_b<(}2N!GUIqkX$xkII$ zYl_NKzgBZ(X+ocz)ho)xirR}lP3V*Jr_rU#U1&WGSIX zY{W6f1P#b&eH`1>s4c}vDFBP8_W5X!BJN;cX#UC{VM}4@03~=g1*z%<*v}b zk2)&vL~Pax{eOp;duT04SS=J&6sVmd6ZI%u{MLg0arbo`m)tigmC1-Tb%8HzW-DM=9&VS55Efc++mp3~*)3;O|e8k91 z^<5&Ty3_#fu0T@tLfPvhxw|sy>&tylfK*}duG}{T6#hmA`+W@EhP~@be<#B=-+dvy zxS;vx3p*a@2l|12pdaW5`hk9+ALs}AfqtMbiT?m`yz=e`v<2P(0038dR9JLUVRs;K za&Km7Y?0jzQ2= Date: Thu, 4 Oct 2018 21:04:25 +0100 Subject: [PATCH 034/325] Fixed the migration --- src/Ombi.Store/Context/ExternalContext.cs | 3 ++- src/Ombi.Store/Context/OmbiContext.cs | 1 + src/Ombi/Program.cs | 31 +++++++++++++---------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs index e77013d42..eb2be6450 100644 --- a/src/Ombi.Store/Context/ExternalContext.cs +++ b/src/Ombi.Store/Context/ExternalContext.cs @@ -17,6 +17,7 @@ namespace Ombi.Store.Context } public DbSet PlexServerContent { get; set; } + public DbSet PlexSeasonsContent { get; set; } public DbSet PlexEpisode { get; set; } public DbSet RadarrCache { get; set; } public DbSet CouchPotatoCache { get; set; } @@ -37,7 +38,7 @@ namespace Ombi.Store.Context { i.StoragePath = string.Empty; } - optionsBuilder.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "ExternalOmbi.db")}"); + optionsBuilder.UseSqlite($"Data Source={Path.Combine(i.StoragePath, "OmbiExternal.db")}"); } protected override void OnModelCreating(ModelBuilder builder) diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 6660ee7d6..4245dfd8d 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -24,6 +24,7 @@ namespace Ombi.Store.Context public DbSet NotificationTemplates { get; set; } public DbSet ApplicationConfigurations { get; set; } public DbSet PlexServerContent { get; set; } + public DbSet PlexSeasonsContent { get; set; } public DbSet PlexEpisode { get; set; } public DbSet Settings { get; set; } public DbSet RadarrCache { get; set; } diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 6b6b07492..3a11093d2 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -144,9 +144,9 @@ namespace Ombi // Now delete the old stuff if (doneGlobal) - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE GlobalSettings"); + ombi.Database.ExecuteSqlCommand("DELETE FROM GlobalSettings"); if (doneConfig) - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE ApplicationConfiguration"); + ombi.Database.ExecuteSqlCommand("DELETE FROM ApplicationConfiguration"); } @@ -160,59 +160,64 @@ namespace Ombi if (ombi.PlexEpisode.Any()) { external.PlexEpisode.AddRange(ombi.PlexEpisode.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE PlexEpisode"); + 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("TRUNCATE TABLE PlexServerContent"); + ombi.Database.ExecuteSqlCommand("DELETE FROM PlexServerContent"); } if (ombi.EmbyEpisode.Any()) { external.EmbyEpisode.AddRange(ombi.EmbyEpisode.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE EmbyEpisode"); + ombi.Database.ExecuteSqlCommand("DELETE FROM EmbyEpisode"); } if (ombi.EmbyContent.Any()) { external.EmbyContent.AddRange(ombi.EmbyContent.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE EmbyContent"); + ombi.Database.ExecuteSqlCommand("DELETE FROM EmbyContent"); } if (ombi.RadarrCache.Any()) { external.RadarrCache.AddRange(ombi.RadarrCache.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE RadarrCache"); + ombi.Database.ExecuteSqlCommand("DELETE FROM RadarrCache"); } if (ombi.SonarrCache.Any()) { external.SonarrCache.AddRange(ombi.SonarrCache.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE SonarrCache"); + ombi.Database.ExecuteSqlCommand("DELETE FROM SonarrCache"); } if (ombi.LidarrAlbumCache.Any()) { external.LidarrAlbumCache.AddRange(ombi.LidarrAlbumCache.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE LidarrAlbumCache"); + ombi.Database.ExecuteSqlCommand("DELETE FROM LidarrAlbumCache"); } if (ombi.LidarrArtistCache.Any()) { external.LidarrArtistCache.AddRange(ombi.LidarrArtistCache.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE LidarrArtistCache"); + ombi.Database.ExecuteSqlCommand("DELETE FROM LidarrArtistCache"); } if (ombi.SickRageEpisodeCache.Any()) { external.SickRageEpisodeCache.AddRange(ombi.SickRageEpisodeCache.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE SickRageEpisodeCache"); + ombi.Database.ExecuteSqlCommand("DELETE FROM SickRageEpisodeCache"); } if (ombi.SickRageCache.Any()) { external.SickRageCache.AddRange(ombi.SickRageCache.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE SickRageCache"); + ombi.Database.ExecuteSqlCommand("DELETE FROM SickRageCache"); } if (ombi.CouchPotatoCache.Any()) { external.CouchPotatoCache.AddRange(ombi.CouchPotatoCache.ToList()); - ombi.Database.ExecuteSqlCommand("TRUNCATE TABLE CouchPotatoCache"); + ombi.Database.ExecuteSqlCommand("DELETE FROM CouchPotatoCache"); } external.SaveChanges(); From e8fbf53755b318841e54a58686c471d4c86f5566 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 5 Oct 2018 13:04:47 +0100 Subject: [PATCH 035/325] Date and times are now in the local users date time --- .../app/issues/issueDetails.component.html | 2 +- .../app/requests/movierequests.component.html | 8 ++++---- .../requests/music/musicrequests.component.html | 4 ++-- .../requests/tvrequest-children.component.html | 2 +- .../app/requests/tvrequests.component.html | 4 ++-- .../app/search/moviesearch.component.html | 6 +++--- .../app/search/moviesearchgrid.component.html | 4 ++-- .../app/search/music/albumsearch.component.html | 2 +- .../app/search/seriesinformation.component.html | 2 +- .../ClientApp/app/search/tvsearch.component.html | 4 ++-- src/Ombi/ClientApp/app/shared/shared.module.ts | 3 +++ .../usermanagement/usermanagement.component.html | 15 +++++++++++---- 12 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.html b/src/Ombi/ClientApp/app/issues/issueDetails.component.html index 33157cd09..44be113c6 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.html +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.html @@ -63,7 +63,7 @@

{{comment.comment}}

- +
diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index a35ede06c..6167fbac0 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -58,7 +58,7 @@ -
{{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate | date: 'mediumDate'} }}
-
{{ 'Requests.DigitalRelease' | translate: {date: request.digitalReleaseDate | date: 'mediumDate'} }}
-
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | date}}
+
{{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate | amLocal | amDateFormat: 'LL'} }}
+
{{ 'Requests.DigitalRelease' | translate: {date: request.digitalReleaseDate | amLocal | amDateFormat: 'LL'} }}
+
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal | amDateFormat: 'LL'}}

diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index f6ad4bb2a..caa1ca2d6 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -97,8 +97,8 @@
-
{{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | date: 'mediumDate'} }}
-
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | date: 'mediumDate'}}
+
{{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | amLocal | amDateFormat: 'LL'} }}
+
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal | amDateFormat: 'LL'}}

+ + {{u.lastLoggedIn | amLocal | amDateFormat: 'l LT'}} + + + Not logged in yet! + + Local User From 293aa8823457c6acd79c07aca659fa647a73699d Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Sat, 6 Oct 2018 23:09:02 +1300 Subject: [PATCH 036/325] Hides Sonarr options on tv requests page if only 1 option available. --- src/Ombi/ClientApp/app/requests/tvrequests.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/app/requests/tvrequests.component.html index e4d10d72e..801998c71 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.html @@ -50,7 +50,7 @@ View
-
+
@@ -66,7 +66,7 @@
-
+
From f8cda54002a33f5e37a3a902b14b4e25f4aa8bd5 Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Sat, 6 Oct 2018 23:30:32 +1300 Subject: [PATCH 037/325] Hides Radarr options on movie requests page if only 1 option available. --- src/Ombi/ClientApp/app/requests/movierequests.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 6167fbac0..05d0ca14f 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -129,7 +129,7 @@ -
+
@@ -145,7 +145,7 @@
-
+
From 42eb5ca9117bc801575fddafea0f4028d560648b Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Sun, 7 Oct 2018 02:06:30 +1300 Subject: [PATCH 038/325] Changes language selector to always show native language name. --- src/Ombi/ClientApp/app/app.component.html | 22 +++++++++++----------- src/Ombi/wwwroot/translations/da.json | 13 ------------- src/Ombi/wwwroot/translations/de.json | 13 ------------- src/Ombi/wwwroot/translations/en.json | 13 ------------- src/Ombi/wwwroot/translations/es.json | 13 ------------- src/Ombi/wwwroot/translations/fr.json | 13 ------------- src/Ombi/wwwroot/translations/it.json | 13 ------------- src/Ombi/wwwroot/translations/nl.json | 13 ------------- src/Ombi/wwwroot/translations/no.json | 13 ------------- src/Ombi/wwwroot/translations/pl.json | 13 ------------- src/Ombi/wwwroot/translations/pt.json | 13 ------------- src/Ombi/wwwroot/translations/sv.json | 13 ------------- 12 files changed, 11 insertions(+), 154 deletions(-) diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index 953e2a9a2..d695ac61c 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -117,37 +117,37 @@ diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 0229b3603..7786d69ad 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -57,19 +57,6 @@ "Welcome": "Velkommen til {{username}}", "UpdateDetails": "Opdater loginoplysninger", "Logout": "Log af", - "Language": { - "English": "Engelsk", - "French": "Fransk", - "Spanish": "Spansk", - "German": "Tysk", - "Italian": "Italiensk", - "Danish": "Dansk", - "Dutch": "Hollandsk", - "Norwegian": "Norsk", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Åbn mobilapp", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index c3646221d..2dccedb1f 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -57,19 +57,6 @@ "Welcome": "Willkommen {{username}}", "UpdateDetails": "Update-Details", "Logout": "Ausloggen", - "Language": { - "English": "Englisch", - "French": "Französisch", - "Spanish": "Spanisch", - "German": "Deutsch", - "Italian": "Italienisch", - "Danish": "Dänisch", - "Dutch": "Niederländisch", - "Norwegian": "Norwegisch", - "BrazillianPortuguese": "Portugiesisch (Brasilien)", - "Polish": "Polnisch", - "Swedish": "Schwedisch" - }, "OpenMobileApp": "Mobile App", "RecentlyAdded": "Kürzlich hinzugefügt" }, diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 93f6c39f0..2d6d81e94 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -60,19 +60,6 @@ "Welcome": "Welcome {{username}}", "UpdateDetails": "Update Details", "Logout": "Logout", - "Language": { - "English": "English", - "French": "French", - "Spanish": "Spanish", - "German": "German", - "Italian": "Italian", - "Danish": "Danish", - "Dutch": "Dutch", - "Norwegian":"Norwegian", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish":"Polish", - "Swedish":"Swedish" - }, "OpenMobileApp":"Open Mobile App", "RecentlyAdded":"Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index dc7637e79..a9f8c2b5e 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -57,19 +57,6 @@ "Welcome": "Bienvenido {{username}}", "UpdateDetails": "Detalles de la actualización", "Logout": "Cerrar sesión", - "Language": { - "English": "Inglés", - "French": "Francés", - "Spanish": "Español", - "German": "Alemán", - "Italian": "Italiano", - "Danish": "Danés", - "Dutch": "Holandés", - "Norwegian": "Norwegian", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Open Mobile App", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index c20dffdb0..bf6e26a93 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -57,19 +57,6 @@ "Welcome": "Bienvenue {{username}}", "UpdateDetails": "Détails de la mise à jour", "Logout": "Déconnexion", - "Language": { - "English": "Anglais", - "French": "Français", - "Spanish": "Espagnol", - "German": "Allemand", - "Italian": "Italien", - "Danish": "Danois", - "Dutch": "Néerlandais", - "Norwegian": "Norvégien", - "BrazillianPortuguese": "Portuguais brésilien", - "Polish": "Polonais", - "Swedish": "Swedish" - }, "OpenMobileApp": "Ouvrir l'application mobile", "RecentlyAdded": "Ajouts récents" }, diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 0ade93919..bfa026be0 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -57,19 +57,6 @@ "Welcome": "Benvenuto {{username}}", "UpdateDetails": "Aggiorna i tuoi dati", "Logout": "Logout", - "Language": { - "English": "Inglese", - "French": "Francese", - "Spanish": "Spagnolo", - "German": "Tedesco", - "Italian": "Italiano", - "Danish": "Danese", - "Dutch": "Olandese", - "Norwegian": "Norvegese", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Apri l'applicazione mobile", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 18a1d319d..24ce67966 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -57,19 +57,6 @@ "Welcome": "Welkom {{username}}", "UpdateDetails": "Update gegevens", "Logout": "Logout", - "Language": { - "English": "Engels", - "French": "Frans", - "Spanish": "Spaans", - "German": "Duits", - "Italian": "Italiaans", - "Danish": "Deens", - "Dutch": "Nederlands", - "Norwegian": "Noors", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Open Mobiele App", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 80cd9e31a..6f84943a8 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -57,19 +57,6 @@ "Welcome": "Velkommen {{username}}", "UpdateDetails": "Oppdater detaljer", "Logout": "Logg av", - "Language": { - "English": "Engelsk", - "French": "Fransk", - "Spanish": "Spansk", - "German": "Tysk", - "Italian": "Italiensk", - "Danish": "Dansk", - "Dutch": "Nederlandsk", - "Norwegian": "Norsk", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Åpne mobilapp", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 3aba4da41..b53f7f1c1 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -57,19 +57,6 @@ "Welcome": "Witaj {{username}}", "UpdateDetails": "Podaj szczegóły", "Logout": "Wyloguj", - "Language": { - "English": "Angielski", - "French": "Francuski", - "Spanish": "Hiszpański", - "German": "Niemiecki", - "Italian": "Włoski", - "Danish": "Duński", - "Dutch": "Holenderski", - "Norwegian": "Norweski", - "BrazillianPortuguese": "Brazylijski portugalski", - "Polish": "Polski", - "Swedish": "Swedish" - }, "OpenMobileApp": "Otwórz aplikację mobilną", "RecentlyAdded": "Ostatnio dodane" }, diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index eaf45cac9..199f06593 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -57,19 +57,6 @@ "Welcome": "Bem-vindo, {{username}}", "UpdateDetails": "Detalhes da Atualização", "Logout": "Sair", - "Language": { - "English": "Inglês", - "French": "Francês", - "Spanish": "Espanhol", - "German": "Alemão", - "Italian": "Italiano", - "Danish": "Dinamarquês", - "Dutch": "Holandês", - "Norwegian": "Norueguês", - "BrazillianPortuguese": "Português (Brasil)", - "Polish": "Polonês", - "Swedish": "Swedish" - }, "OpenMobileApp": "Abrir aplicativo do celular", "RecentlyAdded": "Recentemente adicionado" }, diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 8d2e8374a..6da35d413 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -57,19 +57,6 @@ "Welcome": "Välkommen {{username}}", "UpdateDetails": "Uppdatera information", "Logout": "Logga ut", - "Language": { - "English": "Engelska", - "French": "Franska", - "Spanish": "Spanska", - "German": "Tyska", - "Italian": "Italienska", - "Danish": "Danska", - "Dutch": "Holländska", - "Norwegian": "Norska", - "BrazillianPortuguese": "Brazillian portugisiska", - "Polish": "Polska", - "Swedish": "Swedish" - }, "OpenMobileApp": "Öppna Mobil App", "RecentlyAdded": "Nyligen tillagda" }, From dcab7773be13fcb78b168666d76087ec3840ed44 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 20:51:30 +0100 Subject: [PATCH 039/325] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 70 +++++++++++++-------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 0229b3603..b60fb6c7e 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -12,8 +12,8 @@ "Common": { "ContinueButton": "Fortsæt", "Available": "Tilgængelig", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", + "PartiallyAvailable": "Delvist tilgængelig", + "Monitored": "Overvåget", "NotAvailable": "Ikke tilgængelig", "ProcessingRequest": "Behandler anmodning", "PendingApproval": "Afventer godkendelse", @@ -48,7 +48,7 @@ "Requests": "Anmodninger", "UserManagement": "Brugeradministration", "Issues": "Problemer", - "Vote": "Vote", + "Vote": "Stem", "Donate": "Donér!", "DonateLibraryMaintainer": "Donér til vedligeholder af bibliotek", "DonateTooltip": "Sådan overbeviser jeg min kone om, at jeg skal bruge min fritid på at udvikle Ombi :)", @@ -66,27 +66,27 @@ "Danish": "Dansk", "Dutch": "Hollandsk", "Norwegian": "Norsk", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" + "BrazillianPortuguese": "Brasiliansk portugisisk", + "Polish": "Polsk", + "Swedish": "Svensk" }, "OpenMobileApp": "Åbn mobilapp", - "RecentlyAdded": "Recently Added" + "RecentlyAdded": "Senest tilføjet" }, "Search": { "Title": "Søg", "Paragraph": "Ønsker du at se noget, som er utilgængeligt? intet problem, bare søg efter det nedenfor og anmod om det!", "MoviesTab": "Film", "TvTab": "Tv-serier", - "MusicTab": "Music", + "MusicTab": "Musik", "Suggestions": "Forslag", "NoResults": "Beklager, vi fandt ingen resultater!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", + "DigitalDate": "Digital udgivelse: {{date}}", + "TheatricalRelease": "Biografudgivelse: {{date}}", "ViewOnPlex": "Se på Plex", "ViewOnEmby": "Se på Emby", "RequestAdded": "{{title}} er anmodet med succes", - "Similar": "Similar", + "Similar": "Lignende", "Movies": { "PopularMovies": "Populære film", "UpcomingMovies": "Kommende film", @@ -116,15 +116,15 @@ "Paragraph": "Herunder kan du se dine og alle andre anmodninger, samt status for download og godkendelse.", "MoviesTab": "Film", "TvTab": "Tv-serier", - "MusicTab": "Music", + "MusicTab": "Musik", "RequestedBy": "Anmodet af:", "Status": "Status:", "RequestStatus": "Status for anmodning:", "Denied": " Afvist:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", + "TheatricalRelease": "Biografudgivelse: {{date}}", + "ReleaseDate": "Udgivet: {{date}}", + "TheatricalReleaseSort": "Biografudgivelse", + "DigitalRelease": "Digital udgivelse: {{date}}", "RequestDate": "Dato for anmodning:", "QualityOverride": "Tilsidesæt kvalitet:", "RootFolderOverride": "Tilsidesæt rodmappe:", @@ -140,20 +140,20 @@ "GridStatus": "Status", "ReportIssue": "Rapportér problem", "Filter": "Filter", - "Sort": "Sort", + "Sort": "Sorter", "SeasonNumberHeading": "Sæson: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", + "SortRequestDateAsc": "Dato for anmodning ▲", + "SortRequestDateDesc": "Dato for anmodning ▼", "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Quota": "{{remaining}}/{{total}} anmodninger, der er tilbage", + "NextDays": "En anden anmodning vil blive tilføjet i {{time}} Dage", + "NextHours": "En anden anmodning vil blive tilføjet i {{time}} Timer", + "NextMinutes": "En anden anmodning vil blive tilføjet i {{time}} Minutter", + "NextMinute": "En anden anmodning vil blive tilføjet i {{time}} Minut" } }, "Issues": { @@ -180,18 +180,18 @@ "FilterHeaderAvailability": "Tilgængelighed", "FilterHeaderRequestStatus": "Status", "Approved": "Godkendt", - "PendingApproval": "Pending Approval" + "PendingApproval": "Afventer godkendelse" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "TvRemaining": "Tv: {{remaining}}/{{total}} Resterende", + "MovieRemaining": "Film: {{remaining}}/{{total}} Resterende", + "MusicRemaining": "Musik: {{remaining}}/{{total}} Resterende", + "TvDue": "Tv: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Musik: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Stemt", + "VotesTab": "Nødvendige stemmer" } } \ No newline at end of file From 12d37511eef4c7c30e4d6358cad7ee116c2e67d7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 20:55:38 +0100 Subject: [PATCH 040/325] Potentially fix the user profiles issue --- .../Controllers/External/RadarrController.cs | 34 ++++++++----------- .../Controllers/External/SonarrController.cs | 1 + 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/Ombi/Controllers/External/RadarrController.cs b/src/Ombi/Controllers/External/RadarrController.cs index 128b1a9e2..882f55283 100644 --- a/src/Ombi/Controllers/External/RadarrController.cs +++ b/src/Ombi/Controllers/External/RadarrController.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Caching.Memory; using Ombi.Api.Radarr; using Ombi.Api.Radarr.Models; using Ombi.Attributes; @@ -13,9 +12,9 @@ using Ombi.Settings.Settings.Models.External; namespace Ombi.Controllers.External { - [Authorize] - [ApiV1] - [Produces("application/json")] + [Authorize] + [ApiV1] + [Produces("application/json")] public class RadarrController : Controller { public RadarrController(IRadarrApi radarr, ISettingsService settings, @@ -24,6 +23,7 @@ namespace Ombi.Controllers.External RadarrApi = radarr; RadarrSettings = settings; Cache = mem; + RadarrSettings.ClearCache(); } private IRadarrApi RadarrApi { get; } @@ -61,15 +61,12 @@ namespace Ombi.Controllers.External [HttpGet("Profiles")] public async Task> GetProfiles() { - return await Cache.GetOrAdd(CacheKeys.RadarrQualityProfiles, async () => + var settings = await RadarrSettings.GetSettingsAsync(); + if (settings.Enabled) { - var settings = await RadarrSettings.GetSettingsAsync(); - if (settings.Enabled) - { - return await RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri); - } - return null; - }, DateTime.Now.AddHours(1)); + return await RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri); + } + return null; } /// @@ -80,15 +77,12 @@ namespace Ombi.Controllers.External [HttpGet("RootFolders")] public async Task> GetRootFolders() { - return await Cache.GetOrAdd(CacheKeys.RadarrRootProfiles, async () => + var settings = await RadarrSettings.GetSettingsAsync(); + if (settings.Enabled) { - var settings = await RadarrSettings.GetSettingsAsync(); - if (settings.Enabled) - { - return await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); - } - return null; - }, DateTime.Now.AddHours(1)); + return await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); + } + return null; } } } \ No newline at end of file diff --git a/src/Ombi/Controllers/External/SonarrController.cs b/src/Ombi/Controllers/External/SonarrController.cs index 94d1e3edf..a1e90e96f 100644 --- a/src/Ombi/Controllers/External/SonarrController.cs +++ b/src/Ombi/Controllers/External/SonarrController.cs @@ -20,6 +20,7 @@ namespace Ombi.Controllers.External { SonarrApi = sonarr; SonarrSettings = settings; + SonarrSettings.ClearCache(); } private ISonarrApi SonarrApi { get; } From 8bb3b1888d2b8a6f98f0f6e797c33b18267c50db Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 20:57:03 +0100 Subject: [PATCH 041/325] !wip poweruser --- src/Ombi/Controllers/External/RadarrController.cs | 2 ++ src/Ombi/Controllers/External/SonarrController.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Ombi/Controllers/External/RadarrController.cs b/src/Ombi/Controllers/External/RadarrController.cs index 882f55283..623322704 100644 --- a/src/Ombi/Controllers/External/RadarrController.cs +++ b/src/Ombi/Controllers/External/RadarrController.cs @@ -59,6 +59,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("Profiles")] + [PowerUser] public async Task> GetProfiles() { var settings = await RadarrSettings.GetSettingsAsync(); @@ -75,6 +76,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("RootFolders")] + [PowerUser] public async Task> GetRootFolders() { var settings = await RadarrSettings.GetSettingsAsync(); diff --git a/src/Ombi/Controllers/External/SonarrController.cs b/src/Ombi/Controllers/External/SonarrController.cs index a1e90e96f..c3401736d 100644 --- a/src/Ombi/Controllers/External/SonarrController.cs +++ b/src/Ombi/Controllers/External/SonarrController.cs @@ -55,6 +55,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("Profiles")] + [PowerUser] public async Task> GetProfiles() { var settings = await SonarrSettings.GetSettingsAsync(); @@ -70,6 +71,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("RootFolders")] + [PowerUser] public async Task> GetRootFolders() { var settings = await SonarrSettings.GetSettingsAsync(); From 7763ecca4f844cffc7bd840754c22570cf6b059c Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:24 +0100 Subject: [PATCH 042/325] Fixed lidarr newsletter bug --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 9f5e58482..88125b7c6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -98,7 +98,7 @@ namespace Ombi.Schedule.Jobs.Ombi // Get the Content var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); - var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking(); + var lidarrContent = _lidarrAlbumRepository.GetAll().Where(x => x.FullyAvailable).AsNoTracking(); var addedLog = _recentlyAddedLog.GetAll(); var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); From 730bb52e01d0096de5f9c270346d1fe8bd25b33c Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:30 +0100 Subject: [PATCH 043/325] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index b60fb6c7e..05214732e 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -57,19 +57,6 @@ "Welcome": "Velkommen til {{username}}", "UpdateDetails": "Opdater loginoplysninger", "Logout": "Log af", - "Language": { - "English": "Engelsk", - "French": "Fransk", - "Spanish": "Spansk", - "German": "Tysk", - "Italian": "Italiensk", - "Danish": "Dansk", - "Dutch": "Hollandsk", - "Norwegian": "Norsk", - "BrazillianPortuguese": "Brasiliansk portugisisk", - "Polish": "Polsk", - "Swedish": "Svensk" - }, "OpenMobileApp": "Åbn mobilapp", "RecentlyAdded": "Senest tilføjet" }, From 20fa3813a86fa2719e28f7e5dfb0f7e2da152502 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:31 +0100 Subject: [PATCH 044/325] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 18a1d319d..24ce67966 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -57,19 +57,6 @@ "Welcome": "Welkom {{username}}", "UpdateDetails": "Update gegevens", "Logout": "Logout", - "Language": { - "English": "Engels", - "French": "Frans", - "Spanish": "Spaans", - "German": "Duits", - "Italian": "Italiaans", - "Danish": "Deens", - "Dutch": "Nederlands", - "Norwegian": "Noors", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Open Mobiele App", "RecentlyAdded": "Recently Added" }, From eed92e7ed5524aca926ff70ba0a0476a436a2d12 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:32 +0100 Subject: [PATCH 045/325] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index c20dffdb0..bf6e26a93 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -57,19 +57,6 @@ "Welcome": "Bienvenue {{username}}", "UpdateDetails": "Détails de la mise à jour", "Logout": "Déconnexion", - "Language": { - "English": "Anglais", - "French": "Français", - "Spanish": "Espagnol", - "German": "Allemand", - "Italian": "Italien", - "Danish": "Danois", - "Dutch": "Néerlandais", - "Norwegian": "Norvégien", - "BrazillianPortuguese": "Portuguais brésilien", - "Polish": "Polonais", - "Swedish": "Swedish" - }, "OpenMobileApp": "Ouvrir l'application mobile", "RecentlyAdded": "Ajouts récents" }, From b5df13aaeba24501276fa30e569d978dda377a99 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:34 +0100 Subject: [PATCH 046/325] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index c3646221d..2dccedb1f 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -57,19 +57,6 @@ "Welcome": "Willkommen {{username}}", "UpdateDetails": "Update-Details", "Logout": "Ausloggen", - "Language": { - "English": "Englisch", - "French": "Französisch", - "Spanish": "Spanisch", - "German": "Deutsch", - "Italian": "Italienisch", - "Danish": "Dänisch", - "Dutch": "Niederländisch", - "Norwegian": "Norwegisch", - "BrazillianPortuguese": "Portugiesisch (Brasilien)", - "Polish": "Polnisch", - "Swedish": "Schwedisch" - }, "OpenMobileApp": "Mobile App", "RecentlyAdded": "Kürzlich hinzugefügt" }, From c89b02a89f7e364661cf7b1dbae8250eb8900b7d Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:35 +0100 Subject: [PATCH 047/325] New translations en.json (Italian) --- src/Ombi/wwwroot/translations/it.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 0ade93919..bfa026be0 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -57,19 +57,6 @@ "Welcome": "Benvenuto {{username}}", "UpdateDetails": "Aggiorna i tuoi dati", "Logout": "Logout", - "Language": { - "English": "Inglese", - "French": "Francese", - "Spanish": "Spagnolo", - "German": "Tedesco", - "Italian": "Italiano", - "Danish": "Danese", - "Dutch": "Olandese", - "Norwegian": "Norvegese", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Apri l'applicazione mobile", "RecentlyAdded": "Recently Added" }, From 2e0b112a17fdf4f1f22d7db93cdcda9a23c93fc6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:36 +0100 Subject: [PATCH 048/325] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 80cd9e31a..6f84943a8 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -57,19 +57,6 @@ "Welcome": "Velkommen {{username}}", "UpdateDetails": "Oppdater detaljer", "Logout": "Logg av", - "Language": { - "English": "Engelsk", - "French": "Fransk", - "Spanish": "Spansk", - "German": "Tysk", - "Italian": "Italiensk", - "Danish": "Dansk", - "Dutch": "Nederlandsk", - "Norwegian": "Norsk", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Åpne mobilapp", "RecentlyAdded": "Recently Added" }, From bd9e5aa1057c9bd429629406e1f313c6a96fae86 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:37 +0100 Subject: [PATCH 049/325] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 3aba4da41..b53f7f1c1 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -57,19 +57,6 @@ "Welcome": "Witaj {{username}}", "UpdateDetails": "Podaj szczegóły", "Logout": "Wyloguj", - "Language": { - "English": "Angielski", - "French": "Francuski", - "Spanish": "Hiszpański", - "German": "Niemiecki", - "Italian": "Włoski", - "Danish": "Duński", - "Dutch": "Holenderski", - "Norwegian": "Norweski", - "BrazillianPortuguese": "Brazylijski portugalski", - "Polish": "Polski", - "Swedish": "Swedish" - }, "OpenMobileApp": "Otwórz aplikację mobilną", "RecentlyAdded": "Ostatnio dodane" }, From c4399b2915ac4b8e73391333601f679de6615c12 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:39 +0100 Subject: [PATCH 050/325] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index eaf45cac9..199f06593 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -57,19 +57,6 @@ "Welcome": "Bem-vindo, {{username}}", "UpdateDetails": "Detalhes da Atualização", "Logout": "Sair", - "Language": { - "English": "Inglês", - "French": "Francês", - "Spanish": "Espanhol", - "German": "Alemão", - "Italian": "Italiano", - "Danish": "Dinamarquês", - "Dutch": "Holandês", - "Norwegian": "Norueguês", - "BrazillianPortuguese": "Português (Brasil)", - "Polish": "Polonês", - "Swedish": "Swedish" - }, "OpenMobileApp": "Abrir aplicativo do celular", "RecentlyAdded": "Recentemente adicionado" }, From 5a15a52ffd5859c2cf60c7331e153c0371a975ca Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:40 +0100 Subject: [PATCH 051/325] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index dc7637e79..a9f8c2b5e 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -57,19 +57,6 @@ "Welcome": "Bienvenido {{username}}", "UpdateDetails": "Detalles de la actualización", "Logout": "Cerrar sesión", - "Language": { - "English": "Inglés", - "French": "Francés", - "Spanish": "Español", - "German": "Alemán", - "Italian": "Italiano", - "Danish": "Danés", - "Dutch": "Holandés", - "Norwegian": "Norwegian", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Open Mobile App", "RecentlyAdded": "Recently Added" }, From ebef2950618a9e4cbd191bcbab659f621b276d25 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:41 +0100 Subject: [PATCH 052/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 8d2e8374a..6da35d413 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -57,19 +57,6 @@ "Welcome": "Välkommen {{username}}", "UpdateDetails": "Uppdatera information", "Logout": "Logga ut", - "Language": { - "English": "Engelska", - "French": "Franska", - "Spanish": "Spanska", - "German": "Tyska", - "Italian": "Italienska", - "Danish": "Danska", - "Dutch": "Holländska", - "Norwegian": "Norska", - "BrazillianPortuguese": "Brazillian portugisiska", - "Polish": "Polska", - "Swedish": "Swedish" - }, "OpenMobileApp": "Öppna Mobil App", "RecentlyAdded": "Nyligen tillagda" }, From 324c02a58d13516d8a05ae55bdbd97021e53fe01 Mon Sep 17 00:00:00 2001 From: Anojh Date: Sun, 7 Oct 2018 15:09:05 -0700 Subject: [PATCH 053/325] users can now remove their own requests --- .../app/requests/movierequests.component.html | 13 ++++++++----- .../app/requests/movierequests.component.ts | 7 +++++++ .../app/requests/music/musicrequests.component.html | 13 ++++++++----- .../app/requests/music/musicrequests.component.ts | 7 +++++++ .../app/requests/tvrequest-children.component.html | 4 +++- .../app/requests/tvrequest-children.component.ts | 8 ++++++++ .../app/requests/tvrequests.component.html | 2 +- .../ClientApp/app/requests/tvrequests.component.ts | 2 ++ 8 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 05d0ca14f..a1dd5cadc 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -166,11 +166,7 @@
-
- -
+
+
-
- -
+
+
+
+ +
diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts index 19e941e9d..ff451e5b5 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts @@ -10,6 +10,7 @@ import { NotificationService, RequestService } from "../services"; export class TvRequestChildrenComponent { @Input() public childRequests: IChildRequests[]; @Input() public isAdmin: boolean; + @Input() public currentUser: string; @Output() public requestDeleted = new EventEmitter(); @@ -116,4 +117,11 @@ export class TvRequestChildrenComponent { this.childRequests.splice(index, 1); } } + + public isRequestUser(request: IChildRequests) { + if (request.requestedUser.userName === this.currentUser) { + return true; + } + return false; + } } diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/app/requests/tvrequests.component.html index 801998c71..7c5e13479 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.html @@ -99,7 +99,7 @@
- +

diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts index 144de0206..924fccd1f 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts @@ -20,6 +20,7 @@ export class TvRequestsComponent implements OnInit { public searchChanged = new Subject(); public searchText: string; public isAdmin: boolean; + public currentUser: string; public showChildDialogue = false; // This is for the child modal popup public selectedSeason: ITvRequests; public defaultPoster: string; @@ -48,6 +49,7 @@ export class TvRequestsComponent implements OnInit { private readonly platformLocation: PlatformLocation) { this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + this.currentUser = this.auth.claims().name; if (this.isAdmin) { this.sonarrService.getQualityProfilesWithoutSettings() .subscribe(x => this.sonarrProfiles = x); From 5e0f04a2f67a177fd25fb73dac6cb5794ea2e9da Mon Sep 17 00:00:00 2001 From: Anojh Date: Sun, 7 Oct 2018 15:28:50 -0700 Subject: [PATCH 054/325] !wip - fix lint errors --- .../app/requests/movierequests.component.ts | 13 +++++++------ .../app/requests/music/musicrequests.component.ts | 13 +++++++------ .../app/requests/tvrequest-children.component.ts | 13 +++++++------ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 950743dc4..19fc989f2 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -218,6 +218,13 @@ export class MovieRequestsComponent implements OnInit { }); } + public isRequestUser(request: IMovieRequests) { + if (request.requestedUser.userName === this.auth.claims().name) { + return true; + } + return false; + } + private filterActiveStyle(el: any) { el = el.toElement || el.relatedTarget || el.target || el.srcElement; @@ -366,10 +373,4 @@ export class MovieRequestsComponent implements OnInit { ("url(" + "https://image.tmdb.org/t/p/w1280" + req.background + ")"); } - public isRequestUser(request: IMovieRequests) { - if (request.requestedUser.userName === this.auth.claims().name) { - return true; - } - return false; - } } diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts index 360b68c27..e70d44a38 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts @@ -198,6 +198,13 @@ export class MusicRequestsComponent implements OnInit { this.loadInit(); } + public isRequestUser(request: IAlbumRequest) { + if (request.requestedUser.userName === this.auth.claims().name) { + return true; + } + return false; + } + // public subscribe(request: IAlbumRequest) { // request.subscribed = true; // this.requestService.subscribeToMovie(request.id) @@ -349,10 +356,4 @@ export class MusicRequestsComponent implements OnInit { ("url(" + req.cover + ")"); } - public isRequestUser(request: IAlbumRequest) { - if (request.requestedUser.userName === this.auth.claims().name) { - return true; - } - return false; - } } diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts index ff451e5b5..bc792a55b 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts @@ -111,6 +111,13 @@ export class TvRequestChildrenComponent { }); } + public isRequestUser(request: IChildRequests) { + if (request.requestedUser.userName === this.currentUser) { + return true; + } + return false; + } + private removeRequestFromUi(key: IChildRequests) { const index = this.childRequests.indexOf(key, 0); if (index > -1) { @@ -118,10 +125,4 @@ export class TvRequestChildrenComponent { } } - public isRequestUser(request: IChildRequests) { - if (request.requestedUser.userName === this.currentUser) { - return true; - } - return false; - } } From bfdc9b84f0867bc63d333b65a94b6ee7f06a3f70 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 8 Oct 2018 10:21:25 +0100 Subject: [PATCH 055/325] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index bf6e26a93..f7b37855e 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -12,8 +12,8 @@ "Common": { "ContinueButton": "Continuer", "Available": "Disponible", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", + "PartiallyAvailable": "Partiellement disponible", + "Monitored": "Suivi", "NotAvailable": "Non disponible", "ProcessingRequest": "En cours de traitement", "PendingApproval": "En attente d'approbation", @@ -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 !", "MoviesTab": "Films", "TvTab": "TV", - "MusicTab": "Music", + "MusicTab": "Musique", "Suggestions": "Suggestions", "NoResults": "Désolé, nous n'avons trouvé aucun résultat !", "DigitalDate": "Sortie numérique: {{date}}", @@ -103,7 +103,7 @@ "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", "TvTab": "Émissions", - "MusicTab": "Music", + "MusicTab": "Musique", "RequestedBy": "Demandé par :", "Status": "Statut :", "RequestStatus": "Statut de la demande :", From 891b12be091f426340ef1c80477cde92d2cb0a72 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 8 Oct 2018 10:30:44 +0100 Subject: [PATCH 056/325] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index f7b37855e..6da397625 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -136,11 +136,11 @@ "SortStatusAsc": "Statut ▲", "SortStatusDesc": "Statut ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Quota": "{{remaining}}/{{total}} demande(s) restante(s)", + "NextDays": "Une autre demande sera ajoutée dans {{time}} jours", + "NextHours": "Une autre demande sera ajoutée dans {{time}} heures", + "NextMinutes": "Une autre demande sera ajoutée dans {{time}} minutes", + "NextMinute": "Une autre demande sera ajoutée dans {{time}} minute" } }, "Issues": { From 5e30c50add04a14a14b993d90010b764014cbc6f Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 8 Oct 2018 10:41:01 +0100 Subject: [PATCH 057/325] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 6da397625..5f1c59ece 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -1,6 +1,6 @@ { "Login": { - "SignInButton": "Connexion", + "SignInButton": "Se connecter", "UsernamePlaceholder": "Nom d’utilisateur", "PasswordPlaceholder": "Mot de passe", "RememberMe": "Se souvenir de moi", @@ -109,7 +109,7 @@ "RequestStatus": "Statut de la demande :", "Denied": " Refusé :", "TheatricalRelease": "Sortie en salle: {{date}}", - "ReleaseDate": "Released: {{date}}", + "ReleaseDate": "Sortie : {{date}}", "TheatricalReleaseSort": "Sortie en salle", "DigitalRelease": "Sortie numérique: {{date}}", "RequestDate": "Date de la demande :", @@ -170,15 +170,15 @@ "PendingApproval": "En attente de validation" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "TvRemaining": "TV : {{remaining}}/{{total}} restant(s)", + "MovieRemaining": "Films : {{remaining}}/{{total}} restant(s)", + "MusicRemaining": "Musique : {{remaining}}/{{total}} restant(s)", + "TvDue": "TV : {{date}}", + "MovieDue": "Film : {{date}}", + "MusicDue": "Musique : {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Voté", + "VotesTab": "Votes nécessaires" } } \ No newline at end of file From 0b7d09b410b06e7df94311b674581c17ce4bcda5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 8 Oct 2018 10:50:47 +0100 Subject: [PATCH 058/325] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 5f1c59ece..013dc9865 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -37,10 +37,10 @@ "OnlineParagraph": "Le serveur média est actuellement en ligne", "PartiallyOnlineHeading": "Partiellement en ligne", "PartiallyOnlineParagraph": "Le serveur média est partiellement en ligne.", - "MultipleServersUnavailable": "Il y a {{serversUnavailable}} serveurs hors ligne sur {{totalServers}}.", - "SingleServerUnavailable": "Il y a {{serversUnavailable}} serveur hors ligne sur {{totalServers}}.", - "OfflineHeading": "Actuellement hors ligne", - "OfflineParagraph": "Le serveur média est actuellement hors ligne.", + "MultipleServersUnavailable": "Il y a {{serversUnavailable}} serveurs hors-ligne sur {{totalServers}}.", + "SingleServerUnavailable": "Il y a {{serversUnavailable}} serveur hors-ligne sur {{totalServers}}.", + "OfflineHeading": "Actuellement hors-ligne", + "OfflineParagraph": "Le serveur média est actuellement hors-ligne.", "CheckPageForUpdates": "Consultez cette page pour voir les mises à jour du site." }, "NavigationBar": { From d9e25522e16f2be5ba8a1f7b95ff330f59f7b35a Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 8 Oct 2018 14:00:52 +0100 Subject: [PATCH 059/325] Fixed the issue where we could not delete users #2558 --- .../ClientApp/app/login/login.component.html | 2 +- .../usermanagement-user.component.html | 7 +- .../usermanagement.component.html | 2 +- .../createadmin/createadmin.component.html | 2 +- .../mediaserver/mediaserver.component.html | 2 +- .../app/wizard/welcome/welcome.component.html | 2 +- src/Ombi/cypress.json | 4 + src/Ombi/cypress/fixtures/example.json | 5 + src/Ombi/cypress/integration/login.spec.js | 38 ++ .../integration/usermanagement.spec.js | 48 ++ src/Ombi/cypress/integration/wizard.spec.js | 21 + src/Ombi/cypress/plugins/index.js | 17 + src/Ombi/cypress/support/commands.js | 25 + src/Ombi/cypress/support/index.js | 20 + src/Ombi/cypress/tsconfig.json | 12 + src/Ombi/package.json | 6 +- src/Ombi/yarn.lock | 597 +++++++++++++++++- 17 files changed, 776 insertions(+), 34 deletions(-) create mode 100644 src/Ombi/cypress.json create mode 100644 src/Ombi/cypress/fixtures/example.json create mode 100644 src/Ombi/cypress/integration/login.spec.js create mode 100644 src/Ombi/cypress/integration/usermanagement.spec.js create mode 100644 src/Ombi/cypress/integration/wizard.spec.js create mode 100644 src/Ombi/cypress/plugins/index.js create mode 100644 src/Ombi/cypress/support/commands.js create mode 100644 src/Ombi/cypress/support/index.js create mode 100644 src/Ombi/cypress/tsconfig.json diff --git a/src/Ombi/ClientApp/app/login/login.component.html b/src/Ombi/ClientApp/app/login/login.component.html index bb6afc1dd..5d5032aef 100644 --- a/src/Ombi/ClientApp/app/login/login.component.html +++ b/src/Ombi/ClientApp/app/login/login.component.html @@ -33,7 +33,7 @@ include the remember me checkbox
- + diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 6f3ae63ee..1dfba95dd 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -1,5 +1,8 @@ 

Create User

User: {{user.userName}}

+ + +
@@ -65,7 +68,7 @@
- +
@@ -208,7 +211,7 @@
- +
diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 8bbc5b45a..26faac5cb 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -2,7 +2,7 @@ - +
diff --git a/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html b/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html index bdb992a6e..2a7facaa5 100644 --- a/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html +++ b/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html @@ -19,7 +19,7 @@
- +
diff --git a/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html b/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html index 0973a2ad6..e6768328e 100644 --- a/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html +++ b/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html @@ -16,7 +16,7 @@
-
diff --git a/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html b/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html index 98cca17ef..8207583b6 100644 --- a/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html +++ b/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html @@ -9,7 +9,7 @@ we are just going to run though the initial Ombi setup!
- Next + Next
diff --git a/src/Ombi/cypress.json b/src/Ombi/cypress.json new file mode 100644 index 000000000..9310964db --- /dev/null +++ b/src/Ombi/cypress.json @@ -0,0 +1,4 @@ +{ + "projectId": "gms1wj", + "baseUrl": "http://localhost:3577" +} diff --git a/src/Ombi/cypress/fixtures/example.json b/src/Ombi/cypress/fixtures/example.json new file mode 100644 index 000000000..da18d9352 --- /dev/null +++ b/src/Ombi/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} \ No newline at end of file diff --git a/src/Ombi/cypress/integration/login.spec.js b/src/Ombi/cypress/integration/login.spec.js new file mode 100644 index 000000000..92f7eface --- /dev/null +++ b/src/Ombi/cypress/integration/login.spec.js @@ -0,0 +1,38 @@ +/// + +describe('Login Page', function () { + it('Invalid Password', function () { + cy.visit('/'); + cy.contains('Sign in'); + + cy.get('#inputEmail').type('automation'); + cy.get('#inputPassword').type('incorrectpw'); + + cy.get('[data-test=signinbtn]').click(); + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains('Incorrect username') + }); + + it('Invalid Username', function () { + cy.visit('/'); + cy.contains('Sign in'); + + cy.get('#inputEmail').type('bad username'); + cy.get('#inputPassword').type('incorrectpw'); + + cy.get('[data-test=signinbtn]').click(); + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains('Incorrect username') + }); + + it('Correct Login', function () { + cy.visit('/'); + cy.contains('Sign in'); + + cy.get('#inputEmail').type('automation'); + cy.get('#inputPassword').type('password'); + + cy.get('[data-test=signinbtn]').click(); + cy.url().should('include', '/search') + }); +}) \ No newline at end of file diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js new file mode 100644 index 000000000..8c15f4593 --- /dev/null +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -0,0 +1,48 @@ +/// + +describe('User Management Page', function () { + beforeEach(function () { + cy.request({ + method: 'POST', + url: 'http://localhost:3577/api/v1/token', + body: { + username: 'automation', + password: 'password', + } + }) + .then((resp) => { + window.localStorage.setItem('id_token', resp.body.access_token) + }); + + cy.visit('/usermanagement'); + }); + + it('Loads users table', function () { + cy.contains("User Management"); + cy.contains("Add User To Ombi"); + }); + + it.only('Creates basic user', function(){ + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include','/user'); + + // Setup the form + cy.get('#username').type("user1"); + cy.get('#alias').type("alias1"); + cy.get('#emailAddress').type("user1@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("password"); + + // setup the roles + cy.contains('Roles').click() + cy.get('#labelRequestTv').click(); + cy.get('#labelRequestMovie').click(); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains('has been created successfully') + }); + +}) \ No newline at end of file diff --git a/src/Ombi/cypress/integration/wizard.spec.js b/src/Ombi/cypress/integration/wizard.spec.js new file mode 100644 index 000000000..d1487c8ca --- /dev/null +++ b/src/Ombi/cypress/integration/wizard.spec.js @@ -0,0 +1,21 @@ +describe('Wizard Setup Tests', function() { + it('Setup Wizard User', function() { + cy.visit('http://localhost:3577/'); + cy.url().should('include', '/Wizard') + + cy.get('[data-test=nextbtn]').click(); + + // Media server page + cy.contains('Please choose your media server'); + cy.get('[data-test=skipbtn]').click(); + + // Create user + cy.contains('Create the Admin account'); + cy.get('#adminUsername').type('automation'); + cy.get('#adminPassword').type('password'); + + // Submit user + cy.get('[data-test=createuserbtn]').click(); + cy.contains('Sign in'); + }) + }) \ No newline at end of file diff --git a/src/Ombi/cypress/plugins/index.js b/src/Ombi/cypress/plugins/index.js new file mode 100644 index 000000000..fd170fba6 --- /dev/null +++ b/src/Ombi/cypress/plugins/index.js @@ -0,0 +1,17 @@ +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +} diff --git a/src/Ombi/cypress/support/commands.js b/src/Ombi/cypress/support/commands.js new file mode 100644 index 000000000..c1f5a772e --- /dev/null +++ b/src/Ombi/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add("login", (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This is will overwrite an existing command -- +// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/src/Ombi/cypress/support/index.js b/src/Ombi/cypress/support/index.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/src/Ombi/cypress/support/index.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/src/Ombi/cypress/tsconfig.json b/src/Ombi/cypress/tsconfig.json new file mode 100644 index 000000000..756a92b35 --- /dev/null +++ b/src/Ombi/cypress/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "allowJs": true, + "baseUrl": "../node_modules", + "types": [ + "cypress" + ] + }, + "include": [ + "**/*.*" + ] + } \ No newline at end of file diff --git a/src/Ombi/package.json b/src/Ombi/package.json index 5fac0c31a..4c5302d6c 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -7,7 +7,8 @@ "lint": "tslint -p .", "publish": "gulp publish", "restore": "dotnet restore && yarn install", - "clean": "gulp clean" + "clean": "gulp clean", + "cypress": "cypress open" }, "dependencies": { "@angular/animations": "^6.0.7", @@ -90,5 +91,8 @@ }, "resolutions": { "@types/tapable": "1.0.0" + }, + "devDependencies": { + "cypress": "^3.1.0" } } diff --git a/src/Ombi/yarn.lock b/src/Ombi/yarn.lock index 68381bf9d..1debb9f2d 100644 --- a/src/Ombi/yarn.lock +++ b/src/Ombi/yarn.lock @@ -100,6 +100,22 @@ dependencies: url "^0.11.0" +"@cypress/listr-verbose-renderer@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +"@cypress/xvfb@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.3.tgz#6319afdcdcff7d1505daeeaa84484d0596189860" + dependencies: + debug "^3.1.0" + lodash.once "^4.1.1" + "@ng-bootstrap/ng-bootstrap@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-2.2.0.tgz#acd514e878a1412f39d50eff691095ecc0882bf3" @@ -128,20 +144,84 @@ dependencies: tslib "^1.9.0" +"@types/blob-util@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/blob-util/-/blob-util-1.3.3.tgz#adba644ae34f88e1dd9a5864c66ad651caaf628a" + +"@types/bluebird@3.5.18": + version "3.5.18" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.18.tgz#6a60435d4663e290f3709898a4f75014f279c4d6" + +"@types/chai-jquery@1.1.35": + version "1.1.35" + resolved "https://registry.yarnpkg.com/@types/chai-jquery/-/chai-jquery-1.1.35.tgz#9a8f0a39ec0851b2768a8f8c764158c2a2568d04" + dependencies: + "@types/chai" "*" + "@types/jquery" "*" + +"@types/chai@*": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.6.tgz#1eb26c040e3a84205b1008ad55c800e5e8a94e34" + +"@types/chai@4.0.8": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.8.tgz#d27600e9ba2f371e08695d90a0fe0408d89c7be7" + "@types/core-js@^2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.0.tgz#35cc282488de6f10af1d92902899a3b8ca3fbc47" +"@types/jquery@*": + version "3.3.12" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.12.tgz#e83229bcbf09dc668f9d4c1894864199521ff258" + dependencies: + "@types/sizzle" "*" + +"@types/jquery@3.2.16": + version "3.2.16" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.2.16.tgz#04419c404a3194350e7d3f339a90e72c88db3111" + +"@types/lodash@4.14.87": + version "4.14.87" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.87.tgz#55f92183b048c2c64402afe472f8333f4e319a6b" + "@types/mini-css-extract-plugin@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.2.0.tgz#afb037dbbd76f6c13803927c2751d194188b5d47" dependencies: "@types/webpack" "*" +"@types/minimatch@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + +"@types/mocha@2.2.44": + version "2.2.44" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" + "@types/node@*", "@types/node@^10.5.1": version "10.5.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.1.tgz#d578446f4abff5c0b49ade9b4e5274f6badaadfc" +"@types/sinon-chai@2.7.29": + version "2.7.29" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-2.7.29.tgz#4db01497e2dd1908b2bd30d1782f456353f5f723" + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.4.tgz#a765b390b373cf01a3b19b0c97f9eb4bb2a168b1" + +"@types/sinon@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.0.0.tgz#9a93ffa4ee1329e85166278a5ed99f81dc4c8362" + +"@types/sizzle@*": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" + "@types/tapable@*", "@types/tapable@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.0.tgz#b76254453021be05681f6213416766bac9afb99c" @@ -356,6 +436,15 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + ajv@^6.1.0: version "6.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360" @@ -400,7 +489,7 @@ ansi-cyan@^0.1.1: dependencies: ansi-wrap "0.1.0" -ansi-escapes@^1.1.0: +ansi-escapes@^1.0.0, ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -612,6 +701,12 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" +async@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611" + dependencies: + lodash "^4.14.0" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -648,10 +743,18 @@ aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + aws4@^1.2.1: version "1.7.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" +aws4@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -668,7 +771,7 @@ babel-polyfill@6.23.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-runtime@^6.22.0: +babel-runtime@^6.18.0, babel-runtime@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: @@ -731,6 +834,10 @@ block-stream@*: dependencies: inherits "~2.0.0" +bluebird@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" + bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -861,6 +968,10 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + buffer-from@^1.0.0, buffer-from@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" @@ -921,6 +1032,12 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cachedir@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-1.3.0.tgz#5e01928bf2d95b5edd94b0942188246740e0dbc4" + dependencies: + os-homedir "^1.0.1" + caller-id@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-id/-/caller-id-0.1.0.tgz#59bdac0893d12c3871408279231f97458364f07b" @@ -984,7 +1101,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1: +chalk@2.4.1, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: @@ -1000,6 +1117,10 @@ chardet@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.5.0.tgz#fe3ac73c00c3d865ffcc02a0682e2c20b6a06029" +check-more-types@2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + check-types@^7.3.0: version "7.4.0" resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" @@ -1048,6 +1169,10 @@ chrome-trace-event@^1.0.0: dependencies: tslib "^1.9.0" +ci-info@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -1076,12 +1201,29 @@ clean-css@4.1.x: dependencies: source-map "0.5.x" +cli-cursor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" dependencies: restore-cursor "^2.0.0" +cli-spinners@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" + +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -1188,12 +1330,16 @@ colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" -combined-stream@^1.0.5, combined-stream@~1.0.5: +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + commander@2.15.x, commander@~2.15.0: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" @@ -1206,6 +1352,12 @@ commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" +common-tags@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0" + dependencies: + babel-runtime "^6.18.0" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1218,6 +1370,14 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +concat-stream@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + concat-stream@^1.5.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" @@ -1345,7 +1505,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.5: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" dependencies: @@ -1475,6 +1635,51 @@ cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" +cypress@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.1.0.tgz#b718ba64289b887c7ab7a7f09245d871a4a409ba" + dependencies: + "@cypress/listr-verbose-renderer" "0.4.1" + "@cypress/xvfb" "1.2.3" + "@types/blob-util" "1.3.3" + "@types/bluebird" "3.5.18" + "@types/chai" "4.0.8" + "@types/chai-jquery" "1.1.35" + "@types/jquery" "3.2.16" + "@types/lodash" "4.14.87" + "@types/minimatch" "3.0.3" + "@types/mocha" "2.2.44" + "@types/sinon" "4.0.0" + "@types/sinon-chai" "2.7.29" + bluebird "3.5.0" + cachedir "1.3.0" + chalk "2.4.1" + check-more-types "2.24.0" + commander "2.11.0" + common-tags "1.4.0" + debug "3.1.0" + execa "0.10.0" + executable "4.1.1" + extract-zip "1.6.6" + fs-extra "4.0.1" + getos "3.1.0" + glob "7.1.2" + is-ci "1.0.10" + is-installed-globally "0.1.0" + lazy-ass "1.6.0" + listr "0.12.0" + lodash "4.17.10" + log-symbols "2.2.0" + minimist "1.2.0" + progress "1.1.8" + ramda "0.24.1" + request "2.87.0" + request-progress "0.3.1" + supports-color "5.1.0" + tmp "0.0.31" + url "0.11.0" + yauzl "2.8.0" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" @@ -1487,6 +1692,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^1.27.2: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -1501,7 +1710,7 @@ debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.1.0: +debug@3.1.0, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -1669,6 +1878,10 @@ electron-to-chromium@^1.2.7: version "1.3.50" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz#7438b76f92b41b919f3fbdd350fbd0757dacddf7" +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + elliptic@^6.0.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -1821,6 +2034,18 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +execa@0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" + dependencies: + cross-spawn "^6.0.0" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -1833,6 +2058,16 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +executable@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + dependencies: + pify "^2.2.0" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -1925,6 +2160,10 @@ extend@^3.0.0, extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + external-editor@^2.0.1: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" @@ -1960,6 +2199,15 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-zip@1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" + dependencies: + concat-stream "1.6.0" + debug "2.6.9" + mkdirp "0.5.0" + yauzl "2.4.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -1992,6 +2240,19 @@ fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + dependencies: + pend "~1.2.0" + +figures@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -2159,6 +2420,14 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -2180,6 +2449,14 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" +fs-extra@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" @@ -2270,6 +2547,12 @@ get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" +getos@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.1.0.tgz#db3aa4df15a3295557ce5e81aa9e3e5cdfaa6567" + dependencies: + async "2.4.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -2319,6 +2602,17 @@ glob2base@^0.0.12: dependencies: find-index "^0.1.1" +glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^4.3.1: version "4.5.3" resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" @@ -2338,17 +2632,6 @@ glob@^6.0.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@~3.1.21: version "3.1.21" resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" @@ -2357,6 +2640,12 @@ glob@~3.1.21: inherits "1" minimatch "~0.2.11" +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + dependencies: + ini "^1.3.4" + global-modules-path@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.1.0.tgz#923ec524e8726bb0c1a4ed4b8e21e1ff80c88bbb" @@ -2428,7 +2717,7 @@ graceful-fs@^3.0.0: dependencies: natives "^1.1.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2507,6 +2796,10 @@ har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + har-validator@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" @@ -2523,6 +2816,13 @@ har-validator@~4.2.1: ajv "^4.9.1" har-schema "^1.0.5" +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -2533,6 +2833,10 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2689,6 +2993,14 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -2752,6 +3064,10 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -2874,6 +3190,12 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-ci@1.0.10: + version "1.0.10" + resolved "http://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e" + dependencies: + ci-info "^1.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -2964,6 +3286,13 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" +is-installed-globally@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + is-my-ip-valid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" @@ -3160,6 +3489,12 @@ json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +jsonfile@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -3201,6 +3536,10 @@ kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" +lazy-ass@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -3224,6 +3563,53 @@ liftoff@^2.1.0: rechoir "^0.6.2" resolve "^1.1.7" +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + +listr-update-renderer@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz#ca80e1779b4e70266807e8eed1ad6abe398550f9" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +listr@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + figures "^1.7.0" + indent-string "^2.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.2.0" + listr-verbose-renderer "^0.4.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + ora "^0.2.3" + p-map "^1.1.1" + rxjs "^5.0.0-beta.11" + stream-to-observable "^0.1.0" + strip-ansi "^3.0.1" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -3348,6 +3734,10 @@ lodash.mergewith@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" +lodash.once@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -3394,20 +3784,37 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@^4.0.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.10: +lodash@4.17.10, lodash@^4.0.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.10: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" +lodash@^4.14.0: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + lodash@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" -log-symbols@^2.1.0: +log-symbols@2.2.0, log-symbols@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" dependencies: chalk "^2.0.1" +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + +log-update@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" + dependencies: + ansi-escapes "^1.0.0" + cli-cursor "^1.0.2" + loglevelnext@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" @@ -3584,12 +3991,22 @@ mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" +mime-db@~1.36.0: + version "1.36.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" + mime-types@^2.1.12, mime-types@~2.1.18, mime-types@~2.1.7: version "2.1.18" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: mime-db "~1.33.0" +mime-types@~2.1.17: + version "2.1.20" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" + dependencies: + mime-db "~1.36.0" + mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" @@ -3687,6 +4104,12 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" +mkdirp@0.5.0: + version "0.5.0" + resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" + dependencies: + minimist "0.0.8" + "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -3981,7 +4404,7 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -oauth-sign@~0.8.1: +oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -4067,6 +4490,10 @@ once@~1.3.0: dependencies: wrappy "1" +onetime@^1.0.0: + version "1.1.0" + resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -4095,6 +4522,15 @@ opn@4.0.2: object-assign "^4.0.1" pinkie-promise "^2.0.0" +ora@^0.2.3: + version "0.2.3" + resolved "http://registry.npmjs.org/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" + dependencies: + chalk "^1.1.1" + cli-cursor "^1.0.2" + cli-spinners "^0.1.2" + object-assign "^4.0.1" + orchestrator@^0.3.0: version "0.3.8" resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" @@ -4111,7 +4547,7 @@ os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -4129,7 +4565,7 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -4303,11 +4739,19 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" -pify@^2.0.0: +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0, pify@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -4618,6 +5062,10 @@ process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" +progress@1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" @@ -4690,6 +5138,10 @@ qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -4705,6 +5157,10 @@ querystring@0.2.0, querystring@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" +ramda@0.24.1: + version "0.24.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" + randomatic@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" @@ -4915,6 +5371,37 @@ replace-ext@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" +request-progress@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-0.3.1.tgz#0721c105d8a96ac6b2ce8b2c89ae2d5ecfcf6b3a" + dependencies: + throttleit "~0.0.2" + +request@2.87.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + "request@>=2.9.0 <2.82.0": version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -5006,6 +5493,13 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: dependencies: path-parse "^1.0.5" +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -5054,6 +5548,12 @@ rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" +rxjs@^5.0.0-beta.11: + version "5.5.12" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" + dependencies: + symbol-observable "1.0.1" + rxjs@^6.0.0, rxjs@^6.1.0, rxjs@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.1.tgz#246cebec189a6cbc143a3ef9f62d6f4c91813ca1" @@ -5237,6 +5737,10 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -5439,6 +5943,10 @@ stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" +stream-to-observable@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" + strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" @@ -5518,6 +6026,12 @@ style-loader@^0.21.0: loader-utils "^1.1.0" schema-utils "^0.4.5" +supports-color@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" + dependencies: + has-flag "^2.0.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -5546,6 +6060,10 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + tapable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" @@ -5574,6 +6092,10 @@ text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +throttleit@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" + through2@^0.6.1: version "0.6.5" resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" @@ -5608,6 +6130,12 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tmp@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -5646,7 +6174,7 @@ to-string-loader@^1.1.5: dependencies: loader-utils "^0.2.16" -tough-cookie@~2.3.0: +tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: @@ -5822,6 +6350,10 @@ unique-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -5869,7 +6401,7 @@ url-loader@^1.0.1: mime "^2.0.3" schema-utils "^0.4.3" -url@^0.11.0: +url@0.11.0, url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" dependencies: @@ -6214,6 +6746,19 @@ yargs@^7.0.0: y18n "^3.2.1" yargs-parser "^5.0.0" +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + dependencies: + fd-slicer "~1.0.1" + +yauzl@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.8.0.tgz#79450aff22b2a9c5a41ef54e02db907ccfbf9ee2" + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.0.1" + yn@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" From 8764ec3a78e6a452690528730edcf14817c61258 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 8 Oct 2018 16:11:01 +0100 Subject: [PATCH 060/325] More UI tests !wip --- .../usermanagement-user.component.html | 2 +- .../usermanagement.component.html | 2 +- src/Ombi/cypress/integration/login.spec.js | 6 +- .../integration/usermanagement.spec.js | 114 +++++++++++++++--- src/Ombi/cypress/support/commands.js | 34 ++++++ 5 files changed, 133 insertions(+), 25 deletions(-) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 1dfba95dd..c25102ba2 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -214,7 +214,7 @@
- + diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 26faac5cb..b8a89c2b3 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -129,7 +129,7 @@ Emby User - Details/Edit + Details/Edit diff --git a/src/Ombi/cypress/integration/login.spec.js b/src/Ombi/cypress/integration/login.spec.js index 92f7eface..af40f21e7 100644 --- a/src/Ombi/cypress/integration/login.spec.js +++ b/src/Ombi/cypress/integration/login.spec.js @@ -9,8 +9,7 @@ describe('Login Page', function () { cy.get('#inputPassword').type('incorrectpw'); cy.get('[data-test=signinbtn]').click(); - cy.get('.ui-growl-title').should('be.visible'); - cy.get('.ui-growl-title').next().contains('Incorrect username') + cy.verifyNotification('Incorrect username'); }); it('Invalid Username', function () { @@ -21,8 +20,7 @@ describe('Login Page', function () { cy.get('#inputPassword').type('incorrectpw'); cy.get('[data-test=signinbtn]').click(); - cy.get('.ui-growl-title').should('be.visible'); - cy.get('.ui-growl-title').next().contains('Incorrect username') + cy.verifyNotification('Incorrect username'); }); it('Correct Login', function () { diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js index 8c15f4593..866542129 100644 --- a/src/Ombi/cypress/integration/usermanagement.spec.js +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -2,18 +2,12 @@ describe('User Management Page', function () { beforeEach(function () { - cy.request({ - method: 'POST', - url: 'http://localhost:3577/api/v1/token', - body: { - username: 'automation', - password: 'password', - } - }) - .then((resp) => { - window.localStorage.setItem('id_token', resp.body.access_token) - }); - + cy.login('automation', 'password'); + cy.createUser('userToDelete', 'password', [{ + value: "requestmovie", + Enabled: "true", + }]); + cy.visit('/usermanagement'); }); @@ -22,9 +16,9 @@ describe('User Management Page', function () { cy.contains("Add User To Ombi"); }); - it.only('Creates basic user', function(){ + it('Creates basic user', function () { cy.get('[data-test=adduserbtn').click(); - cy.url().should('include','/user'); + cy.url().should('include', '/user'); // Setup the form cy.get('#username').type("user1"); @@ -40,9 +34,91 @@ describe('User Management Page', function () { // submit user cy.get('[data-test=createuserbtn]').click(); - - cy.get('.ui-growl-title').should('be.visible'); - cy.get('.ui-growl-title').next().contains('has been created successfully') + + cy.verifyNotification('has been created successfully'); + + // Also check if the user is in the table + cy.contains('alias1'); }); - -}) \ No newline at end of file + + it('Tries to create user without roles', function () { + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include', '/user'); + + // Setup the form + cy.get('#username').type("user1"); + cy.get('#alias').type("alias1"); + cy.get('#emailAddress').type("user1@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("password"); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.verifyNotification('Please assign a role'); + + }); + + it('Tries to create user when passwords do not match', function () { + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include', '/user'); + + // Setup the form + cy.get('#username').type("user1"); + cy.get('#alias').type("alias1"); + cy.get('#emailAddress').type("user1@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("pass22word"); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.verifyNotification('Passwords do not match'); + }); + + it('Delete a user', function () { + cy.get('#edituserToDelete').click(); + cy.contains('User: userToDelete'); + cy.get('[data-test=deletebtn]').click(); + cy.contains('Are you sure that you want to delete this user?'); + cy.contains('Yes').click(); + cy.verifyNotification('was deleted'); + }) + + + it.only('Creates user with request limits', function () { + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include', '/user'); + + // Setup the form + cy.get('#username').type("user2"); + cy.get('#alias').type("alias2"); + cy.get('#emailAddress').type("user2@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("password"); + + // setup the roles + cy.contains('Roles').click() + cy.get('#labelRequestMovie').click(); + + cy.contains('Request Limits').click(); + cy.get('#movieRequestLimit').clear().type(2); + cy.get('#musicRequestLimit').clear().type(3); + cy.get('#episodeRequestLimit').clear().type(4); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.verifyNotification('has been updated successfully'); + + // Verify that the limits are set + cy.get('#edituser2').click(); + cy.contains('Request Limits').click(); + cy.get('#movieRequestLimit').should('eq', 2); + cy.get('#musicRequestLimit').should('eq', 3); + cy.get('#tvRequestLimit').should('eq', 4); + + }); + + +}); \ No newline at end of file diff --git a/src/Ombi/cypress/support/commands.js b/src/Ombi/cypress/support/commands.js index c1f5a772e..cc2110b3e 100644 --- a/src/Ombi/cypress/support/commands.js +++ b/src/Ombi/cypress/support/commands.js @@ -23,3 +23,37 @@ // // -- This is will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) + +Cypress.Commands.add('login', (username, password) => { + cy.request({ + method: 'POST', + url: '/api/v1/token', + body: { + username: username, + password: password, + } + }) + .then((resp) => { + window.localStorage.setItem('id_token', resp.body.access_token) + }); +}); + +Cypress.Commands.add('createUser', (username, password, claims) => { + cy.request({ + method: 'POST', + url: '/api/v1/identity', + body: { + UserName: username, + Password: password, + Claims: claims, + }, + headers: { + 'Authorization': 'Bearer ' + window.localStorage.getItem('id_token'), + } + }) +}) + +Cypress.Commands.add('verifyNotification', (text) => { + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains(text) +}) \ No newline at end of file From 148e39489629f1ac25ccfc58c0a5add977243397 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 8 Oct 2018 22:55:57 +0100 Subject: [PATCH 061/325] Added more UI test !wip --- src/Ombi/ClientApp/app/app.component.html | 4 +- .../updatedetails.component.html | 2 +- .../usermanagement-user.component.html | 6 +- .../integration/usermanagement.spec.js | 116 ++++++++++++++---- src/Ombi/cypress/support/commands.js | 2 +- src/Ombi/cypress/tsconfig.json | 12 -- src/Ombi/tsconfig.json | 4 + 7 files changed, 106 insertions(+), 40 deletions(-) delete mode 100644 src/Ombi/cypress/tsconfig.json diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index d695ac61c..9f6d00a7e 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -94,13 +94,13 @@
- +
diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index c25102ba2..3f44a808b 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -80,7 +80,7 @@
- +
@@ -132,7 +132,7 @@
-
@@ -213,7 +213,7 @@
- + diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js index 866542129..0dcd53a6c 100644 --- a/src/Ombi/cypress/integration/usermanagement.spec.js +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -8,6 +8,11 @@ describe('User Management Page', function () { Enabled: "true", }]); + cy.createUser('userToEdit', 'password', [{ + value: "requestmovie", + Enabled: "true", + }]); + cy.visit('/usermanagement'); }); @@ -86,20 +91,8 @@ describe('User Management Page', function () { }) - it.only('Creates user with request limits', function () { - cy.get('[data-test=adduserbtn').click(); - cy.url().should('include', '/user'); - - // Setup the form - cy.get('#username').type("user2"); - cy.get('#alias').type("alias2"); - cy.get('#emailAddress').type("user2@emailaddress.com"); - cy.get('#password').type("password"); - cy.get('#confirmPass').type("password"); - - // setup the roles - cy.contains('Roles').click() - cy.get('#labelRequestMovie').click(); + it('Add request limits to a user', function () { + cy.get('#edituserToEdit').click(); cy.contains('Request Limits').click(); cy.get('#movieRequestLimit').clear().type(2); @@ -107,18 +100,99 @@ describe('User Management Page', function () { cy.get('#episodeRequestLimit').clear().type(4); // submit user - cy.get('[data-test=createuserbtn]').click(); + cy.get('[data-test=updatebtn]').click(); - cy.verifyNotification('has been updated successfully'); + cy.verifyNotification('successfully'); + + // Verify that the limits are set + cy.get('#edituserToEdit').click(); + cy.contains('Request Limits').click(); + cy.get('#movieRequestLimit').should('have.attr', 'ng-reflect-model', '2') + cy.get('#musicRequestLimit').should('have.attr', 'ng-reflect-model', '3') + cy.get('#episodeRequestLimit').should('have.attr', 'ng-reflect-model', '4') + + }); + + it('Add notification preferences to user', function () { + + cy.get('#edituserToEdit').click(); + + cy.contains('Notification Preferences').click(); + cy.get('[data-test=Discord]').clear().type("Discord"); + cy.get('[data-test=Pushbullet]').clear().type("Pushbullet"); + cy.get('[data-test=Pushover]').clear().type("Pushover"); + cy.get('[data-test=Telegram]').clear().type("Telegram"); + cy.get('[data-test=Slack]').clear().type("Slack"); + cy.get('[data-test=Mattermost]').clear().type("Mattermost"); + + // submit user + cy.get('[data-test=updatebtn]').click(); + + cy.verifyNotification('successfully'); + + // Verify that the limits are set + cy.get('#edituserToEdit').click(); + cy.contains('Notification Preferences').click(); + cy.get('[data-test=Discord]').should('have.attr', 'ng-reflect-model', "Discord"); + cy.get('[data-test=Pushbullet]').should('have.attr', 'ng-reflect-model', "Pushbullet"); + cy.get('[data-test=Pushover]').should('have.attr', 'ng-reflect-model', "Pushover"); + cy.get('[data-test=Telegram]').should('have.attr', 'ng-reflect-model', "Telegram"); + cy.get('[data-test=Slack]').should('have.attr', 'ng-reflect-model', "Slack"); + cy.get('[data-test=Mattermost]').should('have.attr', 'ng-reflect-model', "Mattermost"); + + }); + + it('Modify roles', function () { + + cy.get('#edituserToEdit').click(); + + cy.contains('Roles').click(); + cy.get('#labelRequestMovie').click(); + cy.get('#labelRequestTv').click(); + + // submit user + cy.get('[data-test=updatebtn]').click(); + + cy.verifyNotification('successfully'); // Verify that the limits are set - cy.get('#edituser2').click(); - cy.contains('Request Limits').click(); - cy.get('#movieRequestLimit').should('eq', 2); - cy.get('#musicRequestLimit').should('eq', 3); - cy.get('#tvRequestLimit').should('eq', 4); + cy.get('#edituserToEdit').click(); + cy.contains('Roles').click(); + cy.get('#createRequestMovie').should('have.attr', 'ng-reflect-model', 'true'); + cy.get('#createRequestTv').should('have.attr', 'ng-reflect-model', 'true'); + cy.get('#createDisabled').should('have.attr', 'ng-reflect-model', 'false'); }); + it('Update local users info', function () { + + cy.get('#userDropdown').click(); + cy.get('#updateUserDetails').click(); + + cy.url().should('include','/updatedetails'); + + cy.get('#emailAddress').clear().type("user11@emailaddress.com"); + cy.get('#currentPassword').type("password"); + + cy.get('[data-test=submitbtn]').click(); + + cy.verifyNotification('All of your details have now been updated'); + }); + + it('Update local users info with bad password', function () { + + cy.get('#userDropdown').click(); + cy.get('#updateUserDetails').click(); + + cy.url().should('include','/updatedetails'); + + cy.get('#emailAddress').clear().type("user11@emailaddress.com"); + cy.get('#currentPassword').type("password32113123123"); + + cy.get('[data-test=submitbtn]').click(); + + cy.verifyNotification('Your password is incorrect'); + }); + }); \ No newline at end of file diff --git a/src/Ombi/cypress/support/commands.js b/src/Ombi/cypress/support/commands.js index cc2110b3e..b44a1e2b5 100644 --- a/src/Ombi/cypress/support/commands.js +++ b/src/Ombi/cypress/support/commands.js @@ -56,4 +56,4 @@ Cypress.Commands.add('createUser', (username, password, claims) => { Cypress.Commands.add('verifyNotification', (text) => { cy.get('.ui-growl-title').should('be.visible'); cy.get('.ui-growl-title').next().contains(text) -}) \ No newline at end of file +}); diff --git a/src/Ombi/cypress/tsconfig.json b/src/Ombi/cypress/tsconfig.json deleted file mode 100644 index 756a92b35..000000000 --- a/src/Ombi/cypress/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "baseUrl": "../node_modules", - "types": [ - "cypress" - ] - }, - "include": [ - "**/*.*" - ] - } \ No newline at end of file diff --git a/src/Ombi/tsconfig.json b/src/Ombi/tsconfig.json index 1256bed93..bd114dcdb 100644 --- a/src/Ombi/tsconfig.json +++ b/src/Ombi/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "target": "es5", "lib": [ + "es2015", "es2017", "dom" ], @@ -27,6 +28,9 @@ } ] }, + "types": [ + "cypress" + ], "include": [ "ClientApp/**/*", "typings/**/*", From 0b2b3d2f30d24d6e8a012ba352d95701c9306c2b Mon Sep 17 00:00:00 2001 From: Anojh Date: Tue, 9 Oct 2018 00:26:31 -0700 Subject: [PATCH 062/325] New role to enable users to remove their own requests --- src/Ombi.Helpers/OmbiRoles.cs | 1 + src/Ombi.Store/Context/OmbiContext.cs | 10 ++++++++++ src/Ombi/Attributes/UserAttribute.cs | 14 ++++++++++++++ .../requests/music/musicrequests.component.html | 2 +- src/Ombi/Controllers/IdentityController.cs | 1 + src/Ombi/Controllers/MusicRequestController.cs | 2 +- src/Ombi/Controllers/RequestController.cs | 6 +++--- 7 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 src/Ombi/Attributes/UserAttribute.cs diff --git a/src/Ombi.Helpers/OmbiRoles.cs b/src/Ombi.Helpers/OmbiRoles.cs index 1d584d57f..e0cfc5398 100644 --- a/src/Ombi.Helpers/OmbiRoles.cs +++ b/src/Ombi.Helpers/OmbiRoles.cs @@ -14,5 +14,6 @@ public const string RequestMusic = nameof(RequestMusic); public const string Disabled = nameof(Disabled); public const string ReceivesNewsletter = nameof(ReceivesNewsletter); + public const string ManageOwnRequests = nameof(ManageOwnRequests); } } \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 66631dfc6..54682e24e 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -145,6 +145,16 @@ namespace Ombi.Store.Context 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 var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); if (!apiUserExists) diff --git a/src/Ombi/Attributes/UserAttribute.cs b/src/Ombi/Attributes/UserAttribute.cs new file mode 100644 index 000000000..3ab4cef49 --- /dev/null +++ b/src/Ombi/Attributes/UserAttribute.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Authorization; +using Ombi.Helpers; + + +namespace Ombi.Attributes +{ + public class UserAttribute : AuthorizeAttribute + { + public UserAttribute() + { + Roles = "ManageOwnRequests"; + } + } +} diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index 28734f5a3..c4c903da2 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -186,7 +186,7 @@
-
+ diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index d138e973e..61b3f06d8 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -240,6 +240,7 @@ namespace Ombi.Controllers await CreateRole(OmbiRoles.RequestTv); await CreateRole(OmbiRoles.Disabled); await CreateRole(OmbiRoles.ReceivesNewsletter); + await CreateRole(OmbiRoles.ManageOwnRequests); } private async Task CreateRole(string role) diff --git a/src/Ombi/Controllers/MusicRequestController.cs b/src/Ombi/Controllers/MusicRequestController.cs index 0d763cd86..3ab99dc0f 100644 --- a/src/Ombi/Controllers/MusicRequestController.cs +++ b/src/Ombi/Controllers/MusicRequestController.cs @@ -88,7 +88,7 @@ namespace Ombi.Controllers /// The request identifier. /// [HttpDelete("{requestId:int}")] - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] public async Task DeleteRequest(int requestId) { await _engine.RemoveAlbumRequest(requestId); diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index 25270f9dd..a1a61c9f9 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -95,7 +95,7 @@ namespace Ombi.Controllers /// The request identifier. /// [HttpDelete("movie/{requestId:int}")] - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] public async Task DeleteRequest(int requestId) { await MovieRequestEngine.RemoveMovieRequest(requestId); @@ -269,7 +269,7 @@ namespace Ombi.Controllers /// The request identifier. /// [HttpDelete("tv/{requestId:int}")] - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] public async Task DeleteTvRequest(int requestId) { await TvRequestEngine.RemoveTvRequest(requestId); @@ -380,7 +380,7 @@ namespace Ombi.Controllers /// /// The model. /// - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] [HttpDelete("tv/child/{requestId:int}")] public async Task DeleteChildRequest(int requestId) { From 8ad54a9402480870fb3ada353d324dcd8035c34a Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 9 Oct 2018 15:58:33 +0100 Subject: [PATCH 063/325] !wip changelog --- CHANGELOG.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 655689bec..084805f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,79 @@ ## (unreleased) +### **New Features** + +- Changes language selector to always show native language name. [Victor Usoltsev] + +- Updated test dependancies. [TidusJar] + +- Added the ability to purge/remove issues. [TidusJar] + +### **Fixes** + +- Users can now remove their own requests. [Anojh] + +- New translations en.json (Danish) [Jamie] + +- Fixed lidarr newsletter bug. [Jamie] + +- Potentially fix the user profiles issue. [Jamie] + +- Hides Radarr options on movie requests page if only 1 option available. [Victor Usoltsev] + +- Hides Sonarr options on tv requests page if only 1 option available. [Victor Usoltsev] + +- Fixed the issue where we could not delete users #2558. [TidusJar] + +- New translations en.json (German) [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] + +- Subscribe the user to the request when they vote on it. [TidusJar] + +- Fixed #2555. [Jamie] + +- Fixed #2549. [Jamie] + +- Removed the pinID from the OAuth url #2548. [Jamie] + +- Put the issue purge limit on the issues page. [Jamie] + +- Date and times are now in the local users date time. [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] + +- Truncate the request title. [Jamie] + +- Fixed #2535. [Jamie] + + +## v3.0.3795 (2018-09-23) + +### **New Features** + +- Update CHANGELOG.md. [Jamie] + ### **Fixes** - Fixed the issue with notifications not sending. [Jamie] From 7e49366999b42989ba04476d2b5a10a89536008f Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 19:30:58 +0100 Subject: [PATCH 064/325] !wip --- src/Ombi/cypress/integration/usermanagement.spec.js | 2 +- src/Ombi/package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js index 866542129..3e6b83e28 100644 --- a/src/Ombi/cypress/integration/usermanagement.spec.js +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -109,7 +109,7 @@ describe('User Management Page', function () { // submit user cy.get('[data-test=createuserbtn]').click(); - cy.verifyNotification('has been updated successfully'); + cy.verifyNotification('has been created successfully'); // Verify that the limits are set cy.get('#edituser2').click(); diff --git a/src/Ombi/package.json b/src/Ombi/package.json index 4c5302d6c..ceb7fc621 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "vendor": "gulp vendor", + "main": "gulp main", "lint": "tslint -p .", "publish": "gulp publish", "restore": "dotnet restore && yarn install", From 65233cb3b7ded3fcdbc2436eaa8fe312407c4de9 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:01:46 +0100 Subject: [PATCH 065/325] Fixed the issue where user preferences was not being inported into some notifications --- src/Ombi.Notifications/BaseNotification.cs | 20 ++++++++++++++++++- .../NotificationMessageCurlys.cs | 3 ++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index d351c8283..53d6d5d9d 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -170,6 +170,24 @@ namespace Ombi.Notifications.Interfaces { 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); return parsed; @@ -184,7 +202,7 @@ namespace Ombi.Notifications.Interfaces protected UserNotificationPreferences GetUserPreference(string userId, NotificationAgent agent) { 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) diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 1b655b84d..b178f0545 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -19,7 +19,7 @@ namespace Ombi.Notifications LoadIssues(opts); if (pref != null) { - UserPreference = pref.Enabled ? pref.Value : string.Empty; + UserPreference = pref.Value; } string title; @@ -268,6 +268,7 @@ namespace Ombi.Notifications {nameof(IssueUser),IssueUser}, {nameof(UserName),UserName}, {nameof(Alias),Alias}, + {nameof(UserPreference),UserPreference}, }; } } \ No newline at end of file From 2fc0ab5fa8c632603943b45b449f3f610be59b82 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:05:43 +0100 Subject: [PATCH 066/325] updated typescript !wip --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 862993a21..2d18fdcbb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,6 +3,7 @@ configuration: Release os: Visual Studio 2017 environment: nodejs_version: "9.8.0" + typescript_version: "3.0.1" install: # Get the latest stable version of Node.js or io.js From 48705f2ea09d744d001ffab07a1c9eef78557a5d Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:20:06 +0100 Subject: [PATCH 067/325] another change !wip --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 2d18fdcbb..d8265e6f6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,6 +8,9 @@ environment: install: # Get the latest stable version of Node.js or io.js - ps: Install-Product node $env:nodejs_version + + - cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\2.2;%path% + - cmd: tsc -v build_script: - ps: ./build.ps1 --settings_skipverification=true From 873c0d7da750fa45c8bbb9304ad6ec7105f1807b Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:24:42 +0100 Subject: [PATCH 068/325] tsc to ver 3.0.1 !wip --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index d8265e6f6..d22d50f67 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,7 @@ install: # Get the latest stable version of Node.js or io.js - ps: Install-Product node $env:nodejs_version - - cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\2.2;%path% + - cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\3.0.1;%path% - cmd: tsc -v build_script: - ps: ./build.ps1 --settings_skipverification=true From 9f933eb611f41d5b0d34ce92181d783b85547a37 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:26:52 +0100 Subject: [PATCH 069/325] 3.0.1 didn't exist :S !wip --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index d22d50f67..99ec1e669 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,7 @@ install: # Get the latest stable version of Node.js or io.js - ps: Install-Product node $env:nodejs_version - - cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\3.0.1;%path% + - cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\3.0;%path% - cmd: tsc -v build_script: - ps: ./build.ps1 --settings_skipverification=true From fed8ac9213b31bbebfc22d1a23e0f95706edd1de Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:48:46 +0100 Subject: [PATCH 070/325] updated ts !wip --- src/Ombi/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/package.json b/src/Ombi/package.json index ceb7fc621..df35ffbf8 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -78,7 +78,7 @@ "ts-node": "^7.0.0", "tslint": "^5.10.0", "tslint-language-service": "^0.9.9", - "typescript": "2.7.2", + "typescript": "3.1.1", "uglify-es": "^3.3.9", "uglifyjs-webpack-plugin": "^1.2.7", "url-loader": "^1.0.1", From f0e15670958b54d3b99fb72f88d37862c3626719 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:54:24 +0100 Subject: [PATCH 071/325] put pkg back !wip --- src/Ombi/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/package.json b/src/Ombi/package.json index df35ffbf8..ceb7fc621 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -78,7 +78,7 @@ "ts-node": "^7.0.0", "tslint": "^5.10.0", "tslint-language-service": "^0.9.9", - "typescript": "3.1.1", + "typescript": "2.7.2", "uglify-es": "^3.3.9", "uglifyjs-webpack-plugin": "^1.2.7", "url-loader": "^1.0.1", From 909180d0991dba0e5064f227c926ae3954ca7f93 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 9 Oct 2018 21:50:21 +0100 Subject: [PATCH 072/325] Update LidarrAvailabilityChecker.cs --- src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs index d5ba14a6d..5708dad6c 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -43,7 +43,7 @@ namespace Ombi.Schedule.Jobs.Lidarr var cachedAlbum = await _cachedAlbums.FirstOrDefaultAsync(x => x.ForeignAlbumId.Equals(request.ForeignAlbumId)); if (cachedAlbum != null) { - if (cachedAlbum.Monitored && cachedAlbum.FullyAvailable) + if (cachedAlbum.FullyAvailable) { request.Available = true; request.MarkedAsAvailable = DateTime.Now; @@ -70,4 +70,4 @@ namespace Ombi.Schedule.Jobs.Lidarr } } } -} \ No newline at end of file +} From f2b78384e7288e068c1b8c2b3b4a0b816d9a9659 Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Thu, 11 Oct 2018 00:59:38 +1300 Subject: [PATCH 073/325] Fixes untickable mass email checkboxes in Safari. --- .../ClientApp/app/settings/massemail/massemail.component.html | 2 +- .../ClientApp/app/settings/massemail/massemail.component.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Ombi/ClientApp/app/settings/massemail/massemail.component.html b/src/Ombi/ClientApp/app/settings/massemail/massemail.component.html index e66d83a18..5c51c68ca 100644 --- a/src/Ombi/ClientApp/app/settings/massemail/massemail.component.html +++ b/src/Ombi/ClientApp/app/settings/massemail/massemail.component.html @@ -39,7 +39,7 @@
- +
diff --git a/src/Ombi/ClientApp/app/settings/massemail/massemail.component.ts b/src/Ombi/ClientApp/app/settings/massemail/massemail.component.ts index a80f7adfe..91693103f 100644 --- a/src/Ombi/ClientApp/app/settings/massemail/massemail.component.ts +++ b/src/Ombi/ClientApp/app/settings/massemail/massemail.component.ts @@ -38,10 +38,6 @@ export class MassEmailComponent implements OnInit { this.users.forEach(u => u.selected = !u.selected); } - public selectSingleUser(user: IMassEmailUserModel) { - user.selected = !user.selected; - } - public send() { if(!this.subject) { this.missingSubject = true; From fed7708a0d0e24bdef99d9d4915532fb4ba03d34 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 10 Oct 2018 15:36:37 +0100 Subject: [PATCH 074/325] fixed the build. Thanks Matt! --- src/Ombi/package.json | 3 ++- src/Ombi/tsconfig.json | 3 --- src/Ombi/yarn.lock | 10 +++------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Ombi/package.json b/src/Ombi/package.json index ceb7fc621..fa476f66b 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -91,7 +91,8 @@ "zone.js": "^0.8.26" }, "resolutions": { - "@types/tapable": "1.0.0" + "@types/tapable": "1.0.0", + "cypress/**/@types/sinon": "4.3.3" }, "devDependencies": { "cypress": "^3.1.0" diff --git a/src/Ombi/tsconfig.json b/src/Ombi/tsconfig.json index bd114dcdb..1e41f53b9 100644 --- a/src/Ombi/tsconfig.json +++ b/src/Ombi/tsconfig.json @@ -28,9 +28,6 @@ } ] }, - "types": [ - "cypress" - ], "include": [ "ClientApp/**/*", "typings/**/*", diff --git a/src/Ombi/yarn.lock b/src/Ombi/yarn.lock index 1debb9f2d..77c0b08f6 100644 --- a/src/Ombi/yarn.lock +++ b/src/Ombi/yarn.lock @@ -210,13 +210,9 @@ "@types/chai" "*" "@types/sinon" "*" -"@types/sinon@*": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.4.tgz#a765b390b373cf01a3b19b0c97f9eb4bb2a168b1" - -"@types/sinon@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.0.0.tgz#9a93ffa4ee1329e85166278a5ed99f81dc4c8362" +"@types/sinon@*", "@types/sinon@4.0.0", "@types/sinon@4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.3.3.tgz#97cbbfddc3282b5fd40c7abf80b99db426fd4237" "@types/sizzle@*": version "2.3.2" From 870a07de9d181abb3663eee25e13815e14382717 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 10 Oct 2018 15:47:50 +0100 Subject: [PATCH 075/325] revert, no idea how this happened --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 + src/Ombi.Schedule.Tests/IssuesPurgeTests.cs | 85 +++++++++++++++++++ src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs | 9 ++ src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs | 63 ++++++++++++++ .../Settings/Models/IssueSettings.cs | 3 + .../Settings/Models/JobSettings.cs | 1 + .../Settings/Models/JobSettingsHelper.cs | 5 ++ src/Ombi.Store/Entities/Requests/Issues.cs | 1 + .../ClientApp/app/interfaces/ISettings.ts | 3 + .../music/musicrequests.component.html | 2 +- .../app/settings/issues/issues.component.ts | 6 +- .../app/settings/jobs/jobs.component.html | 9 +- .../app/settings/jobs/jobs.component.ts | 1 + .../usermanagement-user.component.html | 12 +-- src/Ombi/Controllers/SettingsController.cs | 3 +- 15 files changed, 193 insertions(+), 11 deletions(-) create mode 100644 src/Ombi.Schedule.Tests/IssuesPurgeTests.cs create mode 100644 src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs create mode 100644 src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index eac6812bc..30ccb6973 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -192,6 +192,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs new file mode 100644 index 000000000..932022cd8 --- /dev/null +++ b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Moq; +using NUnit.Framework; +using Ombi.Core.Settings; +using Ombi.Schedule.Jobs.Ombi; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using System.Threading.Tasks; + +namespace Ombi.Schedule.Tests +{ + [TestFixture] + public class IssuesPurgeTests + { + + [SetUp] + public void Setup() + { + Repo = new Mock>(); + Settings = new Mock>(); + Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings()); + Job = new IssuesPurge(Repo.Object, Settings.Object); + } + + public Mock> Repo { get; set; } + public Mock> Settings { get; set; } + public IssuesPurge Job { get; set; } + + [Test] + public async Task DoesNotRun_WhenDisabled() + { + await Job.Start(); + Repo.Verify(x => x.GetAll(),Times.Never); + } + + [Test] + public async Task Deletes_Correct_Issue() + { + var issues = new List() + { + new Issues + { + Status = IssueStatus.Resolved, + ResovledDate = DateTime.Now.AddDays(-5).AddHours(-1) + } + }; + + Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); + Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); + await Job.Start(); + + Assert.That(issues.First().Status, Is.EqualTo(IssueStatus.Deleted)); + Repo.Verify(x => x.SaveChangesAsync(), Times.Once); + } + + [Test] + public async Task DoesNot_Delete_AnyIssues() + { + var issues = new List() + { + new Issues + { + Status = IssueStatus.Resolved, + ResovledDate = DateTime.Now.AddDays(-2) + }, + new Issues + { + Status = IssueStatus.Resolved, + ResovledDate = DateTime.Now.AddDays(-6) + } + }; + + Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); + Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); + await Job.Start(); + + Assert.That(issues[0].Status, Is.Not.EqualTo(IssueStatus.Deleted)); + Assert.That(issues[1].Status, Is.EqualTo(IssueStatus.Deleted)); + Repo.Verify(x => x.SaveChangesAsync(), Times.Once); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs new file mode 100644 index 000000000..fbd1e3aaf --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Ombi +{ + public interface IIssuesPurge : IBaseJob + { + Task Start(); + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs new file mode 100644 index 000000000..92ca31071 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs @@ -0,0 +1,63 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; + +namespace Ombi.Schedule.Jobs.Ombi +{ + public class IssuesPurge : IIssuesPurge + { + public IssuesPurge(IRepository issuesRepo, ISettingsService issueSettings) + { + _issuesRepository = issuesRepo; + _settings = issueSettings; + _settings.ClearCache(); + } + + private readonly IRepository _issuesRepository; + private readonly ISettingsService _settings; + + public async Task Start() + { + var settings = await _settings.GetSettingsAsync(); + if (!settings.DeleteIssues) + { + return; + } + + var now = DateTime.Now.AddDays(-settings.DaysAfterResolvedToDelete).Date; + var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved); + var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date <= now); + + foreach (var d in toDelete) + { + d.Status = IssueStatus.Deleted; + } + + await _issuesRepository.SaveChangesAsync(); + } + + private bool _disposed; + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + _issuesRepository?.Dispose(); + _settings?.Dispose(); + } + _disposed = true; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/IssueSettings.cs b/src/Ombi.Settings/Settings/Models/IssueSettings.cs index e025c82d1..d7a35c0d9 100644 --- a/src/Ombi.Settings/Settings/Models/IssueSettings.cs +++ b/src/Ombi.Settings/Settings/Models/IssueSettings.cs @@ -4,5 +4,8 @@ { public bool Enabled { get; set; } public bool EnableInProgress { get; set; } + + public bool DeleteIssues { get; set; } + public int DaysAfterResolvedToDelete { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index 48c721e29..8b283cdf7 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -14,5 +14,6 @@ public string RefreshMetadata { get; set; } public string Newsletter { get; set; } public string LidarrArtistSync { get; set; } + public string IssuesPurge { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index 0f8fec5fd..4491ca27a 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -57,6 +57,11 @@ namespace Ombi.Settings.Settings.Models return Get(s.LidarrArtistSync, Cron.Hourly(40)); } + public static string IssuePurge(JobSettings s) + { + return Get(s.IssuesPurge, Cron.Daily()); + } + private static string Get(string settings, string defaultCron) { return settings.HasValue() ? settings : defaultCron; diff --git a/src/Ombi.Store/Entities/Requests/Issues.cs b/src/Ombi.Store/Entities/Requests/Issues.cs index b1021e362..9fbc6a83e 100644 --- a/src/Ombi.Store/Entities/Requests/Issues.cs +++ b/src/Ombi.Store/Entities/Requests/Issues.cs @@ -29,5 +29,6 @@ namespace Ombi.Store.Entities.Requests Pending = 0, InProgress = 1, Resolved = 2, + Deleted = 3, } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 5f1b255a4..f1934a994 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -144,11 +144,14 @@ export interface IJobSettings { newsletter: string; plexRecentlyAddedSync: string; lidarrArtistSync: string; + issuesPurge: string; } export interface IIssueSettings extends ISettings { enabled: boolean; enableInProgress: boolean; + deleteIssues: boolean; + daysAfterResolvedToDelete: number; } export interface IAuthenticationSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index f86d3351d..c4c903da2 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -59,7 +59,7 @@

- {{request.title}} + {{request.title | truncate: 36}}

diff --git a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts index 005202f1e..cfe0bd65c 100644 --- a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts +++ b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts @@ -21,8 +21,10 @@ export class IssuesComponent implements OnInit { public ngOnInit() { this.settingsService.getIssueSettings().subscribe(x => { this.form = this.fb.group({ - enabled: [x.enabled], - enableInProgress: [x.enableInProgress], + enabled: [x.enabled], + enableInProgress: [x.enableInProgress], + deleteIssues: [x.deleteIssues], + daysAfterResolvedToDelete: [x.daysAfterResolvedToDelete], }); }); this.getCategories(); diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index a4dcd6fb3..1365710f0 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -85,12 +85,19 @@
-
+
The Newsletter is required
+ +
+ + + The Issues Purge is required + +
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index 756d6ba89..d8ce106ae 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -35,6 +35,7 @@ export class JobsComponent implements OnInit { newsletter: [x.newsletter, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], lidarrArtistSync: [x.lidarrArtistSync, Validators.required], + issuesPurge: [x.issuesPurge, Validators.required], }); }); } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index bf0e53895..3f44a808b 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -147,7 +147,7 @@
-
+
@@ -165,7 +165,7 @@
-
+
@@ -182,7 +182,7 @@
-
+
-
+
+

{{result.title}} ({{result.releaseDate | amLocal | amDateFormat: 'YYYY'}})

- - {{ 'Search.TheatricalRelease' | translate: {date: result.releaseDate | amLocal | amDateFormat: 'LL'} }} - {{ 'Search.DigitalDate' | translate: {date: result.digitalReleaseDate | amLocal | amDateFormat: 'LL'} }} + + {{ + 'Search.TheatricalRelease' | translate: {date: result.releaseDate | amLocal | + amDateFormat: 'LL'} }} + {{ 'Search.DigitalDate' | translate: {date: result.digitalReleaseDate | + amLocal | amDateFormat: 'LL'} }} - + - - {{result.quality}}p - - - - - + + {{result.quality}}p + + + + + - + -
+

{{result.overview}}

-
-
- - - -
-
- +
-
- - - - - - -
- - -
+
+ + + + + + +
+ + + +
-
-
+
+
@@ -117,4 +139,4 @@ + [issueCategory]="issueCategorySelected" [id]="issueRequestId" [providerId]="issueProviderId"> \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index f4d19565a..600fc19eb 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -172,7 +172,7 @@ export class MovieSearchComponent implements OnInit { r.subscribed = true; this.requestService.subscribeToMovie(r.requestId) .subscribe(x => { - this.notificationService.success("Subscribed To Movie!"); + this.notificationService.success(`Subscribed To Movie ${r.title}!`); }); } From 05a8846104a821375f1b402e75b491c92b2b06dd Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 23 Nov 2018 19:53:39 +0000 Subject: [PATCH 115/325] !changelog --- CHANGELOG.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9fdea5a0..5e60b7be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,43 @@ ## (unreleased) +### **New Features** + +- Updated the emby api since we no longer need the extra parameters to send to emby to log in a local user #2546. [Jamie] + +- Added the ability to get the ombi user via a Plex Token #2591. [Jamie] + +### **Fixes** + +- Made the subscribe/unsubscribe button more obvious on the UI #2309. [Jamie] + +- Fixed #2603. [Jamie] + +- Fixed the issue with the user overrides #2646. [Jamie] + +- Fixed the issue where we could sometimes allow the request of a whole series when the user shouldn't be able to. [Jamie] + +- Fixed the issue where we were marking episodes as available with the Emby connection when they have not yet aired #2417 #2623. [TidusJar] + +- Fixed the issue where we were marking the whole season as wanted in Sonarr rather than the individual episode #2629. [TidusJar] + +- Fixed #2623. [Jamie] + +- Fixed #2633. [TidusJar] + +- Fixed #2639. [Jamie] + +- Show the TV show as available when we have all the episodes but future episodes have not aired. #2585. [Jamie] + + +## v3.0.3945 (2018-10-25) + +### **New Features** + +- Update Readme for Lidarr. [Qstick] + +- Update CHANGELOG.md. [Jamie] + ### **Fixes** - New translations en.json (French) [Jamie] From 04dcc8f1be57204d38e3eb508694f081f3524b5f Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 23 Nov 2018 20:31:15 +0000 Subject: [PATCH 116/325] !changelog --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1684273b..be6d012ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,8 @@ # Changelog -## V3.0.3945 (2018-10-25) +## v3.0.3988 (2018-11-23) -- Fixed #2601 [TidusJar] -## v3.0.3919 (2018-10-18) ### **New Features** @@ -14,6 +12,8 @@ ### **Fixes** +- Fixed #2601 [TidusJar] + - Made the subscribe/unsubscribe button more obvious on the UI #2309. [Jamie] - Fixed #2603. [Jamie] From 185c47b0ee56310bbc386e9fc936a72c8650b47c Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Wed, 28 Nov 2018 10:02:54 +1300 Subject: [PATCH 117/325] Maps alias email variable for welcome emails. --- src/Ombi/Controllers/IdentityController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 61b3f06d8..f963db0b8 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -863,6 +863,7 @@ namespace Ombi.Controllers { var ombiUser = new OmbiUser { + Alias = user.Alias, Email = user.EmailAddress, UserName = user.UserName }; From 6c1057ad70d05ba5ed1f923085a6ae88abfc1cf2 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 28 Nov 2018 21:19:35 +0000 Subject: [PATCH 118/325] Increased the logo size on the landing page to match the container below it --- src/Ombi/ClientApp/app/landingpage/landingpage.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/landingpage/landingpage.component.html b/src/Ombi/ClientApp/app/landingpage/landingpage.component.html index 27545b64b..03878033f 100644 --- a/src/Ombi/ClientApp/app/landingpage/landingpage.component.html +++ b/src/Ombi/ClientApp/app/landingpage/landingpage.component.html @@ -3,7 +3,7 @@
-
+
From 91fdfa74c19ba876fc0af98ecf5ba5bfeea901dd Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 3 Dec 2018 20:34:21 +0000 Subject: [PATCH 119/325] #2669 Fixed missing translations --- src/Ombi/ClientApp/app/search/moviesearch.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index 05dbf15ad..b51dec5a6 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -92,12 +92,12 @@
+ +
+ + + The Retry Requests is required + +
diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index b523250a6..338b55f21 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -520,6 +520,7 @@ namespace Ombi.Controllers j.Newsletter = j.Newsletter.HasValue() ? j.Newsletter : JobSettingsHelper.Newsletter(j); j.LidarrArtistSync = j.LidarrArtistSync.HasValue() ? j.LidarrArtistSync : JobSettingsHelper.LidarrArtistSync(j); j.IssuesPurge = j.IssuesPurge.HasValue() ? j.IssuesPurge : JobSettingsHelper.IssuePurge(j); + j.RetryRequests = j.RetryRequests.HasValue() ? j.RetryRequests : JobSettingsHelper.ResendFailedRequests(j); return j; } From 75f43260c0aff88d0a6bf7602e4af6dd3f4c0127 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 3 Dec 2018 21:36:46 +0000 Subject: [PATCH 122/325] !wip added the api --- .../Rule/Search/CouchPotatoCacheRuleTests.cs | 4 +- .../Rule/Search/RadarrCacheRuleTests.cs | 4 +- src/Ombi.Core/Ombi.Core.csproj | 1 + src/Ombi.Core/Senders/MusicSender.cs | 2 - src/Ombi.Schedule.Tests/NewsletterTests.cs | 6 +- .../20181203213532_RequestQueue.Designer.cs | 1182 +++++++++++++++++ .../Migrations/20181203213532_RequestQueue.cs | 17 + .../Migrations/OmbiContextModelSnapshot.cs | 2 +- src/Ombi/Controllers/RequestRetyController.cs | 44 + 9 files changed, 1253 insertions(+), 9 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20181203213532_RequestQueue.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs create mode 100644 src/Ombi/Controllers/RequestRetyController.cs diff --git a/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs index 56524522b..2a8f7a520 100644 --- a/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs @@ -18,13 +18,13 @@ namespace Ombi.Core.Tests.Rule.Search [SetUp] public void Setup() { - ContextMock = new Mock>(); + ContextMock = new Mock>(); Rule = new CouchPotatoCacheRule(ContextMock.Object); } private CouchPotatoCacheRule Rule { get; set; } - private Mock> ContextMock { get; set; } + private Mock> ContextMock { get; set; } [Test] public async Task Should_ReturnApproved_WhenMovieIsInCouchPotato() diff --git a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs index 914112d5b..94efe89a2 100644 --- a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs @@ -15,13 +15,13 @@ namespace Ombi.Core.Tests.Rule.Search [SetUp] public void Setup() { - ContextMock = new Mock>(); + ContextMock = new Mock>(); Rule = new RadarrCacheRule(ContextMock.Object); } private RadarrCacheRule Rule { get; set; } - private Mock> ContextMock { get; set; } + private Mock> ContextMock { get; set; } [Test] public async Task Should_ReturnApproved_WhenMovieIsInRadarr() diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 644c02515..fb1024b93 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index b016e76b5..76a9fc14c 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -4,14 +4,12 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Api.Lidarr; using Ombi.Api.Lidarr.Models; -using Ombi.Api.Radarr; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; -using Serilog; using ILogger = Microsoft.Extensions.Logging.ILogger; namespace Ombi.Core.Senders diff --git a/src/Ombi.Schedule.Tests/NewsletterTests.cs b/src/Ombi.Schedule.Tests/NewsletterTests.cs index 146cd97cf..f729e8899 100644 --- a/src/Ombi.Schedule.Tests/NewsletterTests.cs +++ b/src/Ombi.Schedule.Tests/NewsletterTests.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using NUnit.Framework; +using Ombi.Helpers; using static Ombi.Schedule.Jobs.Ombi.NewsletterJob; namespace Ombi.Schedule.Tests @@ -15,7 +17,7 @@ namespace Ombi.Schedule.Tests { ep.Add(i); } - var result = BuildEpisodeList(ep); + var result = StringHelper.BuildEpisodeList(ep); return result; } diff --git a/src/Ombi.Store/Migrations/20181203213532_RequestQueue.Designer.cs b/src/Ombi.Store/Migrations/20181203213532_RequestQueue.Designer.cs new file mode 100644 index 000000000..5de4398af --- /dev/null +++ b/src/Ombi.Store/Migrations/20181203213532_RequestQueue.Designer.cs @@ -0,0 +1,1182 @@ +// +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 +{ + [DbContext(typeof(OmbiContext))] + [Migration("20181203213532_RequestQueue")] + partial class RequestQueue + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs b/src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs new file mode 100644 index 000000000..cd577cc26 --- /dev/null +++ b/src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class RequestQueue : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 60927b1ed..672525b41 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { diff --git a/src/Ombi/Controllers/RequestRetyController.cs b/src/Ombi/Controllers/RequestRetyController.cs new file mode 100644 index 000000000..34e11eb6d --- /dev/null +++ b/src/Ombi/Controllers/RequestRetyController.cs @@ -0,0 +1,44 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities; + +namespace Ombi.Controllers +{ + [ApiV1] + [Authorize] + [Produces("application/json")] + public class RequestRetyController : Controller + { + public RequestRetyController(IRepository requestQueue) + { + _requestQueueRepository = requestQueue; + } + + private readonly IRepository _requestQueueRepository; + + /// + /// Get's all the failed requests that are currently in the queue + /// + /// + [HttpGet] + public async Task> Categories() + { + return await _requestQueueRepository.GetAll().Where(x => !x.Completed.HasValue).ToListAsync(); + } + + [HttpDelete("{queueId:int}")] + public async Task Delete(int queueId) + { + var queueItem = await _requestQueueRepository.GetAll().FirstOrDefaultAsync(x => x.Id == queueId); + await _requestQueueRepository.Delete(queueItem); + return Ok(); + } + + } +} \ No newline at end of file From e8c6b23304e70d41809fcba2eb3391b702b87094 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 3 Dec 2018 21:44:07 +0000 Subject: [PATCH 123/325] Started on the UI !wip --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 + .../app/services/requestretry.service.ts | 18 +++++++++++++ .../failedrequest.component.html | 3 +++ .../failedrequests.component.ts | 25 +++++++++++++++++++ .../app/settings/jobs/jobs.component.html | 2 +- .../ClientApp/app/settings/settings.module.ts | 3 +++ src/Ombi/Controllers/RequestRetyController.cs | 3 ++- 7 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 src/Ombi/ClientApp/app/services/requestretry.service.ts create mode 100644 src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html create mode 100644 src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index f5184493c..836bc4f5b 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -198,6 +198,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi/ClientApp/app/services/requestretry.service.ts b/src/Ombi/ClientApp/app/services/requestretry.service.ts new file mode 100644 index 000000000..338475609 --- /dev/null +++ b/src/Ombi/ClientApp/app/services/requestretry.service.ts @@ -0,0 +1,18 @@ +import { PlatformLocation } from "@angular/common"; +import { Injectable } from "@angular/core"; + +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; + +import { IMobileUsersViewModel } from "../interfaces"; +import { ServiceHelpers } from "./service.helpers"; + +@Injectable() +export class RequestRetryService extends ServiceHelpers { + constructor(http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/requestretry/", platformLocation); + } + public getUserDeviceList(): Observable { + return this.http.get(`${this.url}notification/`, {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html new file mode 100644 index 000000000..4689eef46 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html @@ -0,0 +1,3 @@ + + + diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts new file mode 100644 index 000000000..af75a8bf1 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit } from "@angular/core"; +import { IAbout } from "../../interfaces/ISettings"; +import { JobService, SettingsService } from "../../services"; + +@Component({ + templateUrl: "./about.component.html", +}) +export class AboutComponent implements OnInit { + + public about: IAbout; + public newUpdate: boolean; + + constructor(private readonly settingsService: SettingsService, + private readonly jobService: JobService) { } + + public ngOnInit() { + this.settingsService.about().subscribe(x => this.about = x); + this.jobService.getCachedUpdate().subscribe(x => { + if (x === true) { + this.newUpdate = true; + } + }); + + } +} diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index e889c0fca..f8e3bb309 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -51,7 +51,7 @@
- + The Retry Requests is required
diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 060d42b19..e0fd90db9 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -19,6 +19,7 @@ import { CouchPotatoComponent } from "./couchpotato/couchpotato.component"; import { CustomizationComponent } from "./customization/customization.component"; import { DogNzbComponent } from "./dognzb/dognzb.component"; import { EmbyComponent } from "./emby/emby.component"; +import { FailedRequestsComponent } from "./failedrequests/failedrequests.component"; import { IssuesComponent } from "./issues/issues.component"; import { JobsComponent } from "./jobs/jobs.component"; import { LandingPageComponent } from "./landingpage/landingpage.component"; @@ -77,6 +78,7 @@ const routes: Routes = [ { path: "Newsletter", component: NewsletterComponent, canActivate: [AuthGuard] }, { path: "Lidarr", component: LidarrComponent, canActivate: [AuthGuard] }, { path: "Vote", component: VoteComponent, canActivate: [AuthGuard] }, + { path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] }, ]; @NgModule({ @@ -130,6 +132,7 @@ const routes: Routes = [ NewsletterComponent, LidarrComponent, VoteComponent, + FailedRequestsComponent, ], exports: [ RouterModule, diff --git a/src/Ombi/Controllers/RequestRetyController.cs b/src/Ombi/Controllers/RequestRetyController.cs index 34e11eb6d..69e379838 100644 --- a/src/Ombi/Controllers/RequestRetyController.cs +++ b/src/Ombi/Controllers/RequestRetyController.cs @@ -6,12 +6,13 @@ using Ombi.Store.Repository; using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; +using Ombi.Attributes; using Ombi.Store.Entities; namespace Ombi.Controllers { [ApiV1] - [Authorize] + [Admin] [Produces("application/json")] public class RequestRetyController : Controller { From 806cf7c0ffc73182a8099de40ad84b10825eff53 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 4 Dec 2018 09:45:22 +0000 Subject: [PATCH 124/325] More on the UI !wip --- src/Ombi.Store/Context/OmbiContext.cs | 1 + .../Migrations/20181203213532_RequestQueue.cs | 17 ---- ...> 20181204084915_RequestQueue.Designer.cs} | 24 ++++- .../Migrations/20181204084915_RequestQueue.cs | 35 +++++++ .../Migrations/OmbiContextModelSnapshot.cs | 22 +++++ .../app/interfaces/IFailedRequests.ts | 11 +++ .../ClientApp/app/interfaces/IRequestModel.ts | 2 +- src/Ombi/ClientApp/app/interfaces/index.ts | 1 + src/Ombi/ClientApp/app/services/index.ts | 1 + .../app/services/requestretry.service.ts | 6 +- .../failedrequest.component.html | 25 +++++ .../failedrequests.component.ts | 23 ++--- .../app/settings/jobs/jobs.component.ts | 1 + .../ClientApp/app/settings/settings.module.ts | 3 +- .../Controllers/RequestRetryController.cs | 92 +++++++++++++++++++ src/Ombi/Controllers/RequestRetyController.cs | 45 --------- src/Ombi/Models/FailedRequestViewModel.cs | 17 ++++ 17 files changed, 243 insertions(+), 83 deletions(-) delete mode 100644 src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs rename src/Ombi.Store/Migrations/{20181203213532_RequestQueue.Designer.cs => 20181204084915_RequestQueue.Designer.cs} (98%) create mode 100644 src/Ombi.Store/Migrations/20181204084915_RequestQueue.cs create mode 100644 src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts create mode 100644 src/Ombi/Controllers/RequestRetryController.cs delete mode 100644 src/Ombi/Controllers/RequestRetyController.cs create mode 100644 src/Ombi/Models/FailedRequestViewModel.cs diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 16f26c65a..3d8c05daa 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -56,6 +56,7 @@ namespace Ombi.Store.Context public DbSet RequestSubscription { get; set; } public DbSet UserNotificationPreferences { get; set; } public DbSet UserQualityProfileses { get; set; } + public DbSet RequestQueue { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { diff --git a/src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs b/src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs deleted file mode 100644 index cd577cc26..000000000 --- a/src/Ombi.Store/Migrations/20181203213532_RequestQueue.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Ombi.Store.Migrations -{ - public partial class RequestQueue : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/src/Ombi.Store/Migrations/20181203213532_RequestQueue.Designer.cs b/src/Ombi.Store/Migrations/20181204084915_RequestQueue.Designer.cs similarity index 98% rename from src/Ombi.Store/Migrations/20181203213532_RequestQueue.Designer.cs rename to src/Ombi.Store/Migrations/20181204084915_RequestQueue.Designer.cs index 5de4398af..468abb2c7 100644 --- a/src/Ombi.Store/Migrations/20181203213532_RequestQueue.Designer.cs +++ b/src/Ombi.Store/Migrations/20181204084915_RequestQueue.Designer.cs @@ -9,7 +9,7 @@ using Ombi.Store.Context; namespace Ombi.Store.Migrations { [DbContext(typeof(OmbiContext))] - [Migration("20181203213532_RequestQueue")] + [Migration("20181204084915_RequestQueue")] partial class RequestQueue { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -510,6 +510,28 @@ namespace Ombi.Store.Migrations b.ToTable("RecentlyAddedLog"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") diff --git a/src/Ombi.Store/Migrations/20181204084915_RequestQueue.cs b/src/Ombi.Store/Migrations/20181204084915_RequestQueue.cs new file mode 100644 index 000000000..820ce50af --- /dev/null +++ b/src/Ombi.Store/Migrations/20181204084915_RequestQueue.cs @@ -0,0 +1,35 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class RequestQueue : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "RequestQueue", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RequestId = table.Column(nullable: false), + Type = table.Column(nullable: false), + Dts = table.Column(nullable: false), + Error = table.Column(nullable: true), + Completed = table.Column(nullable: true), + RetryCount = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RequestQueue", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RequestQueue"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 672525b41..5a009d5ef 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -508,6 +508,28 @@ namespace Ombi.Store.Migrations b.ToTable("RecentlyAddedLog"); }); + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") diff --git a/src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts b/src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts new file mode 100644 index 000000000..002904386 --- /dev/null +++ b/src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts @@ -0,0 +1,11 @@ +import { RequestType } from "."; +export interface IFailedRequestsViewModel { + failedId: number; + title: string; + releaseYear: Date; + requestId: number; + requestType: RequestType; + dts: Date; + error: string; + retryCount: number; +} diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index 310aaa6fd..5a72abf31 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -3,7 +3,7 @@ export enum RequestType { movie = 1, tvShow = 2, - + album = 3, } // NEW WORLD diff --git a/src/Ombi/ClientApp/app/interfaces/index.ts b/src/Ombi/ClientApp/app/interfaces/index.ts index bfc89edc6..e1cf823e8 100644 --- a/src/Ombi/ClientApp/app/interfaces/index.ts +++ b/src/Ombi/ClientApp/app/interfaces/index.ts @@ -17,3 +17,4 @@ export * from "./IRecentlyAdded"; export * from "./ILidarr"; export * from "./ISearchMusicResult"; export * from "./IVote"; +export * from "./IFailedRequests"; diff --git a/src/Ombi/ClientApp/app/services/index.ts b/src/Ombi/ClientApp/app/services/index.ts index c1ccc2585..edffdd625 100644 --- a/src/Ombi/ClientApp/app/services/index.ts +++ b/src/Ombi/ClientApp/app/services/index.ts @@ -15,3 +15,4 @@ export * from "./mobile.service"; export * from "./notificationMessage.service"; export * from "./recentlyAdded.service"; export * from "./vote.service"; +export * from "./requestretry.service"; diff --git a/src/Ombi/ClientApp/app/services/requestretry.service.ts b/src/Ombi/ClientApp/app/services/requestretry.service.ts index 338475609..09e345566 100644 --- a/src/Ombi/ClientApp/app/services/requestretry.service.ts +++ b/src/Ombi/ClientApp/app/services/requestretry.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IMobileUsersViewModel } from "../interfaces"; +import { IFailedRequestsViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() @@ -12,7 +12,7 @@ export class RequestRetryService extends ServiceHelpers { constructor(http: HttpClient, public platformLocation: PlatformLocation) { super(http, "/api/v1/requestretry/", platformLocation); } - public getUserDeviceList(): Observable { - return this.http.get(`${this.url}notification/`, {headers: this.headers}); + public getFailedRequests(): Observable { + return this.http.get(this.url, {headers: this.headers}); } } diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html index 4689eef46..d1e5b13ec 100644 --- a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html @@ -1,3 +1,28 @@  + + + + + + + + + + + + + + + + + + + + + + +
TitleTypeRetry CountError DescriptionRetryDelete
+ {{v.title}} + {{RequestType[v.type] | humanize}}{{v.retryCount}}
diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts index af75a8bf1..214729840 100644 --- a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts @@ -1,25 +1,18 @@ import { Component, OnInit } from "@angular/core"; -import { IAbout } from "../../interfaces/ISettings"; -import { JobService, SettingsService } from "../../services"; +import { IFailedRequestsViewModel, RequestType } from "../../interfaces"; +import { RequestRetryService } from "../../services"; @Component({ - templateUrl: "./about.component.html", + templateUrl: "./failedrequest.component.html", }) -export class AboutComponent implements OnInit { +export class FailedRequestsComponent implements OnInit { - public about: IAbout; - public newUpdate: boolean; + public vm: IFailedRequestsViewModel[]; + public RequestType = RequestType; - constructor(private readonly settingsService: SettingsService, - private readonly jobService: JobService) { } + constructor(private retry: RequestRetryService) { } public ngOnInit() { - this.settingsService.about().subscribe(x => this.about = x); - this.jobService.getCachedUpdate().subscribe(x => { - if (x === true) { - this.newUpdate = true; - } - }); - + this.retry.getFailedRequests().subscribe(x => this.vm = x); } } diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index d8ce106ae..853005185 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -36,6 +36,7 @@ export class JobsComponent implements OnInit { plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], lidarrArtistSync: [x.lidarrArtistSync, Validators.required], issuesPurge: [x.issuesPurge, Validators.required], + retryRequests: [x.retryRequests, Validators.required], }); }); } diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index e0fd90db9..fb1a10abe 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -9,7 +9,7 @@ import { AuthGuard } from "../auth/auth.guard"; import { AuthService } from "../auth/auth.service"; import { CouchPotatoService, EmbyService, IssuesService, JobService, LidarrService, MobileService, NotificationMessageService, PlexService, RadarrService, - SonarrService, TesterService, ValidationService, + RequestRetryService, SonarrService, TesterService, ValidationService, } from "../services"; import { PipeModule } from "../pipes/pipe.module"; @@ -152,6 +152,7 @@ const routes: Routes = [ MobileService, NotificationMessageService, LidarrService, + RequestRetryService, ], }) diff --git a/src/Ombi/Controllers/RequestRetryController.cs b/src/Ombi/Controllers/RequestRetryController.cs new file mode 100644 index 000000000..6a53f9732 --- /dev/null +++ b/src/Ombi/Controllers/RequestRetryController.cs @@ -0,0 +1,92 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Ombi.Attributes; +using Ombi.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Controllers +{ + [ApiV1] + [Admin] + [Produces("application/json")] + public class RequestRetryController : Controller + { + public RequestRetryController(IRepository requestQueue, IMovieRequestRepository movieRepo, + ITvRequestRepository tvRepo, IMusicRequestRepository musicRepo) + { + _requestQueueRepository = requestQueue; + _movieRequestRepository = movieRepo; + _tvRequestRepository = tvRepo; + _musicRequestRepository = musicRepo; + } + + private readonly IRepository _requestQueueRepository; + private readonly IMovieRequestRepository _movieRequestRepository; + private readonly ITvRequestRepository _tvRequestRepository; + private readonly IMusicRequestRepository _musicRequestRepository; + + /// + /// Get's all the failed requests that are currently in the queue + /// + /// + [HttpGet] + public async Task> GetFailedRequests() + { + var failed = await _requestQueueRepository.GetAll().Where(x => !x.Completed.HasValue).ToListAsync(); + + var vm = new List(); + foreach (var f in failed) + { + var vmModel = new FailedRequestViewModel + { + RequestId = f.RequestId, + RetryCount = f.RetryCount, + Dts = f.Dts, + Error = f.Error, + FailedId = f.Id, + Type = f.Type + }; + + if (f.Type == RequestType.Movie) + { + var request = await _movieRequestRepository.Find(f.RequestId); + vmModel.Title = request.Title; + vmModel.ReleaseYear = request.ReleaseDate; + } + + if (f.Type == RequestType.Album) + { + var request = await _musicRequestRepository.Find(f.RequestId); + vmModel.Title = request.Title; + vmModel.ReleaseYear = request.ReleaseDate; + } + + if (f.Type == RequestType.TvShow) + { + var request = await _tvRequestRepository.GetChild().Include(x => x.ParentRequest).FirstOrDefaultAsync(x => x.Id == f.RequestId); + vmModel.Title = request.Title; + vmModel.ReleaseYear = request.ParentRequest.ReleaseDate; + } + vm.Add(vmModel); + } + + return vm; + } + + [HttpDelete("{queueId:int}")] + public async Task Delete(int queueId) + { + var queueItem = await _requestQueueRepository.GetAll().FirstOrDefaultAsync(x => x.Id == queueId); + await _requestQueueRepository.Delete(queueItem); + return Ok(); + } + + } +} \ No newline at end of file diff --git a/src/Ombi/Controllers/RequestRetyController.cs b/src/Ombi/Controllers/RequestRetyController.cs deleted file mode 100644 index 69e379838..000000000 --- a/src/Ombi/Controllers/RequestRetyController.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Ombi.Store.Entities.Requests; -using Ombi.Store.Repository; -using System.Collections.Generic; -using System.Linq; -using Microsoft.EntityFrameworkCore; -using Ombi.Attributes; -using Ombi.Store.Entities; - -namespace Ombi.Controllers -{ - [ApiV1] - [Admin] - [Produces("application/json")] - public class RequestRetyController : Controller - { - public RequestRetyController(IRepository requestQueue) - { - _requestQueueRepository = requestQueue; - } - - private readonly IRepository _requestQueueRepository; - - /// - /// Get's all the failed requests that are currently in the queue - /// - /// - [HttpGet] - public async Task> Categories() - { - return await _requestQueueRepository.GetAll().Where(x => !x.Completed.HasValue).ToListAsync(); - } - - [HttpDelete("{queueId:int}")] - public async Task Delete(int queueId) - { - var queueItem = await _requestQueueRepository.GetAll().FirstOrDefaultAsync(x => x.Id == queueId); - await _requestQueueRepository.Delete(queueItem); - return Ok(); - } - - } -} \ No newline at end of file diff --git a/src/Ombi/Models/FailedRequestViewModel.cs b/src/Ombi/Models/FailedRequestViewModel.cs new file mode 100644 index 000000000..bd3f7a858 --- /dev/null +++ b/src/Ombi/Models/FailedRequestViewModel.cs @@ -0,0 +1,17 @@ +using System; +using Ombi.Store.Entities; + +namespace Ombi.Models +{ + public class FailedRequestViewModel + { + public int FailedId { get; set; } + public string Title { get; set; } + public DateTime ReleaseYear { get; set; } + public int RequestId { get; set; } + public RequestType Type { get; set; } + public DateTime Dts { get; set; } + public string Error { get; set; } + public int RetryCount { get; set; } + } +} \ No newline at end of file From 9d2fc81a0c876042c0d6507927361c18dae661dd Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 4 Dec 2018 14:15:38 +0000 Subject: [PATCH 125/325] !wip --- src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts | 2 +- src/Ombi/ClientApp/app/services/requestretry.service.ts | 3 +++ .../app/settings/failedrequests/failedrequest.component.html | 4 +--- .../app/settings/failedrequests/failedrequests.component.ts | 4 ++++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts b/src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts index 002904386..51a924db5 100644 --- a/src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts +++ b/src/Ombi/ClientApp/app/interfaces/IFailedRequests.ts @@ -4,7 +4,7 @@ export interface IFailedRequestsViewModel { title: string; releaseYear: Date; requestId: number; - requestType: RequestType; + type: RequestType; dts: Date; error: string; retryCount: number; diff --git a/src/Ombi/ClientApp/app/services/requestretry.service.ts b/src/Ombi/ClientApp/app/services/requestretry.service.ts index 09e345566..9803f73f7 100644 --- a/src/Ombi/ClientApp/app/services/requestretry.service.ts +++ b/src/Ombi/ClientApp/app/services/requestretry.service.ts @@ -15,4 +15,7 @@ export class RequestRetryService extends ServiceHelpers { public getFailedRequests(): Observable { return this.http.get(this.url, {headers: this.headers}); } + public deleteFailedRequest(failedId: number): Observable { + return this.http.delete(`${this.url}/${failedId}`, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html index d1e5b13ec..c0cc2ca1e 100644 --- a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html @@ -9,7 +9,6 @@ Type Retry Count Error Description - Retry Delete @@ -21,8 +20,7 @@ {{RequestType[v.type] | humanize}} {{v.retryCount}} - - + diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts index 214729840..65be04a22 100644 --- a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts @@ -15,4 +15,8 @@ export class FailedRequestsComponent implements OnInit { public ngOnInit() { this.retry.getFailedRequests().subscribe(x => this.vm = x); } + + public remove(failedId: number) { + this.retry.deleteFailedRequest(failedId).subscribe(); + } } From b8450a5c497e7abffca84463e7f4d7ffb63b331c Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 4 Dec 2018 21:23:30 +0000 Subject: [PATCH 126/325] Started #2359 !wip --- src/Ombi.Api.Sonarr/ISonarrV3Api.cs | 13 ++++++++ .../Models/V3/LanguageProfiles.cs | 30 +++++++++++++++++++ src/Ombi.Api.Sonarr/SonarrApi.cs | 27 +++++++++-------- src/Ombi.Api.Sonarr/SonarrV3Api.cs | 25 ++++++++++++++++ src/Ombi.DependencyInjection/IocExtensions.cs | 1 + .../Models/External/SonarrSettings.cs | 1 + .../app/settings/sonarr/sonarr.component.ts | 1 + 7 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 src/Ombi.Api.Sonarr/ISonarrV3Api.cs create mode 100644 src/Ombi.Api.Sonarr/Models/V3/LanguageProfiles.cs create mode 100644 src/Ombi.Api.Sonarr/SonarrV3Api.cs diff --git a/src/Ombi.Api.Sonarr/ISonarrV3Api.cs b/src/Ombi.Api.Sonarr/ISonarrV3Api.cs new file mode 100644 index 000000000..1d3ea3468 --- /dev/null +++ b/src/Ombi.Api.Sonarr/ISonarrV3Api.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.Sonarr.Models; +using System.Net.Http; +using Ombi.Api.Sonarr.Models.V3; + +namespace Ombi.Api.Sonarr +{ + public interface ISonarrV3Api : ISonarrApi + { + Task> LanguageProfiles(string apiKey, string baseUrl); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Sonarr/Models/V3/LanguageProfiles.cs b/src/Ombi.Api.Sonarr/Models/V3/LanguageProfiles.cs new file mode 100644 index 000000000..aa3b199bd --- /dev/null +++ b/src/Ombi.Api.Sonarr/Models/V3/LanguageProfiles.cs @@ -0,0 +1,30 @@ +namespace Ombi.Api.Sonarr.Models.V3 +{ + public class LanguageProfiles + { + public string name { get; set; } + public bool upgradeAllowed { get; set; } + public Cutoff cutoff { get; set; } + public Languages[] languages { get; set; } + public int id { get; set; } + } + + public class Cutoff + { + public int id { get; set; } + public string name { get; set; } + } + + public class Languages + { + public Language languages { get; set; } + public bool allowed { get; set; } + } + + public class Language + { + public int id { get; set; } + public string name { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.Sonarr/SonarrApi.cs b/src/Ombi.Api.Sonarr/SonarrApi.cs index 7fd74d2a3..0b0df4c15 100644 --- a/src/Ombi.Api.Sonarr/SonarrApi.cs +++ b/src/Ombi.Api.Sonarr/SonarrApi.cs @@ -16,18 +16,19 @@ namespace Ombi.Api.Sonarr Api = api; } - private IApi Api { get; } + protected IApi Api { get; } + protected virtual string ApiBaseUrl => "/api/"; public async Task> GetProfiles(string apiKey, string baseUrl) { - var request = new Request("/api/profile", baseUrl, HttpMethod.Get); + var request = new Request($"{ApiBaseUrl}profile", baseUrl, HttpMethod.Get); request.AddHeader("X-Api-Key", apiKey); return await Api.Request>(request); } public async Task> GetRootFolders(string apiKey, string baseUrl) { - var request = new Request("/api/rootfolder", baseUrl, HttpMethod.Get); + var request = new Request($"{ApiBaseUrl}rootfolder", baseUrl, HttpMethod.Get); request.AddHeader("X-Api-Key", apiKey); return await Api.Request>(request); } @@ -40,7 +41,7 @@ namespace Ombi.Api.Sonarr /// public async Task> GetSeries(string apiKey, string baseUrl) { - var request = new Request("/api/series", baseUrl, HttpMethod.Get); + var request = new Request($"{ApiBaseUrl}series", baseUrl, HttpMethod.Get); request.AddHeader("X-Api-Key", apiKey); var results = await Api.Request>(request); @@ -63,7 +64,7 @@ namespace Ombi.Api.Sonarr /// public async Task GetSeriesById(int id, string apiKey, string baseUrl) { - var request = new Request($"/api/series/{id}", baseUrl, HttpMethod.Get); + var request = new Request($"{ApiBaseUrl}series/{id}", baseUrl, HttpMethod.Get); request.AddHeader("X-Api-Key", apiKey); var result = await Api.Request(request); if (result?.seasons?.Length > 0) @@ -82,7 +83,7 @@ namespace Ombi.Api.Sonarr /// public async Task UpdateSeries(SonarrSeries updated, string apiKey, string baseUrl) { - var request = new Request("/api/series/", baseUrl, HttpMethod.Put); + var request = new Request($"{ApiBaseUrl}series/", baseUrl, HttpMethod.Put); request.AddHeader("X-Api-Key", apiKey); request.AddJsonBody(updated); return await Api.Request(request); @@ -94,7 +95,7 @@ namespace Ombi.Api.Sonarr { return new NewSeries { ErrorMessages = new List { seriesToAdd.Validate() } }; } - var request = new Request("/api/series/", baseUrl, HttpMethod.Post); + var request = new Request($"{ApiBaseUrl}series/", baseUrl, HttpMethod.Post); request.AddHeader("X-Api-Key", apiKey); request.AddJsonBody(seriesToAdd); @@ -120,7 +121,7 @@ namespace Ombi.Api.Sonarr /// public async Task> GetEpisodes(int seriesId, string apiKey, string baseUrl) { - var request = new Request($"/api/Episode?seriesId={seriesId}", baseUrl, HttpMethod.Get); + var request = new Request($"{ApiBaseUrl}Episode?seriesId={seriesId}", baseUrl, HttpMethod.Get); request.AddHeader("X-Api-Key", apiKey); return await Api.Request>(request); } @@ -134,14 +135,14 @@ namespace Ombi.Api.Sonarr /// public async Task GetEpisodeById(int episodeId, string apiKey, string baseUrl) { - var request = new Request($"/api/Episode/{episodeId}", baseUrl, HttpMethod.Get); + var request = new Request($"{ApiBaseUrl}Episode/{episodeId}", baseUrl, HttpMethod.Get); request.AddHeader("X-Api-Key", apiKey); return await Api.Request(request); } public async Task UpdateEpisode(Episode episodeToUpdate, string apiKey, string baseUrl) { - var request = new Request($"/api/Episode/", baseUrl, HttpMethod.Put); + var request = new Request($"{ApiBaseUrl}Episode/", baseUrl, HttpMethod.Put); request.AddHeader("X-Api-Key", apiKey); request.AddJsonBody(episodeToUpdate); return await Api.Request(request); @@ -189,7 +190,7 @@ namespace Ombi.Api.Sonarr private async Task Command(string apiKey, string baseUrl, object body) { - var request = new Request($"/api/Command/", baseUrl, HttpMethod.Post); + var request = new Request($"{ApiBaseUrl}Command/", baseUrl, HttpMethod.Post); request.AddHeader("X-Api-Key", apiKey); request.AddJsonBody(body); return await Api.Request(request); @@ -197,7 +198,7 @@ namespace Ombi.Api.Sonarr public async Task SystemStatus(string apiKey, string baseUrl) { - var request = new Request("/api/system/status", baseUrl, HttpMethod.Get); + var request = new Request($"{ApiBaseUrl}system/status", baseUrl, HttpMethod.Get); request.AddHeader("X-Api-Key", apiKey); return await Api.Request(request); @@ -217,7 +218,7 @@ namespace Ombi.Api.Sonarr ignoreEpisodesWithoutFiles = false, } }; - var request = new Request("/api/seasonpass", baseUrl, HttpMethod.Post); + var request = new Request($"{ApiBaseUrl}seasonpass", baseUrl, HttpMethod.Post); request.AddHeader("X-Api-Key", apiKey); request.AddJsonBody(seasonPass); diff --git a/src/Ombi.Api.Sonarr/SonarrV3Api.cs b/src/Ombi.Api.Sonarr/SonarrV3Api.cs new file mode 100644 index 000000000..64377ee4a --- /dev/null +++ b/src/Ombi.Api.Sonarr/SonarrV3Api.cs @@ -0,0 +1,25 @@ +using System.Net.Http; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.Sonarr.Models.V3; + +namespace Ombi.Api.Sonarr +{ + public class SonarrV3Api : SonarrApi, ISonarrV3Api + { + public SonarrV3Api(IApi api) : base(api) + { + + } + + protected override string ApiBaseUrl => "/api/v3/"; + + public async Task> LanguageProfiles(string apiKey, string baseUrl) + { + var request = new Request($"{ApiBaseUrl}languageprofile", baseUrl, HttpMethod.Get); + request.AddHeader("X-Api-Key", apiKey); + + return await Api.Request>(request); + } + } +} diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index f5184493c..c33f31c10 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -107,6 +107,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs index 0c7e17900..81df73aad 100644 --- a/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs @@ -18,5 +18,6 @@ public string QualityProfileAnime { get; set; } public string RootPathAnime { get; set; } public bool AddOnly { get; set; } + public bool V3 { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts index a1c03be58..4af2c490e 100644 --- a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts @@ -47,6 +47,7 @@ export class SonarrComponent implements OnInit { port: [x.port, [Validators.required]], addOnly: [x.addOnly], seasonFolders: [x.seasonFolders], + v3: [x.v3], }); if (x.qualityProfile) { From a69637a3fbe255787ca791e7c44df08ed2e6c48d Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 5 Dec 2018 09:25:59 +0000 Subject: [PATCH 127/325] Did the frontend settings for Sonarr to add V3. !wip #2359 --- .../Rule/Search/CouchPotatoCacheRuleTests.cs | 4 +- .../Rule/Search/RadarrCacheRuleTests.cs | 4 +- src/Ombi.Core/Senders/TvSender.cs | 14 +- .../Models/External/SonarrSettings.cs | 1 + .../ClientApp/app/interfaces/ISettings.ts | 2 + src/Ombi/ClientApp/app/interfaces/ISonarr.ts | 5 + .../services/applications/sonarr.service.ts | 6 +- .../app/settings/sonarr/sonarr.component.html | 143 +++++++++++------- .../app/settings/sonarr/sonarr.component.ts | 23 ++- .../Controllers/External/SonarrController.cs | 36 ++++- 10 files changed, 174 insertions(+), 64 deletions(-) diff --git a/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs index 56524522b..2a8f7a520 100644 --- a/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs @@ -18,13 +18,13 @@ namespace Ombi.Core.Tests.Rule.Search [SetUp] public void Setup() { - ContextMock = new Mock>(); + ContextMock = new Mock>(); Rule = new CouchPotatoCacheRule(ContextMock.Object); } private CouchPotatoCacheRule Rule { get; set; } - private Mock> ContextMock { get; set; } + private Mock> ContextMock { get; set; } [Test] public async Task Should_ReturnApproved_WhenMovieIsInCouchPotato() diff --git a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs index 914112d5b..94efe89a2 100644 --- a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs @@ -15,13 +15,13 @@ namespace Ombi.Core.Tests.Rule.Search [SetUp] public void Setup() { - ContextMock = new Mock>(); + ContextMock = new Mock>(); Rule = new RadarrCacheRule(ContextMock.Object); } private RadarrCacheRule Rule { get; set; } - private Mock> ContextMock { get; set; } + private Mock> ContextMock { get; set; } [Test] public async Task Should_ReturnApproved_WhenMovieIsInRadarr() diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 1b3ed9461..b6c2aa8af 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -21,11 +21,12 @@ namespace Ombi.Core.Senders { public class TvSender : ITvSender { - public TvSender(ISonarrApi sonarrApi, ILogger log, ISettingsService sonarrSettings, + public TvSender(ISonarrApi sonarrApi, ISonarrV3Api sonarrV3Api, ILogger log, ISettingsService sonarrSettings, ISettingsService dog, IDogNzbApi dogApi, ISettingsService srSettings, ISickRageApi srApi, IRepository userProfiles) { SonarrApi = sonarrApi; + SonarrV3Api = sonarrV3Api; Logger = log; SonarrSettings = sonarrSettings; DogNzbSettings = dog; @@ -36,6 +37,7 @@ namespace Ombi.Core.Senders } private ISonarrApi SonarrApi { get; } + private ISonarrV3Api SonarrV3Api { get; } private IDogNzbApi DogNzbApi { get; } private ISickRageApi SickRageApi { get; } private ILogger Logger { get; } @@ -175,6 +177,16 @@ namespace Ombi.Core.Senders qualityToUse = model.ParentRequest.QualityOverride.Value; } + + // Are we using v3 sonarr? + var sonarrV3 = s.V3; + var languageProfileId = 0; + if (sonarrV3) + { + languageProfileId = s.LanguageProfile; + } + + try { // Does the series actually exist? diff --git a/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs index 81df73aad..bbbe58fd3 100644 --- a/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs @@ -19,5 +19,6 @@ public string RootPathAnime { get; set; } public bool AddOnly { get; set; } public bool V3 { get; set; } + public int LanguageProfile { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index f1934a994..99662088e 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -72,6 +72,8 @@ export interface ISonarrSettings extends IExternalSettings { rootPathAnime: string; fullRootPath: string; addOnly: boolean; + v3: boolean; + languageProfile: number; } export interface IRadarrSettings extends IExternalSettings { diff --git a/src/Ombi/ClientApp/app/interfaces/ISonarr.ts b/src/Ombi/ClientApp/app/interfaces/ISonarr.ts index 3c71b835c..ffe9e9b6d 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISonarr.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISonarr.ts @@ -7,3 +7,8 @@ export interface ISonarrProfile { name: string; id: number; } + +export interface ILanguageProfiles { + name: string; + id: number; +} diff --git a/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts b/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts index 756c6ea6c..bce47acf9 100644 --- a/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts @@ -5,7 +5,7 @@ import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; import { ISonarrSettings } from "../../interfaces"; -import { ISonarrProfile, ISonarrRootFolder } from "../../interfaces"; +import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder } from "../../interfaces"; import { ServiceHelpers } from "../service.helpers"; @Injectable() @@ -27,4 +27,8 @@ export class SonarrService extends ServiceHelpers { public getQualityProfilesWithoutSettings(): Observable { return this.http.get(`${this.url}/Profiles/`, {headers: this.headers}); } + + public getV3LanguageProfiles(settings: ISonarrSettings): Observable { + return this.http.post(`${this.url}/v3/languageprofiles/`, JSON.stringify(settings), {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html index 6a419feab..91385c353 100644 --- a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html +++ b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html @@ -1,5 +1,4 @@ - - +
Sonarr Settings @@ -10,33 +9,47 @@
-
-
- - +
+
+
+ + +
+
+
+ +
+
+
+ + +
- - - The IP/Hostname is required + + + The IP/Hostname is required
- - The Port is required + + The Port is required
- - - The API Key is required + + + The API Key is required
@@ -48,63 +61,80 @@
- +
-
-
- + + +
+ +
+ + + A Default Quality + Profile is required +
-
-
- -
- -
- A Default Quality Profile is required - -
-
+ +
- +
-
-
- -
-
-
+
- + + A Default Root Path + is + required
- A Default Root Path is required -
-
+ +
-
- + +
+ +
+ +
+ + + + A Default + Langauage Profile is required +
-
+
@@ -112,26 +142,27 @@
-
+
-
+
+
+ +
+
+ +
- -
-
- - -
-
- +
+
-
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts index 4af2c490e..ee2438f1b 100644 --- a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { ISonarrProfile, ISonarrRootFolder } from "../../interfaces"; +import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder } from "../../interfaces"; import { ISonarrSettings } from "../../interfaces"; import { SonarrService } from "../../services"; @@ -18,10 +18,13 @@ export class SonarrComponent implements OnInit { public qualitiesAnime: ISonarrProfile[]; public rootFolders: ISonarrRootFolder[]; public rootFoldersAnime: ISonarrRootFolder[]; + public languageProfiles: ILanguageProfiles[]; public selectedRootFolder: ISonarrRootFolder; public selectedQuality: ISonarrProfile; + public selectedLanguageProfiles: ILanguageProfiles; public profilesRunning: boolean; public rootFoldersRunning: boolean; + public langRunning: boolean; public form: FormGroup; public advanced = false; @@ -48,6 +51,7 @@ export class SonarrComponent implements OnInit { addOnly: [x.addOnly], seasonFolders: [x.seasonFolders], v3: [x.v3], + langaugeProfile: [x.languageProfile], }); if (x.qualityProfile) { @@ -56,11 +60,16 @@ export class SonarrComponent implements OnInit { if (x.rootPath) { this.getRootFolders(this.form); } + if(x.languageProfile) { + this.getLanguageProfiles(this.form); + } }); this.rootFolders = []; this.qualities = []; + this.languageProfiles = []; this.rootFolders.push({ path: "Please Select", id: -1 }); this.qualities.push({ name: "Please Select", id: -1 }); + this.languageProfiles.push({ name: "Please Select", id: -1 }); } public getProfiles(form: FormGroup) { @@ -89,6 +98,18 @@ export class SonarrComponent implements OnInit { }); } + public getLanguageProfiles(form: FormGroup) { + this.langRunning = true; + this.sonarrService.getV3LanguageProfiles(form.value) + .subscribe(x => { + this.languageProfiles = x; + this.languageProfiles.unshift({ name: "Please Select", id: -1 }); + + this.langRunning = false; + this.notificationService.success("Successfully retrieved the Languge Profiles"); + }); + } + public test(form: FormGroup) { if (form.invalid) { this.notificationService.error("Please check your entered values"); diff --git a/src/Ombi/Controllers/External/SonarrController.cs b/src/Ombi/Controllers/External/SonarrController.cs index c3401736d..bc2534ab8 100644 --- a/src/Ombi/Controllers/External/SonarrController.cs +++ b/src/Ombi/Controllers/External/SonarrController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Ombi.Api.Sonarr; using Ombi.Api.Sonarr.Models; +using Ombi.Api.Sonarr.Models.V3; using Ombi.Attributes; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; @@ -16,14 +17,16 @@ namespace Ombi.Controllers.External [Produces("application/json")] public class SonarrController : Controller { - public SonarrController(ISonarrApi sonarr, ISettingsService settings) + public SonarrController(ISonarrApi sonarr, ISonarrV3Api sonarrv3, ISettingsService settings) { SonarrApi = sonarr; + SonarrV3Api = sonarrv3; SonarrSettings = settings; SonarrSettings.ClearCache(); } private ISonarrApi SonarrApi { get; } + private ISonarrV3Api SonarrV3Api { get; } private ISettingsService SonarrSettings { get; } /// @@ -82,5 +85,36 @@ namespace Ombi.Controllers.External return null; } + + /// + /// Gets the Sonarr V3 language profiles + /// + /// + [HttpGet("v3/LanguageProfiles")] + [PowerUser] + public async Task> GetLanguageProfiles() + { + var settings = await SonarrSettings.GetSettingsAsync(); + if (settings.Enabled) + { + return await SonarrV3Api.LanguageProfiles(settings.ApiKey, settings.FullUri); + } + + return null; + } + + + /// + /// Gets the Sonarr V3 language profiles + /// + /// The settings. + /// + [HttpPost("v3/LanguageProfiles")] + [PowerUser] + public async Task> GetLanguageProfiles([FromBody] SonarrSettings settings) + { + return await SonarrV3Api.LanguageProfiles(settings.ApiKey, settings.FullUri); + } + } } \ No newline at end of file From c1e2cad2528ea1643bf07d985a3294f56bda8a08 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 5 Dec 2018 09:47:06 +0000 Subject: [PATCH 128/325] Added Sonarr v3 #2359 --- src/Ombi.Api.Sonarr/Models/NewSeries.cs | 3 +++ src/Ombi.Core/Senders/TvSender.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Ombi.Api.Sonarr/Models/NewSeries.cs b/src/Ombi.Api.Sonarr/Models/NewSeries.cs index ef18baddb..d6f721b0b 100644 --- a/src/Ombi.Api.Sonarr/Models/NewSeries.cs +++ b/src/Ombi.Api.Sonarr/Models/NewSeries.cs @@ -27,6 +27,9 @@ namespace Ombi.Api.Sonarr.Models public int id { get; set; } public List images { get; set; } + // V3 Property + public int languageProfileId { get; set; } + /// /// This is for us /// diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index b6c2aa8af..aadb893d0 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -180,12 +180,7 @@ namespace Ombi.Core.Senders // Are we using v3 sonarr? var sonarrV3 = s.V3; - var languageProfileId = 0; - if (sonarrV3) - { - languageProfileId = s.LanguageProfile; - } - + var languageProfileId = s.LanguageProfile; try { @@ -216,6 +211,11 @@ namespace Ombi.Core.Senders } }; + if (sonarrV3) + { + newSeries.languageProfileId = languageProfileId; + } + // Montitor the correct seasons, // If we have that season in the model then it's monitored! var seasonsToAdd = GetSeasonsToCreate(model); From d3444059dda456419d5fc7dae32ce807f09aa4af Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 5 Dec 2018 20:48:16 +0000 Subject: [PATCH 129/325] Sorted out the sonarr settings UI !wip --- .../app/settings/sonarr/sonarr.component.html | 50 +++++++++++-------- .../app/settings/sonarr/sonarr.component.ts | 5 +- src/Ombi/ClientApp/styles/Styles.scss | 2 +- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html index 91385c353..f016fd56e 100644 --- a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html +++ b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.html @@ -22,34 +22,40 @@
- +
- + - The IP/Hostname is required
- + - The Port is required
- + - The API Key is required
@@ -68,9 +74,10 @@
-
- +
- A Default Quality - Profile is required +
+
+
@@ -94,7 +102,10 @@
- +
- A Default Root Path - is - required
@@ -119,17 +127,17 @@
- +
- + - A Default - Langauage Profile is required
diff --git a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts index ee2438f1b..11845a06e 100644 --- a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts @@ -51,7 +51,7 @@ export class SonarrComponent implements OnInit { addOnly: [x.addOnly], seasonFolders: [x.seasonFolders], v3: [x.v3], - langaugeProfile: [x.languageProfile], + languageProfile: [x.languageProfile], }); if (x.qualityProfile) { @@ -63,6 +63,9 @@ export class SonarrComponent implements OnInit { if(x.languageProfile) { this.getLanguageProfiles(this.form); } + if(x.v3) { + this.form.controls.languageProfile.setValidators([Validators.required]); + } }); this.rootFolders = []; this.qualities = []; diff --git a/src/Ombi/ClientApp/styles/Styles.scss b/src/Ombi/ClientApp/styles/Styles.scss index b41e1c2a7..d98e4cf83 100644 --- a/src/Ombi/ClientApp/styles/Styles.scss +++ b/src/Ombi/ClientApp/styles/Styles.scss @@ -27,4 +27,4 @@ $bg-colour-disabled: #252424; .label { margin: 3px; -} \ No newline at end of file +} From a1c903aa162ed436c33a4290189662eedfe5405f Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 5 Dec 2018 21:06:31 +0000 Subject: [PATCH 130/325] Sorted out some of the settings pages, trying to make it consistent --- .../app/settings/lidarr/lidarr.component.html | 39 +++++--- .../app/settings/radarr/radarr.component.html | 96 +++++++++++-------- .../app/settings/settingsmenu.component.html | 2 +- 3 files changed, 82 insertions(+), 55 deletions(-) diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html index 50938412f..5e898e719 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html @@ -19,25 +19,28 @@
- + - The IP/Hostname is required
- + - The Port is required +
- + - The API Key is required +
@@ -56,19 +59,22 @@
- +
- - A Default Quality Profile is required
- +
@@ -89,12 +97,14 @@
- A Language profile is required
- +
- A Metadata profile is required
diff --git a/src/Ombi/ClientApp/app/settings/radarr/radarr.component.html b/src/Ombi/ClientApp/app/settings/radarr/radarr.component.html index 909a64226..08a8035c2 100644 --- a/src/Ombi/ClientApp/app/settings/radarr/radarr.component.html +++ b/src/Ombi/ClientApp/app/settings/radarr/radarr.component.html @@ -1,5 +1,4 @@ - - +
Radarr Settings @@ -19,25 +18,34 @@
- + - - The IP/Hostname is required +
- + - - The Port is required +
- - - - The API Key is required + + +
@@ -49,63 +57,73 @@
- +
+
-
- -
-
-
- +
- +
- A Default Quality Profile is required
-
-
- -
- -
- +
- + -
- A Default Root Path is required + + +
+ +
- +
-
- - A Default Minimum Availability is required
- +
+
+
- +
@@ -118,4 +136,4 @@
-
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index 59ce35c32..f77e77501 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -54,7 +54,7 @@ Music From 4eeb5d4d355cd89025ba53471e53243ffa1215f1 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 5 Dec 2018 21:24:50 +0000 Subject: [PATCH 131/325] Sorted out the UI !wip --- src/Ombi.Store/Entities/RequestType.cs | 6 +----- src/Ombi/ClientApp/app/interfaces/IRequestModel.ts | 4 ++-- src/Ombi/ClientApp/app/services/requestretry.service.ts | 4 ++-- .../settings/failedrequests/failedrequest.component.html | 2 +- .../settings/failedrequests/failedrequests.component.ts | 9 +++++++-- .../ClientApp/app/settings/settingsmenu.component.html | 1 + src/Ombi/Controllers/RequestRetryController.cs | 2 +- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Ombi.Store/Entities/RequestType.cs b/src/Ombi.Store/Entities/RequestType.cs index 151453bdd..4d2d20ac4 100644 --- a/src/Ombi.Store/Entities/RequestType.cs +++ b/src/Ombi.Store/Entities/RequestType.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Ombi.Store.Entities +namespace Ombi.Store.Entities { public enum RequestType { diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index 5a72abf31..b083ca088 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -1,9 +1,9 @@ import { IUser } from "./IUser"; export enum RequestType { + tvShow = 0, movie = 1, - tvShow = 2, - album = 3, + album = 2, } // NEW WORLD diff --git a/src/Ombi/ClientApp/app/services/requestretry.service.ts b/src/Ombi/ClientApp/app/services/requestretry.service.ts index 9803f73f7..e5c9cabe0 100644 --- a/src/Ombi/ClientApp/app/services/requestretry.service.ts +++ b/src/Ombi/ClientApp/app/services/requestretry.service.ts @@ -15,7 +15,7 @@ export class RequestRetryService extends ServiceHelpers { public getFailedRequests(): Observable { return this.http.get(this.url, {headers: this.headers}); } - public deleteFailedRequest(failedId: number): Observable { - return this.http.delete(`${this.url}/${failedId}`, {headers: this.headers}); + public deleteFailedRequest(failedId: number): Observable { + return this.http.delete(`${this.url}/${failedId}`, {headers: this.headers}); } } diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html index c0cc2ca1e..898710199 100644 --- a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequest.component.html @@ -20,7 +20,7 @@ {{RequestType[v.type] | humanize}} {{v.retryCount}} - + diff --git a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts index 65be04a22..a303ac713 100644 --- a/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts +++ b/src/Ombi/ClientApp/app/settings/failedrequests/failedrequests.component.ts @@ -16,7 +16,12 @@ export class FailedRequestsComponent implements OnInit { this.retry.getFailedRequests().subscribe(x => this.vm = x); } - public remove(failedId: number) { - this.retry.deleteFailedRequest(failedId).subscribe(); + public remove(failed: IFailedRequestsViewModel) { + this.retry.deleteFailedRequest(failed.failedId).subscribe(x => { + if(x) { + const index = this.vm.indexOf(failed); + this.vm.splice(index,1); + } + }); } } diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index 59ce35c32..eae56bce2 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -84,6 +84,7 @@
-   - \ No newline at end of file + + From 2500c062709fd9659518ae49edbb919c73615d59 Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Tue, 11 Dec 2018 13:16:52 +0100 Subject: [PATCH 134/325] Update HtmlTemplateGenerator.cs --- .../Jobs/Ombi/HtmlTemplateGenerator.cs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 09b7d9858..0dba6d1d3 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -7,18 +7,18 @@ namespace Ombi.Schedule.Jobs.Ombi { protected virtual void AddBackgroundInsideTable(StringBuilder sb, string url) { - sb.Append(""); - sb.AppendFormat("", url); + sb.Append("
"); + sb.AppendFormat("", url); sb.Append(""); - sb.Append("
"); - sb.Append(""); + sb.Append("
"); + sb.Append(""); } protected virtual void AddPosterInsideTable(StringBuilder sb, string url) { sb.Append(""); - sb.Append("
"); - sb.AppendFormat("", url); + sb.Append("
"); + sb.AppendFormat("", url); } protected virtual void AddMediaServerUrl(StringBuilder sb, string mediaurl, string url) @@ -27,10 +27,10 @@ namespace Ombi.Schedule.Jobs.Ombi { sb.Append(""); sb.Append( - ""); @@ -44,16 +44,16 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddInfoTable(StringBuilder sb) { sb.Append( - "
"); + ""); sb.AppendFormat("", mediaurl); sb.AppendFormat( - "", + "", url); sb.Append(""); sb.Append(""); + ""); sb.Append(""); } protected virtual void AddTitle(StringBuilder sb, string url, string title) { - sb.Append(""); - sb.Append(""); + sb.Append(""); sb.Append(""); @@ -61,30 +61,30 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddParagraph(StringBuilder sb, string text) { - sb.Append(""); - sb.Append(""); + sb.Append(""); sb.Append(""); } protected virtual void AddTvParagraph(StringBuilder sb, string episodes, string summary) { - sb.Append(""); - sb.Append(""); + sb.Append(""); sb.Append(""); } protected virtual void AddGenres(StringBuilder sb, string text) { - sb.Append(""); - sb.Append(""); + sb.Append(""); sb.Append(""); } } -} \ No newline at end of file +} From a1026f8055d2351bf97062f67f95e944cec3681b Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Tue, 11 Dec 2018 13:17:24 +0100 Subject: [PATCH 135/325] Update NewsletterTemplate.html --- .../Templates/NewsletterTemplate.html | 126 ++++++++++++++++-- 1 file changed, 117 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 469f0dc90..f133cabb7 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -2,8 +2,8 @@ - - + + Ombi -
"); - if(url.HasValue()) sb.AppendFormat("", url); - sb.AppendFormat("

{0}

", title); + sb.Append("
"); + if(url.HasValue()) sb.AppendFormat("", url); + sb.AppendFormat("

{0}

", title); if (url.HasValue()) sb.Append("
"); sb.Append("
"); - sb.AppendFormat("

{0}

", text); + sb.Append("
"); + sb.AppendFormat("

{0}

", text); sb.Append("
"); - sb.AppendFormat("

{0}

", episodes); - sb.AppendFormat("
{0}
", summary); + sb.Append("
"); + sb.AppendFormat("

{0}

", episodes); + sb.AppendFormat("{0}"", summary); sb.Append("
"); - sb.AppendFormat("{0}", text); + sb.Append("
"); + sb.AppendFormat("{0}"", text); sb.Append("
From dfb15150794625f3c7b73427cb2f629d293f8e18 Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Tue, 11 Dec 2018 14:29:48 +0100 Subject: [PATCH 136/325] fixes build --- src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 0dba6d1d3..96814402a 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -73,7 +73,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); sb.Append(""); sb.Append(""); } @@ -82,7 +82,7 @@ namespace Ombi.Schedule.Jobs.Ombi { sb.Append(""); sb.Append(""); sb.Append(""); } From 960dbbcf4ecb6d32b372e1eb2902ee5d41603c2c Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Tue, 11 Dec 2018 15:00:32 +0100 Subject: [PATCH 137/325] this should fix the build for sure (stupid quotes) --- src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 96814402a..366f666ac 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -73,7 +73,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); sb.Append(""); sb.Append(""); } @@ -82,7 +82,7 @@ namespace Ombi.Schedule.Jobs.Ombi { sb.Append(""); sb.Append(""); sb.Append(""); } From c8b7229e53cecb893603ddea3756ab37b1c5b900 Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Tue, 11 Dec 2018 16:51:59 +0100 Subject: [PATCH 138/325] fixed titles --- src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 366f666ac..ea4a071e7 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -50,10 +50,10 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddTitle(StringBuilder sb, string url, string title) { - sb.Append(""); + sb.Append(""); sb.Append(""); sb.Append(""); From b9ab0e486134c7ed8f5d42889de7041495e11aa9 Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Tue, 11 Dec 2018 16:52:13 +0100 Subject: [PATCH 139/325] Update NewsletterTemplate.html --- .../Templates/NewsletterTemplate.html | 116 ++++++++++-------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index f133cabb7..9f1f33f28 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -40,8 +40,7 @@ } table td { - font-family: sans-serif; - font-size: 14px; + font-family: 'Open Sans', Helvetica, Arial, sans-serif; vertical-align: top; } @@ -97,6 +96,7 @@ padding-top: 10px; } + .media-card { font-family: 'Open Sans', Helvetica, Arial, sans-serif; vertical-align: top; @@ -106,6 +106,7 @@ max-width: 500px; height: 252px; max-height: 252px; + min-height: 252px; } .card-bg { @@ -150,16 +151,17 @@ height: 227px; } - .title { + .title h1 { font-family: 'Open Sans', Helvetica, Arial, sans-serif; + font-size: 1.5rem; vertical-align: top; text-overflow: ellipsis; - overflow: hidden; - padding: 5px; - max-height: 130px; + padding-left: 5px; + max-height: 50px; max-width: 320px; overflow: hidden; display: block; + margin: 0; } .description { @@ -316,7 +318,8 @@ color: #ff761b; font-family: sans-serif; font-weight: 400; - line-height: 1.4; + font-size: 1.2rem; + line-height: 1.3rem; margin: 0 auto; text-transform: capitalize; } @@ -416,52 +419,65 @@ - - - - "); sb.Append(""); sb.Append(""); @@ -61,7 +61,7 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddParagraph(StringBuilder sb, string text) { - sb.Append(""); + sb.Append(""); sb.Append(""); From 2fbb76555d3c23fdf4acc33f7a3458c419423c0f Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Tue, 11 Dec 2018 22:44:35 +0100 Subject: [PATCH 144/325] Update NewsletterTemplate.html --- .../Templates/NewsletterTemplate.html | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 9f1f33f28..c1849542d 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -144,7 +144,6 @@ .movie-info { font-family: 'Open Sans', Helvetica, Arial, sans-serif; - font-size: 14px; vertical-align: top; padding-left: 4px; text-align: left; @@ -153,13 +152,12 @@ .title h1 { font-family: 'Open Sans', Helvetica, Arial, sans-serif; - font-size: 1.5rem; + font-size: 1.3rem; + line-height: 1.4rem; vertical-align: top; - text-overflow: ellipsis; - padding-left: 5px; - max-height: 50px; max-width: 320px; overflow: hidden; + text-overflow: ellipsis; display: block; margin: 0; } @@ -167,14 +165,15 @@ .description { font-family: 'Open Sans', Helvetica, Arial, sans-serif; vertical-align: top; - padding: 5px; - height: 100%; + height: 130px; max-height: 130px; max-width: 320px; overflow: hidden; - display: block; + text-overflow: ellipsis; margin: 0px; + display: block; font-size: 0.8rem !important; + text-align: justify; } .meta { @@ -223,7 +222,7 @@ font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-weight: 400; line-height: 1.4rem; - font-size: 1.5rem; + font-size: 1.3rem; margin: 0; text-transform: capitalize; } @@ -234,7 +233,6 @@ font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-weight: normal; margin: 0; - margin-bottom: 15px; } p li, From 15920cdd50615bbcedaf0a5babccdaa110173df6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Dec 2018 07:01:18 +0000 Subject: [PATCH 145/325] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7da4cd6d8..debc40f62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v3.0.3988 (2018-11-23) +## v3.0.4036 (2018-12-11) From 3e647249697e88efd32cbc3b794a26519dfce463 Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Thu, 13 Dec 2018 18:33:57 +0100 Subject: [PATCH 146/325] Update HtmlTemplateGenerator.cs --- src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 000eba669..03f4ef96f 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -50,10 +50,10 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddTitle(StringBuilder sb, string url, string title) { - sb.Append(""); + sb.Append(""); sb.Append(""); sb.Append(""); From 9943a1b5a57fdda390b4bafa3a267ea820c75b6a Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Thu, 13 Dec 2018 18:34:07 +0100 Subject: [PATCH 147/325] Update NewsletterTemplate.html --- .../Templates/NewsletterTemplate.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index c1849542d..7a8baf7f0 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -160,6 +160,9 @@ text-overflow: ellipsis; display: block; margin: 0; + height: 100%; + min-height: 20px; + max-height: 45px; } .description { @@ -313,13 +316,9 @@ @media only screen and (max-width: 1059px) { table[class=body] h1 { - color: #ff761b; - font-family: sans-serif; - font-weight: 400; font-size: 1.2rem; line-height: 1.3rem; margin: 0 auto; - text-transform: capitalize; } table[class=body] p, From 27e15a76bc1236ac8970f75c752e945138f7e6a1 Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Thu, 13 Dec 2018 19:26:11 +0100 Subject: [PATCH 148/325] Update HtmlTemplateGenerator.cs --- src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 03f4ef96f..a52abb16a 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -50,10 +50,10 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddTitle(StringBuilder sb, string url, string title) { - sb.Append(""); + sb.Append(""); sb.Append(""); sb.Append(""); From 14c40a106ea862f9788e5945167b45a123ba60da Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Thu, 13 Dec 2018 19:26:22 +0100 Subject: [PATCH 149/325] Update NewsletterTemplate.html --- .../Templates/NewsletterTemplate.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 7a8baf7f0..436d87c28 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -156,8 +156,7 @@ line-height: 1.4rem; vertical-align: top; max-width: 320px; - overflow: hidden; - text-overflow: ellipsis; + white-space: normal; display: block; margin: 0; height: 100%; @@ -319,6 +318,7 @@ font-size: 1.2rem; line-height: 1.3rem; margin: 0 auto; + white-space: normal; } table[class=body] p, From a95e904c8b91cb471edc38de59ce06bb2fceee2d Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Thu, 13 Dec 2018 21:25:12 +0100 Subject: [PATCH 150/325] android please be nice now --- src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index a52abb16a..412a19943 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -50,10 +50,10 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddTitle(StringBuilder sb, string url, string title) { - sb.Append(""); + sb.Append(""); sb.Append(""); sb.Append(""); @@ -61,7 +61,7 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddParagraph(StringBuilder sb, string text) { - sb.Append(""); + sb.Append(""); sb.Append(""); @@ -70,7 +70,7 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddTvParagraph(StringBuilder sb, string episodes, string summary) { - sb.Append(""); + sb.Append(""); sb.Append(""); + sb.Append(""); sb.Append(""); sb.Append(""); From cac08cf808e5cd0e73e4881ec4af63325b0cb6fa Mon Sep 17 00:00:00 2001 From: d1slact0r <3063928+d1slact0r@users.noreply.github.com> Date: Thu, 13 Dec 2018 21:57:40 +0100 Subject: [PATCH 153/325] Update NewsletterTemplate.html --- .../Templates/NewsletterTemplate.html | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 1095e93e5..5456743c9 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -156,10 +156,11 @@ line-height: 24px; vertical-align: top; max-width: 320px; + white-space: normal; display: block; - height: 100%; - min-height: 20px; - max-height: 45px; + height: 50px; + min-height: 50px; + max-height: 50px; } .description { @@ -312,8 +313,6 @@ @media only screen and (max-width: 1059px) { table[class=body] h1 { font-size: 22px; - padding: 0 !important; - margin: 0 !important; } table[class=body] p, From d67101cc0777094f90d8bb3bc29063a862ddb069 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 15 Dec 2018 01:15:30 +0000 Subject: [PATCH 154/325] Update EmbyEpisodeSync.cs --- src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index 23ad24268..2bb417d3d 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -83,7 +83,7 @@ namespace Ombi.Schedule.Jobs.Emby { processed++; - if (ep.LocationType.Equals("Virtual", StringComparison.InvariantCultureIgnoreCase)) + if (ep.LocationType?.Equals("Virtual", StringComparison.InvariantCultureIgnoreCase) ?? false) { // For some reason Emby is not respecting the `IsVirtualItem` field. continue; @@ -154,4 +154,4 @@ namespace Ombi.Schedule.Jobs.Emby GC.SuppressFinalize(this); } } -} \ No newline at end of file +} From 43e30ec0bb509ed6312f259a15755bc284e3273c Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 09:52:04 +0000 Subject: [PATCH 155/325] Updated to .net core 2.2 and included a linux-arm64 build --- appveyor.yml | 12 +++++----- build.cake | 21 ++---------------- .../Ombi.Api.Mattermost.csproj | 2 +- src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj | 2 +- src/Ombi.Api.Service/Ombi.Api.Service.csproj | 2 +- src/Ombi.Api/Ombi.Api.csproj | 4 ++-- src/Ombi.Core.Tests/Ombi.Core.Tests.csproj | 4 ++-- src/Ombi.Core/Ombi.Core.csproj | 8 +++---- .../Ombi.DependencyInjection.csproj | 6 ++--- src/Ombi.Helpers/Ombi.Helpers.csproj | 6 ++--- .../Ombi.Notifications.Tests.csproj | 4 ++-- .../Ombi.Schedule.Tests.csproj | 6 ++--- src/Ombi.Schedule/Ombi.Schedule.csproj | 6 ++--- src/Ombi.Settings/Ombi.Settings.csproj | 4 ++-- src/Ombi.Store/Ombi.Store.csproj | 10 ++++----- src/Ombi.Tests/Ombi.Tests.csproj | 6 ++--- src/Ombi.Updater/Ombi.Updater.csproj | 22 +++++++++---------- src/Ombi/Ombi.csproj | 20 ++++++++--------- 18 files changed, 64 insertions(+), 81 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 448e1b9c8..2715e44d7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,22 +27,22 @@ test: off after_build: - cmd: >- - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.1\windows.zip" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\windows.zip" - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.1\osx.tar.gz" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\osx.tar.gz" - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.1\linux.tar.gz" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux.tar.gz" - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.1\linux-arm.tar.gz" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.\linux-arm.tar.gz" - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.1\windows-32bit.zip" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\windows-32bit.zip" -# appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.0\linux-arm64.tar.gz" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux-arm64.tar.gz" diff --git a/build.cake b/build.cake index d706e7b6b..8333bd3a1 100644 --- a/build.cake +++ b/build.cake @@ -26,7 +26,7 @@ var csProj = "./src/Ombi/Ombi.csproj"; // Path to the project.csproj var solutionFile = "Ombi.sln"; // Solution file if needed GitVersion versionInfo = null; -var frameworkVer = "netcoreapp2.1"; +var frameworkVer = "netcoreapp2.2"; var buildSettings = new DotNetCoreBuildSettings { @@ -47,7 +47,6 @@ var windowsArtifactsFolder = artifactsFolder + "win10-x64/published"; var windows32BitArtifactsFolder = artifactsFolder + "win10-x86/published"; var osxArtifactsFolder = artifactsFolder + "osx-x64/published"; var linuxArtifactsFolder = artifactsFolder + "linux-x64/published"; -var linuxArmArtifactsFolder = artifactsFolder + "linux-arm/published"; var linuxArm64BitArtifactsFolder = artifactsFolder + "linux-arm64/published"; @@ -150,8 +149,7 @@ Task("Package") Zip(windows32BitArtifactsFolder +"/",artifactsFolder + "windows-32bit.zip"); GZipCompress(osxArtifactsFolder, artifactsFolder + "osx.tar.gz"); GZipCompress(linuxArtifactsFolder, artifactsFolder + "linux.tar.gz"); - GZipCompress(linuxArmArtifactsFolder, artifactsFolder + "linux-arm.tar.gz"); - //GZipCompress(linuxArm64BitArtifactsFolder, artifactsFolder + "linux-arm64.tar.gz"); + GZipCompress(linuxArm64BitArtifactsFolder, artifactsFolder + "linux-arm64.tar.gz"); }); Task("Publish") @@ -160,7 +158,6 @@ Task("Publish") .IsDependentOn("Publish-Windows-32bit") .IsDependentOn("Publish-OSX") .IsDependentOn("Publish-Linux") - .IsDependentOn("Publish-Linux-ARM") .IsDependentOn("Publish-Linux-ARM-64Bit") .IsDependentOn("Package"); @@ -217,20 +214,6 @@ Task("Publish-Linux") DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); }); -Task("Publish-Linux-ARM") - .Does(() => -{ - publishSettings.Runtime = "linux-arm"; - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer+"/linux-arm/published"); - - DotNetCorePublish("./src/Ombi/Ombi.csproj", publishSettings); - CopyFile( - buildDir + "/"+frameworkVer+"/linux-arm/Swagger.xml", - buildDir + "/"+frameworkVer+"/linux-arm/published/Swagger.xml"); - - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/linux-arm/published/updater"); - DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); -}); Task("Publish-Linux-ARM-64Bit") .Does(() => diff --git a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj index 83318be7b..98292f463 100644 --- a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj +++ b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj index 0c615f301..9f25a7946 100644 --- a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj +++ b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/Ombi.Api.Service/Ombi.Api.Service.csproj b/src/Ombi.Api.Service/Ombi.Api.Service.csproj index 8cbddd874..bd53c9808 100644 --- a/src/Ombi.Api.Service/Ombi.Api.Service.csproj +++ b/src/Ombi.Api.Service/Ombi.Api.Service.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Ombi.Api/Ombi.Api.csproj b/src/Ombi.Api/Ombi.Api.csproj index a37c128fb..e20dd6ccd 100644 --- a/src/Ombi.Api/Ombi.Api.csproj +++ b/src/Ombi.Api/Ombi.Api.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj index d20176ec4..23fc6db78 100644 --- a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj +++ b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp2.2 @@ -10,7 +10,7 @@ - + diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 10e07822a..1748fcc2c 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -11,11 +11,11 @@ - - - + + + - + diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 028c37b43..ec905e718 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/Ombi.Helpers/Ombi.Helpers.csproj b/src/Ombi.Helpers/Ombi.Helpers.csproj index 2aaaa076f..5dedaff61 100644 --- a/src/Ombi.Helpers/Ombi.Helpers.csproj +++ b/src/Ombi.Helpers/Ombi.Helpers.csproj @@ -10,9 +10,9 @@ - - - + + + diff --git a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj index 5d5d3b9d0..5436dff22 100644 --- a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj +++ b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj @@ -1,14 +1,14 @@  - netcoreapp2.1 + netcoreapp2.2 - + diff --git a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj index ca07f635f..0c83dd755 100644 --- a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj +++ b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj @@ -1,16 +1,16 @@ - netcoreapp2.1 + netcoreapp2.2 - + - + diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index 06cc2bb49..b262b79d2 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -10,13 +10,13 @@ - - + + - + diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj index 19a415a47..6db0768aa 100644 --- a/src/Ombi.Settings/Ombi.Settings.csproj +++ b/src/Ombi.Settings/Ombi.Settings.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index cdbd3fe84..f68d1d752 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -10,11 +10,11 @@ - - - - - + + + + + diff --git a/src/Ombi.Tests/Ombi.Tests.csproj b/src/Ombi.Tests/Ombi.Tests.csproj index 55c66b80c..fdfec1cb2 100644 --- a/src/Ombi.Tests/Ombi.Tests.csproj +++ b/src/Ombi.Tests/Ombi.Tests.csproj @@ -1,18 +1,18 @@ - netcoreapp2.1 + netcoreapp2.2 false - + - + diff --git a/src/Ombi.Updater/Ombi.Updater.csproj b/src/Ombi.Updater/Ombi.Updater.csproj index 07fb92d81..6220a100b 100644 --- a/src/Ombi.Updater/Ombi.Updater.csproj +++ b/src/Ombi.Updater/Ombi.Updater.csproj @@ -3,7 +3,7 @@ Exe win10-x64;win10-x86;osx-x64;ubuntu-x64;debian.8-x64;centos.7-x64;linux-x64;linux-arm;linux-arm64; - netcoreapp2.1 + netcoreapp2.2 3.0.0.0 3.0.0.0 @@ -12,17 +12,17 @@ - - - - - - - - - + + + + + + + + + - + \ No newline at end of file diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 7489ad77f..cf3bff48f 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 - win10-x64;win10-x86;osx-x64;ubuntu-x64;debian.8-x64;centos.7-x64;linux-x64;linux-arm;linux-arm64; + netcoreapp2.2 + win10-x64;win10-x86;osx-x64;linux-x64;linux-arm64; false Latest $(SemVer) @@ -65,23 +65,23 @@ - + - - - - + + + + - + - + - + From 222871c22836c8ba06045c4e7b2e431782b65627 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 10:18:06 +0000 Subject: [PATCH 156/325] Fixed build --- appveyor.yml | 2 +- .../music-placeholder.psd | Bin package-lock.json | 291 ------------------ src/Ombi/Program.cs | 7 +- 4 files changed, 4 insertions(+), 296 deletions(-) rename music-placeholder.psd => assets/music-placeholder.psd (100%) delete mode 100644 package-lock.json diff --git a/appveyor.yml b/appveyor.yml index 2715e44d7..53d1263c6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -42,7 +42,7 @@ after_build: appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\windows-32bit.zip" - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux-arm64.tar.gz" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux-arm64.tar.gz" diff --git a/music-placeholder.psd b/assets/music-placeholder.psd similarity index 100% rename from music-placeholder.psd rename to assets/music-placeholder.psd diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 10c7546e4..000000000 --- a/package-lock.json +++ /dev/null @@ -1,291 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "1.0.3" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "1.9.1" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.11" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" - }, - "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", - "requires": { - "path-parse": "1.0.5" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "tslib": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz", - "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==" - }, - "tslint": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.10.0.tgz", - "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=", - "requires": { - "babel-code-frame": "6.26.0", - "builtin-modules": "1.1.1", - "chalk": "2.4.1", - "commander": "2.15.1", - "diff": "3.5.0", - "glob": "7.1.2", - "js-yaml": "3.12.0", - "minimatch": "3.0.4", - "resolve": "1.7.1", - "semver": "5.5.0", - "tslib": "1.9.2", - "tsutils": "2.27.1" - } - }, - "tsutils": { - "version": "2.27.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.27.1.tgz", - "integrity": "sha512-AE/7uzp32MmaHvNNFES85hhUDHFdFZp6OAiZcd6y4ZKKIg6orJTm8keYWBhIhrJQH3a4LzNKat7ZPXZt5aTf6w==", - "requires": { - "tslib": "1.9.2" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - } - } -} diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 3a11093d2..d9631410e 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -95,7 +95,7 @@ namespace Ombi Console.WriteLine($"We are running on {urlValue}"); - BuildWebHost(args).Run(); + CreateWebHostBuilder(args).Build().Run(); } /// @@ -245,12 +245,11 @@ namespace Ombi } } - public static IWebHost BuildWebHost(string[] args) => + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() .UseUrls(UrlArgs) - .PreferHostingUrls(true) - .Build(); + .PreferHostingUrls(true); private static string HelpOutput(ParserResult args) { From da841d173ad9f362ca4d5777af7c2529e5d518cc Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 10:46:37 +0000 Subject: [PATCH 157/325] fixed appveyor !wip --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 53d1263c6..2dfb5b17c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,7 +36,7 @@ after_build: appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux.tar.gz" - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.\linux-arm.tar.gz" + appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux-arm.tar.gz" appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\windows-32bit.zip" From f7d1ca66739b9b61c89da6776dd220909c178e12 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 12:06:06 +0000 Subject: [PATCH 158/325] Really did fix it this time !wip --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2dfb5b17c..edd53f512 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,9 +36,6 @@ after_build: appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux.tar.gz" - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\linux-arm.tar.gz" - - appveyor PushArtifact "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp2.2\windows-32bit.zip" From 3c1f23ea92e6a30b148ebfebebbe72f14027fdb7 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:21:24 +0000 Subject: [PATCH 159/325] Fixed a bug with us thinking future dated emby episodes are not available, Consoldated the emby and plex search rules (since they have the same logic) --- .../Rule/Rules/Search/AvailabilityRuleBase.cs | 97 +++++++++++++++++++ .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 45 ++++----- .../Rule/Rules/Search/PlexAvailabilityRule.cs | 50 ++-------- 3 files changed, 126 insertions(+), 66 deletions(-) create mode 100644 src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleBase.cs diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleBase.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleBase.cs new file mode 100644 index 000000000..25cf30492 --- /dev/null +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleBase.cs @@ -0,0 +1,97 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; +using Ombi.Core.Models.Search; +using Ombi.Store.Entities; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Core.Rule.Rules.Search +{ + public abstract class AvailabilityRuleBase : BaseSearchRule + { + public void CheckForUnairedEpisodes(SearchTvShowViewModel search) + { + if (search.SeasonRequests.All(x => x.Episodes.All(e => e.Available))) + { + search.FullyAvailable = true; + } + else + { + var airedButNotAvailable = search.SeasonRequests.Any(x => + x.Episodes.Any(c => !c.Available && c.AirDate <= DateTime.Now.Date && c.AirDate != DateTime.MinValue)); + if (!airedButNotAvailable) + { + var unairedEpisodes = search.SeasonRequests.Any(x => + x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date)); + if (unairedEpisodes) + { + search.FullyAvailable = true; + } + } + } + } + + public async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, + SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb) + { + PlexEpisode epExists = null; + if (useImdb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.ImdbId == item.ImdbId.ToString()); + } + + if (useTheMovieDb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.TheMovieDbId == item.TheMovieDbId.ToString()); + } + + if (useTvDb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.TvDbId == item.TvDbId.ToString()); + } + + if (epExists != null) + { + episode.Available = true; + } + } + public async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, + SeasonRequests season, EmbyContent item, bool useTheMovieDb, bool useTvDb) + { + EmbyEpisode epExists = null; + if (useImdb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.ImdbId == item.ImdbId.ToString()); + } + + if (useTheMovieDb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.TheMovieDbId == item.TheMovieDbId.ToString()); + } + + if (useTvDb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.TvDbId == item.TvDbId.ToString()); + } + + if (epExists != null) + { + episode.Available = true; + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 486de9ea8..0d7c56372 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -3,15 +3,17 @@ using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; namespace Ombi.Core.Rule.Rules.Search { - public class EmbyAvailabilityRule : BaseSearchRule, IRules + public class EmbyAvailabilityRule : AvailabilityRuleBase, IRules { public EmbyAvailabilityRule(IEmbyContentRepository repo) { @@ -23,15 +25,27 @@ namespace Ombi.Core.Rule.Rules.Search public async Task Execute(SearchViewModel obj) { EmbyContent item = null; + var useImdb = false; + var useTheMovieDb = false; + var useTvDb = false; + if (obj.ImdbId.HasValue()) { item = await EmbyContentRepository.GetByImdbId(obj.ImdbId); + if (item != null) + { + useImdb = true; + } } if (item == null) { if (obj.TheMovieDbId.HasValue()) { item = await EmbyContentRepository.GetByTheMovieDbId(obj.TheMovieDbId); + if (item != null) + { + useTheMovieDb = true; + } } if (item == null) @@ -39,10 +53,14 @@ namespace Ombi.Core.Rule.Rules.Search if (obj.TheTvDbId.HasValue()) { item = await EmbyContentRepository.GetByTvDbId(obj.TheTvDbId); + if (item != null) + { + useTvDb = true; + } } } } - + if (item != null) { obj.Available = true; @@ -59,29 +77,12 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - EmbyEpisode epExists = null; - - if (item.HasImdb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(e => e.EpisodeNumber == episode.EpisodeNumber && e.SeasonNumber == season.SeasonNumber - && e.ImdbId == item.ImdbId); - } if (item.HasTvDb && epExists == null) - { - epExists = await allEpisodes.FirstOrDefaultAsync(e => e.EpisodeNumber == episode.EpisodeNumber && e.SeasonNumber == season.SeasonNumber - && e.Series.TvDbId == item.TvDbId); - } if (item.HasTheMovieDb && epExists == null) - { - epExists = await allEpisodes.FirstOrDefaultAsync(e => e.EpisodeNumber == episode.EpisodeNumber && e.SeasonNumber == season.SeasonNumber - && e.TheMovieDbId == item.TheMovieDbId); - } - - if (epExists != null) - { - episode.Available = true; - } + await SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); } } } + + CheckForUnairedEpisodes(search); } } return Success(); diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index e1ddcecd0..575d49d62 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -7,10 +7,11 @@ using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; namespace Ombi.Core.Rule.Rules.Search { - public class PlexAvailabilityRule : BaseSearchRule, IRules + public class PlexAvailabilityRule : AvailabilityRuleBase, IRules { public PlexAvailabilityRule(IPlexContentRepository repo) { @@ -74,56 +75,17 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - PlexEpisode epExists = null; - if (useImdb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId.ToString()); - } - if (useTheMovieDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId.ToString()); - } - if (useTvDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId.ToString()); - } - - if (epExists != null) - { - episode.Available = true; - } + await SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); } } - if (search.SeasonRequests.All(x => x.Episodes.All(e => e.Available))) - { - search.FullyAvailable = true; - } - else - { - var airedButNotAvailable = search.SeasonRequests.Any(x => - x.Episodes.Any(c => !c.Available && c.AirDate <= DateTime.Now.Date)); - if (!airedButNotAvailable) - { - var unairedEpisodes = search.SeasonRequests.Any(x => - x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date)); - if (unairedEpisodes) - { - search.FullyAvailable = true; - } - } - - } + CheckForUnairedEpisodes(search); } } } return Success(); } + + } } \ No newline at end of file From 0cc57c3c1fd5b003b3ef051c683f948935c3459e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:31:04 +0000 Subject: [PATCH 160/325] !wip improved the API's documentation started on the deny reason --- src/Ombi.Core/Engine/IMusicRequestEngine.cs | 2 +- .../Engine/Interfaces/IMovieRequestEngine.cs | 2 +- .../Engine/Interfaces/ITvRequestEngine.cs | 2 +- src/Ombi.Core/Engine/MovieRequestEngine.cs | 3 +- src/Ombi.Core/Engine/MusicRequestEngine.cs | 3 +- src/Ombi.Core/Engine/TvRequestEngine.cs | 3 +- .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 6 +--- .../Rule/Rules/Search/PlexAvailabilityRule.cs | 5 +-- .../Controllers/External/PlexController.cs | 1 - src/Ombi/Controllers/IdentityController.cs | 6 ++-- src/Ombi/Controllers/ImagesController.cs | 3 +- src/Ombi/Controllers/IssuesController.cs | 3 +- src/Ombi/Controllers/JobController.cs | 3 +- src/Ombi/Controllers/LandingPageController.cs | 3 +- src/Ombi/Controllers/LoggingController.cs | 3 +- src/Ombi/Controllers/MobileController.cs | 5 ++- .../Controllers/MusicRequestController.cs | 7 ++-- .../Controllers/NotificationsController.cs | 3 +- src/Ombi/Controllers/PlexOAuthController.cs | 1 + .../Controllers/RecentlyAddedController.cs | 3 +- src/Ombi/Controllers/RequestController.cs | 14 ++++---- .../Controllers/RequestRetryController.cs | 1 + src/Ombi/Controllers/SearchController.cs | 3 +- src/Ombi/Controllers/SettingsController.cs | 3 +- src/Ombi/Controllers/StatsController.cs | 3 +- src/Ombi/Controllers/StatusController.cs | 3 +- src/Ombi/Controllers/TokenController.cs | 8 ++++- src/Ombi/Controllers/UpdateController.cs | 3 +- src/Ombi/Controllers/VoteController.cs | 3 +- src/Ombi/Models/DenyAlbumMOdel.cs | 33 +++++++++++++++++++ src/Ombi/Models/DenyMovieModel.cs | 33 +++++++++++++++++++ src/Ombi/Models/DenyTvModel.cs | 33 +++++++++++++++++++ src/Ombi/Ombi.csproj | 2 ++ src/Ombi/Startup.cs | 3 ++ 34 files changed, 168 insertions(+), 44 deletions(-) create mode 100644 src/Ombi/Models/DenyAlbumMOdel.cs create mode 100644 src/Ombi/Models/DenyMovieModel.cs create mode 100644 src/Ombi/Models/DenyTvModel.cs diff --git a/src/Ombi.Core/Engine/IMusicRequestEngine.cs b/src/Ombi.Core/Engine/IMusicRequestEngine.cs index 5caba8a34..02a051343 100644 --- a/src/Ombi.Core/Engine/IMusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/IMusicRequestEngine.cs @@ -12,7 +12,7 @@ namespace Ombi.Core.Engine { TaskApproveAlbum(AlbumRequest request); Task ApproveAlbumById(int requestId); - Task DenyAlbumById(int modelId); + Task DenyAlbumById(int modelId, string reason); Task> GetRequests(); Task> GetRequests(int count, int position, OrderFilterModel orderFilter); Task GetTotal(); diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index bb8b9e64d..d741dc8bc 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -17,6 +17,6 @@ namespace Ombi.Core.Engine.Interfaces Task UpdateMovieRequest(MovieRequests request); Task ApproveMovie(MovieRequests request); Task ApproveMovieById(int requestId); - Task DenyMovieById(int modelId); + Task DenyMovieById(int modelId, string denyReason); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs index 36ae7da61..63de72bd1 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs @@ -12,7 +12,7 @@ namespace Ombi.Core.Engine.Interfaces Task RemoveTvRequest(int requestId); Task GetTvRequest(int requestId); Task RequestTvShow(TvRequestViewModel tv); - Task DenyChildRequest(int requestId); + Task DenyChildRequest(int requestId, string reason); Task> GetRequestsLite(int count, int position, OrderFilterModel type); Task> SearchTvRequest(string search); Task UpdateTvRequest(TvRequests request); diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 16fd7667b..fcbb0ac3b 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -305,7 +305,7 @@ namespace Ombi.Core.Engine return await ApproveMovie(request); } - public async Task DenyMovieById(int modelId) + public async Task DenyMovieById(int modelId, string denyReason) { var request = await MovieRepository.Find(modelId); if (request == null) @@ -317,6 +317,7 @@ namespace Ombi.Core.Engine } request.Denied = true; + request.DeniedReason = denyReason; // We are denying a request NotificationHelper.Notify(request, NotificationType.RequestDeclined); await MovieRepository.Update(request); diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index 185f86c37..66be18cf6 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -299,7 +299,7 @@ namespace Ombi.Core.Engine return await ApproveAlbum(request); } - public async Task DenyAlbumById(int modelId) + public async Task DenyAlbumById(int modelId, string reason) { var request = await MusicRepository.Find(modelId); if (request == null) @@ -311,6 +311,7 @@ namespace Ombi.Core.Engine } request.Denied = true; + request.DeniedReason = reason; // We are denying a request NotificationHelper.Notify(request, NotificationType.RequestDeclined); await MusicRepository.Update(request); diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 290bedd6b..ddcc22d7b 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -403,7 +403,7 @@ namespace Ombi.Core.Engine }; } - public async Task DenyChildRequest(int requestId) + public async Task DenyChildRequest(int requestId, string reason) { var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId); if (request == null) @@ -414,6 +414,7 @@ namespace Ombi.Core.Engine }; } request.Denied = true; + request.DeniedReason = reason; await TvRepository.UpdateChild(request); NotificationHelper.Notify(request, NotificationType.RequestDeclined); return new RequestEngineResult diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 0d7c56372..e125d9f59 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -1,15 +1,11 @@ -using System; -using System.Linq; -using System.Linq.Expressions; +using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; -using Ombi.Store.Repository.Requests; namespace Ombi.Core.Rule.Rules.Search { diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index 575d49d62..a9458fb23 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -1,13 +1,10 @@ -using System; -using System.Linq; +using System.Linq; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; -using Ombi.Store.Repository.Requests; namespace Ombi.Core.Rule.Rules.Search { diff --git a/src/Ombi/Controllers/External/PlexController.cs b/src/Ombi/Controllers/External/PlexController.cs index f0492b580..9f7df05ad 100644 --- a/src/Ombi/Controllers/External/PlexController.cs +++ b/src/Ombi/Controllers/External/PlexController.cs @@ -185,7 +185,6 @@ namespace Ombi.Controllers.External /// /// Gets the plex servers. /// - /// The u. /// [HttpGet("servers")] [PowerUser] diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index f963db0b8..ec884ace6 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; -using System.Web; using AutoMapper; using Hangfire; using Microsoft.AspNetCore.Authorization; @@ -11,10 +10,8 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Ombi.Api.Plex; using Ombi.Attributes; -using Ombi.Config; using Ombi.Core.Authentication; using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; @@ -45,6 +42,7 @@ namespace Ombi.Controllers /// [ApiV1] [Produces("application/json")] + [ApiController] public class IdentityController : Controller { public IdentityController(OmbiUserManager user, IMapper mapper, RoleManager rm, IEmailProvider prov, @@ -935,6 +933,8 @@ namespace Ombi.Controllers } [HttpPost("NotificationPreferences")] + [ProducesResponseType(404)] + [ProducesResponseType(401)] public async Task AddUserNotificationPreference([FromBody] List preferences) { foreach (var pref in preferences) diff --git a/src/Ombi/Controllers/ImagesController.cs b/src/Ombi/Controllers/ImagesController.cs index acbdfb9bc..39de92c71 100644 --- a/src/Ombi/Controllers/ImagesController.cs +++ b/src/Ombi/Controllers/ImagesController.cs @@ -16,7 +16,8 @@ namespace Ombi.Controllers { [ApiV1] [Produces("application/json")] - public class ImagesController : Controller + [ApiController] + public class ImagesController : ControllerBase { public ImagesController(IFanartTvApi fanartTvApi, IApplicationConfigRepository config, IOptions options, ICacheService c) diff --git a/src/Ombi/Controllers/IssuesController.cs b/src/Ombi/Controllers/IssuesController.cs index a228a63ef..1a5af5446 100644 --- a/src/Ombi/Controllers/IssuesController.cs +++ b/src/Ombi/Controllers/IssuesController.cs @@ -23,7 +23,8 @@ namespace Ombi.Controllers [ApiV1] [Authorize] [Produces("application/json")] - public class IssuesController : Controller + [ApiController] + public class IssuesController : ControllerBase { public IssuesController(IRepository categories, IRepository issues, IRepository comments, UserManager userManager, INotificationService notify) diff --git a/src/Ombi/Controllers/JobController.cs b/src/Ombi/Controllers/JobController.cs index a89346250..cec8d2c45 100644 --- a/src/Ombi/Controllers/JobController.cs +++ b/src/Ombi/Controllers/JobController.cs @@ -16,7 +16,8 @@ namespace Ombi.Controllers [ApiV1] [Admin] [Produces("application/json")] - public class JobController : Controller + [ApiController] + public class JobController : ControllerBase { public JobController(IOmbiAutomaticUpdater updater, IPlexUserImporter userImporter, ICacheService mem, IEmbyUserImporter embyImporter, IPlexContentSync plexContentSync, diff --git a/src/Ombi/Controllers/LandingPageController.cs b/src/Ombi/Controllers/LandingPageController.cs index e495f2cf3..6b1c27656 100644 --- a/src/Ombi/Controllers/LandingPageController.cs +++ b/src/Ombi/Controllers/LandingPageController.cs @@ -14,7 +14,8 @@ namespace Ombi.Controllers [ApiV1] [AllowAnonymous] [Produces("application/json")] - public class LandingPageController + [ApiController] + public class LandingPageController : ControllerBase { public LandingPageController(ISettingsService plex, ISettingsService emby, IPlexApi plexApi, IEmbyApi embyApi) diff --git a/src/Ombi/Controllers/LoggingController.cs b/src/Ombi/Controllers/LoggingController.cs index c6879da39..c944825af 100644 --- a/src/Ombi/Controllers/LoggingController.cs +++ b/src/Ombi/Controllers/LoggingController.cs @@ -9,7 +9,8 @@ namespace Ombi.Controllers [Authorize] [ApiV1] [Produces("application/json")] - public class LoggingController : Controller + [ApiController] + public class LoggingController : ControllerBase { public LoggingController(ILogger logger) { diff --git a/src/Ombi/Controllers/MobileController.cs b/src/Ombi/Controllers/MobileController.cs index 70a6f1053..c3b15a910 100644 --- a/src/Ombi/Controllers/MobileController.cs +++ b/src/Ombi/Controllers/MobileController.cs @@ -17,7 +17,8 @@ namespace Ombi.Controllers [ApiV1] [Authorize] [Produces("application/json")] - public class MobileController : Controller + [ApiController] + public class MobileController : ControllerBase { public MobileController(IRepository notification, OmbiUserManager user) { @@ -30,6 +31,8 @@ namespace Ombi.Controllers [HttpPost("Notification")] [ApiExplorerSettings(IgnoreApi = true)] + [ProducesResponseType(400)] + [ProducesResponseType(200)] public async Task AddNotitficationId([FromBody] NotificationIdBody body) { if (body?.PlayerId.HasValue() ?? false) diff --git a/src/Ombi/Controllers/MusicRequestController.cs b/src/Ombi/Controllers/MusicRequestController.cs index fee0cc39d..ea3f615f0 100644 --- a/src/Ombi/Controllers/MusicRequestController.cs +++ b/src/Ombi/Controllers/MusicRequestController.cs @@ -17,7 +17,8 @@ namespace Ombi.Controllers [Authorize] [Route("api/v1/request/music")] [Produces("application/json")] - public class MusicRequestController : Controller + [ApiController] + public class MusicRequestController : ControllerBase { public MusicRequestController(IMusicRequestEngine engine, IVoteEngine voteEngine, ILogger log) { @@ -154,9 +155,9 @@ namespace Ombi.Controllers /// [HttpPut("deny")] [PowerUser] - public async Task Deny([FromBody] AlbumUpdateModel model) + public async Task Deny([FromBody] DenyAlbumModel model) { - return await _engine.DenyAlbumById(model.Id); + return await _engine.DenyAlbumById(model.Id, model.Reason); } /// diff --git a/src/Ombi/Controllers/NotificationsController.cs b/src/Ombi/Controllers/NotificationsController.cs index a881a89d3..8fe453d3d 100644 --- a/src/Ombi/Controllers/NotificationsController.cs +++ b/src/Ombi/Controllers/NotificationsController.cs @@ -36,7 +36,8 @@ namespace Ombi.Controllers [Admin] [ApiV1] [Produces("application/json")] - public class NotificationsController : Controller + [ApiController] + public class NotificationsController : ControllerBase { public NotificationsController(IMassEmailSender sender) { diff --git a/src/Ombi/Controllers/PlexOAuthController.cs b/src/Ombi/Controllers/PlexOAuthController.cs index 2aad2a2a9..fe78435c9 100644 --- a/src/Ombi/Controllers/PlexOAuthController.cs +++ b/src/Ombi/Controllers/PlexOAuthController.cs @@ -20,6 +20,7 @@ namespace Ombi.Controllers [ApiExplorerSettings(IgnoreApi = true)] [ApiV1] [AllowAnonymous] + [ApiController] public class PlexOAuthController : Controller { public PlexOAuthController(IPlexOAuthManager manager, IPlexApi plexApi, ISettingsService plexSettings, diff --git a/src/Ombi/Controllers/RecentlyAddedController.cs b/src/Ombi/Controllers/RecentlyAddedController.cs index fb4446efd..a56750449 100644 --- a/src/Ombi/Controllers/RecentlyAddedController.cs +++ b/src/Ombi/Controllers/RecentlyAddedController.cs @@ -12,7 +12,8 @@ namespace Ombi.Controllers [ApiV1] [Produces("application/json")] [Authorize] - public class RecentlyAddedController : Controller + [ApiController] + public class RecentlyAddedController : ControllerBase { public RecentlyAddedController(IRecentlyAddedEngine engine) { diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index 9e13e1c90..b3cccf9d1 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -20,7 +20,8 @@ namespace Ombi.Controllers [Authorize] [ApiV1] [Produces("application/json")] - public class RequestController : Controller + [ApiController] + public class RequestController : ControllerBase { public RequestController(IMovieRequestEngine engine, ITvRequestEngine tvRequestEngine, IVoteEngine vote, ILogger log) @@ -118,9 +119,8 @@ namespace Ombi.Controllers } /// - /// Deletes the specified movie request. + /// Deletes the all movie request. /// - /// The request identifier. /// [HttpDelete("movie/all")] [PowerUser] @@ -184,9 +184,9 @@ namespace Ombi.Controllers /// [HttpPut("movie/deny")] [PowerUser] - public async Task DenyMovie([FromBody] MovieUpdateModel model) + public async Task DenyMovie([FromBody] DenyMovieModel model) { - return await MovieRequestEngine.DenyMovieById(model.Id); + return await MovieRequestEngine.DenyMovieById(model.Id, model.Reason); } /// @@ -372,9 +372,9 @@ namespace Ombi.Controllers /// [HttpPut("tv/deny")] [PowerUser] - public async Task DenyChild([FromBody] TvUpdateModel model) + public async Task DenyChild([FromBody] DenyTvModel model) { - return await TvRequestEngine.DenyChildRequest(model.Id); + return await TvRequestEngine.DenyChildRequest(model.Id, model.Reason); } /// diff --git a/src/Ombi/Controllers/RequestRetryController.cs b/src/Ombi/Controllers/RequestRetryController.cs index b8ad2759e..12208978a 100644 --- a/src/Ombi/Controllers/RequestRetryController.cs +++ b/src/Ombi/Controllers/RequestRetryController.cs @@ -16,6 +16,7 @@ namespace Ombi.Controllers [ApiV1] [Admin] [Produces("application/json")] + [ApiController] public class RequestRetryController : Controller { public RequestRetryController(IRepository requestQueue, IMovieRequestRepository movieRepo, diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 2a7327481..0a0d08ea1 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -17,7 +17,8 @@ namespace Ombi.Controllers [Authorize] [ApiV1] [Produces("application/json")] - public class SearchController : Controller + [ApiController] + public class SearchController : ControllerBase { public SearchController(IMovieEngine movie, ITvSearchEngine tvEngine, ILogger logger, IMusicSearchEngine music) { diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 6b9476ce6..a02e966c1 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -37,7 +37,8 @@ namespace Ombi.Controllers [Admin] [ApiV1] [Produces("application/json")] - public class SettingsController : Controller + [ApiController] + public class SettingsController : ControllerBase { public SettingsController(ISettingsResolver resolver, IMapper mapper, diff --git a/src/Ombi/Controllers/StatsController.cs b/src/Ombi/Controllers/StatsController.cs index 0d871d80f..08d98b2c3 100644 --- a/src/Ombi/Controllers/StatsController.cs +++ b/src/Ombi/Controllers/StatsController.cs @@ -10,7 +10,8 @@ namespace Ombi.Controllers [Admin] [Authorize] [Produces("application/json")] - public class StatsController : Controller + [ApiController] + public class StatsController : ControllerBase { public StatsController(IUserStatsEngine eng) { diff --git a/src/Ombi/Controllers/StatusController.cs b/src/Ombi/Controllers/StatusController.cs index bc0fd3908..a3e36fb43 100644 --- a/src/Ombi/Controllers/StatusController.cs +++ b/src/Ombi/Controllers/StatusController.cs @@ -37,7 +37,8 @@ namespace Ombi.Controllers { [ApiV1] [Produces("application/json")] - public class StatusController : Controller + [ApiController] + public class StatusController : ControllerBase { public StatusController(ISettingsService ombi) { diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 75e40639f..be7ea56c6 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -22,7 +22,8 @@ namespace Ombi.Controllers { [ApiV1] [Produces("application/json")] - public class TokenController : Controller + [ApiController] + public class TokenController : ControllerBase { public TokenController(OmbiUserManager um, IOptions ta, IAuditRepository audit, ITokenRepository token, IPlexOAuthManager oAuthManager) @@ -46,6 +47,7 @@ namespace Ombi.Controllers /// The model. /// [HttpPost] + [ProducesResponseType(401)] public async Task GetToken([FromBody] UserAuthModel model) { if (!model.UsePlexOAuth) @@ -100,6 +102,8 @@ namespace Ombi.Controllers /// Returns the Token for the Ombi User if we can match the Plex user with a valid Ombi User /// [HttpPost("plextoken")] + [ProducesResponseType(401)] + [ProducesResponseType(400)] public async Task GetTokenWithPlexToken([FromBody] PlexTokenAuthentication model) { if (!model.PlexToken.HasValue()) @@ -161,6 +165,7 @@ namespace Ombi.Controllers } [HttpGet("{pinId:int}")] + [ProducesResponseType(401)] public async Task OAuth(int pinId) { var accessToken = await _plexOAuthManager.GetAccessTokenFromPin(pinId); @@ -201,6 +206,7 @@ namespace Ombi.Controllers /// /// [HttpPost("refresh")] + [ProducesResponseType(401)] public IActionResult RefreshToken([FromBody] TokenRefresh token) { diff --git a/src/Ombi/Controllers/UpdateController.cs b/src/Ombi/Controllers/UpdateController.cs index 0a6c3b80c..3fb1c7382 100644 --- a/src/Ombi/Controllers/UpdateController.cs +++ b/src/Ombi/Controllers/UpdateController.cs @@ -11,7 +11,8 @@ namespace Ombi.Controllers [ApiV1] [Produces("application/json")] [AllowAnonymous] - public class UpdateController : Controller + [ApiController] + public class UpdateController : ControllerBase { public UpdateController(ICacheService cache, IChangeLogProcessor processor) { diff --git a/src/Ombi/Controllers/VoteController.cs b/src/Ombi/Controllers/VoteController.cs index 70ea0ec8c..8c7c88396 100644 --- a/src/Ombi/Controllers/VoteController.cs +++ b/src/Ombi/Controllers/VoteController.cs @@ -13,7 +13,8 @@ namespace Ombi.Controllers [ApiV1] [Authorize] [Produces("application/json")] - public class VoteController : Controller + [ApiController] + public class VoteController : ControllerBase { public VoteController(IVoteEngine engine) { diff --git a/src/Ombi/Models/DenyAlbumMOdel.cs b/src/Ombi/Models/DenyAlbumMOdel.cs new file mode 100644 index 000000000..0b9346ead --- /dev/null +++ b/src/Ombi/Models/DenyAlbumMOdel.cs @@ -0,0 +1,33 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: MovieUpdateModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace Ombi.Core.Models.Requests +{ + public class DenyAlbumModel: AlbumUpdateModel + { + public string Reason { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/Models/DenyMovieModel.cs b/src/Ombi/Models/DenyMovieModel.cs new file mode 100644 index 000000000..88ae5c5db --- /dev/null +++ b/src/Ombi/Models/DenyMovieModel.cs @@ -0,0 +1,33 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: MovieUpdateModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace Ombi.Core.Models.Requests +{ + public class DenyMovieModel : MovieUpdateModel + { + public string Reason { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/Models/DenyTvModel.cs b/src/Ombi/Models/DenyTvModel.cs new file mode 100644 index 000000000..5bc57be0b --- /dev/null +++ b/src/Ombi/Models/DenyTvModel.cs @@ -0,0 +1,33 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: TvUpdateModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace Ombi.Models +{ + public class DenyTvModel: TvUpdateModel + { + public string Reason { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index cf3bff48f..679d8dc7e 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -72,6 +72,8 @@ + + diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 7e3f48c8f..b08f93045 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -96,6 +96,8 @@ namespace Ombi options.User.AllowedUserNameCharacters = string.Empty; }); + + services.AddHealthChecks(); services.AddMemoryCache(); services.AddJwtAuthentication(Configuration); @@ -150,6 +152,7 @@ namespace Ombi var ctx = serviceProvider.GetService(); loggerFactory.AddSerilog(); + app.UseHealthChecks("/health"); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); From 2fdfa3be97b4891e2cdde4450bf990c20aa0fe19 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:37:48 +0000 Subject: [PATCH 161/325] Fixed the NRO error !wip --- .../{AvailabilityRuleBase.cs => AvailabilityRuleHelper.cs} | 6 +++--- src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs | 6 +++--- src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) rename src/Ombi.Core/Rule/Rules/Search/{AvailabilityRuleBase.cs => AvailabilityRuleHelper.cs} (93%) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleBase.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs similarity index 93% rename from src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleBase.cs rename to src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index 25cf30492..528e8cfa3 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleBase.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -9,9 +9,9 @@ using Ombi.Store.Repository.Requests; namespace Ombi.Core.Rule.Rules.Search { - public abstract class AvailabilityRuleBase : BaseSearchRule + public static class AvailabilityRuleHelper { - public void CheckForUnairedEpisodes(SearchTvShowViewModel search) + public static void CheckForUnairedEpisodes(SearchTvShowViewModel search) { if (search.SeasonRequests.All(x => x.Episodes.All(e => e.Available))) { @@ -33,7 +33,7 @@ namespace Ombi.Core.Rule.Rules.Search } } - public async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, + public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb) { PlexEpisode epExists = null; diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index e125d9f59..3171c6ada 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -9,7 +9,7 @@ using Ombi.Store.Repository; namespace Ombi.Core.Rule.Rules.Search { - public class EmbyAvailabilityRule : AvailabilityRuleBase, IRules + public class EmbyAvailabilityRule : BaseSearchRule, IRules { public EmbyAvailabilityRule(IEmbyContentRepository repo) { @@ -73,12 +73,12 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - await SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); + await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); } } } - CheckForUnairedEpisodes(search); + AvailabilityRuleHelper.CheckForUnairedEpisodes(search); } } return Success(); diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index a9458fb23..7f79e4165 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -8,7 +8,7 @@ using Ombi.Store.Repository; namespace Ombi.Core.Rule.Rules.Search { - public class PlexAvailabilityRule : AvailabilityRuleBase, IRules + public class PlexAvailabilityRule : BaseSearchRule, IRules { public PlexAvailabilityRule(IPlexContentRepository repo) { @@ -72,11 +72,11 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - await SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); + await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); } } - CheckForUnairedEpisodes(search); + AvailabilityRuleHelper.CheckForUnairedEpisodes(search); } } } From 18d2488abd440f570dbcc7a50e36b783d75a2c90 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:38:58 +0000 Subject: [PATCH 162/325] removed unused reference !wip --- src/Ombi/ClientApp/app/requests/movierequests.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 19fc989f2..e002b087e 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -4,6 +4,7 @@ import { DomSanitizer } from "@angular/platform-browser"; import { Subject } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; +import { ConfirmationService } from "primeng/primeng"; import { AuthService } from "../auth/auth.service"; import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; import { NotificationService, RadarrService, RequestService } from "../services"; From 870eec17c5b3b4a143f662a358838f2718a4fb66 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:41:58 +0000 Subject: [PATCH 163/325] Another unused reference !wip --- .../ClientApp/app/requests/movierequests.component.html | 7 +++++++ src/Ombi/ClientApp/app/requests/movierequests.component.ts | 1 - src/Ombi/ClientApp/app/requests/requests.module.ts | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index a1dd5cadc..bbe3e9d2f 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -215,6 +215,13 @@ + + + + + + + diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index e002b087e..19fc989f2 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -4,7 +4,6 @@ import { DomSanitizer } from "@angular/platform-browser"; import { Subject } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; -import { ConfirmationService } from "primeng/primeng"; import { AuthService } from "../auth/auth.service"; import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; import { NotificationService, RadarrService, RequestService } from "../services"; diff --git a/src/Ombi/ClientApp/app/requests/requests.module.ts b/src/Ombi/ClientApp/app/requests/requests.module.ts index 63d7117f5..ca77c8f8c 100644 --- a/src/Ombi/ClientApp/app/requests/requests.module.ts +++ b/src/Ombi/ClientApp/app/requests/requests.module.ts @@ -6,7 +6,7 @@ import { OrderModule } from "ngx-order-pipe"; import { InfiniteScrollModule } from "ngx-infinite-scroll"; -import { ButtonModule, DialogModule, PaginatorModule } from "primeng/primeng"; +import { ButtonModule, ConfirmDialogModule, DialogModule, PaginatorModule } from "primeng/primeng"; import { MovieRequestsComponent } from "./movierequests.component"; import { MusicRequestsComponent } from "./music/musicrequests.component"; // Request @@ -38,6 +38,7 @@ const routes: Routes = [ OrderModule, PaginatorModule, TooltipModule, + ConfirmDialogModule, ], declarations: [ RequestComponent, From 72e0ebc8876d9119ee90aba68ed50fb2adab657e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:49:06 +0000 Subject: [PATCH 164/325] !wip fixed builds --- .../Rules/Search/AvailabilityRuleHelper.cs | 2 +- .../app/requests/movierequests.component.ts | 21 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index 528e8cfa3..428de9ce5 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -63,7 +63,7 @@ namespace Ombi.Core.Rule.Rules.Search episode.Available = true; } } - public async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, + public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, SeasonRequests season, EmbyContent item, bool useTheMovieDb, bool useTvDb) { EmbyEpisode epExists = null; diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 19fc989f2..c0c51d30a 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -1,9 +1,10 @@ import { PlatformLocation } from "@angular/common"; -import { Component, Input, OnInit } from "@angular/core"; +import { Component, Input, OnInit, ViewChild } from "@angular/core"; import { DomSanitizer } from "@angular/platform-browser"; import { Subject } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; +import { ConfirmationService, ConfirmDialog } from "primeng/primeng"; import { AuthService } from "../auth/auth.service"; import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; import { NotificationService, RadarrService, RequestService } from "../services"; @@ -37,9 +38,10 @@ export class MovieRequestsComponent implements OnInit { public orderType: OrderType = OrderType.RequestedDateDesc; public OrderType = OrderType; + @ViewChild("") public confirmDialogComponent: ConfirmDialog; public totalMovies: number = 100; - private currentlyLoaded: number; + public currentlyLoaded: number; private amountToLoad: number; constructor( @@ -48,7 +50,8 @@ export class MovieRequestsComponent implements OnInit { private notificationService: NotificationService, private radarrService: RadarrService, private sanitizer: DomSanitizer, - private readonly platformLocation: PlatformLocation) { + private readonly platformLocation: PlatformLocation, + private confirmationService: ConfirmationService) { this.searchChanged.pipe( debounceTime(600), // Wait Xms after the last event before emitting last event distinctUntilChanged(), // only emit if value is different from previous value @@ -130,9 +133,15 @@ export class MovieRequestsComponent implements OnInit { } public deny(request: IMovieRequests) { - request.denied = true; - this.denyRequest(request); - } + + this.confirmationService.confirm({ + message: "Are you sure", + accept: () => { + request.denied = true; + this.denyRequest(request); + }, + }); + } public selectRootFolder(searchResult: IMovieRequests, rootFolderSelected: IRadarrRootFolder, event: any) { event.preventDefault(); From ffc1641d7740cb8d71f10ed43ef1c986e939e6ab Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:49:58 +0000 Subject: [PATCH 165/325] !wip fixed ui error --- .../ClientApp/app/requests/movierequests.component.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index bbe3e9d2f..af9f3a22e 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -216,7 +216,11 @@ - + +
    +
  • test
  • +
+
From 3377eb98389a9b0b2d42306f15f8a274e509ae67 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 13:52:52 +0000 Subject: [PATCH 166/325] Set the landing and login pages background refresh to 15 seconds rather than 10 and 7 --- src/Ombi/ClientApp/app/landingpage/landingpage.component.ts | 2 +- src/Ombi/ClientApp/app/login/login.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/landingpage/landingpage.component.ts b/src/Ombi/ClientApp/app/landingpage/landingpage.component.ts index 514b1754e..dc329baf3 100644 --- a/src/Ombi/ClientApp/app/landingpage/landingpage.component.ts +++ b/src/Ombi/ClientApp/app/landingpage/landingpage.component.ts @@ -37,7 +37,7 @@ export class LandingPageComponent implements OnDestroy, OnInit { }); this.timer = setInterval(() => { this.cycleBackground(); - }, 10000); + }, 15000); const base = this.location.getBaseHrefFromDOM(); if (base.length > 1) { diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 0c04edbad..4a9ad4aaf 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -87,7 +87,7 @@ export class LoginComponent implements OnDestroy, OnInit { }); this.timer = setInterval(() => { this.cycleBackground(); - }, 7000); + }, 15000); const base = this.location.getBaseHrefFromDOM(); if (base.length > 1) { From bd3a243af96dfa9b1e7dd4d0f404d349cdcde52e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 14:47:35 +0000 Subject: [PATCH 167/325] Deny reason for movie requests --- .../ClientApp/app/interfaces/IRequestModel.ts | 4 ++ .../app/requests/movierequests.component.html | 17 +++---- .../app/requests/movierequests.component.ts | 49 +++++++++---------- .../ClientApp/app/requests/requests.module.ts | 3 +- .../ClientApp/app/services/request.service.ts | 6 +-- .../usermanagement-user.component.ts | 10 ++++ src/Ombi/ClientApp/styles/base.scss | 11 ++++- 7 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index b083ca088..16a1511e9 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -47,6 +47,10 @@ export interface IMovieUpdateModel { id: number; } +export interface IDenyMovieModel extends IMovieUpdateModel { + reason: string; +} + export interface IAlbumUpdateModel { id: number; } diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index af9f3a22e..f8ea31950 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -88,7 +88,7 @@
{{ 'Requests.Denied' | translate }} - +
@@ -215,17 +215,14 @@ - - -
    -
  • test
  • -
-
+ +Please enter a rejection reason, the user will be notified of this: + - - + + -
+ diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index c0c51d30a..3c7a4f993 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -1,10 +1,9 @@ import { PlatformLocation } from "@angular/common"; -import { Component, Input, OnInit, ViewChild } from "@angular/core"; +import { Component, Input, OnInit } from "@angular/core"; import { DomSanitizer } from "@angular/platform-browser"; import { Subject } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; -import { ConfirmationService, ConfirmDialog } from "primeng/primeng"; import { AuthService } from "../auth/auth.service"; import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; import { NotificationService, RadarrService, RequestService } from "../services"; @@ -38,7 +37,9 @@ export class MovieRequestsComponent implements OnInit { public orderType: OrderType = OrderType.RequestedDateDesc; public OrderType = OrderType; - @ViewChild("") public confirmDialogComponent: ConfirmDialog; + public denyDisplay: boolean; + public requestToDeny: IMovieRequests; + public rejectionReason: string; public totalMovies: number = 100; public currentlyLoaded: number; @@ -50,8 +51,7 @@ export class MovieRequestsComponent implements OnInit { private notificationService: NotificationService, private radarrService: RadarrService, private sanitizer: DomSanitizer, - private readonly platformLocation: PlatformLocation, - private confirmationService: ConfirmationService) { + private readonly platformLocation: PlatformLocation) { this.searchChanged.pipe( debounceTime(600), // Wait Xms after the last event before emitting last event distinctUntilChanged(), // only emit if value is different from previous value @@ -133,15 +133,23 @@ export class MovieRequestsComponent implements OnInit { } public deny(request: IMovieRequests) { - - this.confirmationService.confirm({ - message: "Are you sure", - accept: () => { - request.denied = true; - this.denyRequest(request); - }, - }); - } + this.requestToDeny = request; + this.denyDisplay = true; + } + + public denyRequest() { + this.requestService.denyMovie({ id: this.requestToDeny.id, reason: this.rejectionReason }) + .subscribe(x => { + this.denyDisplay = false; + if (x.result) { + this.notificationService.success( + `Request for ${this.requestToDeny.title} has been denied successfully`); + } else { + this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); + this.requestToDeny.denied = false; + } + }); + } public selectRootFolder(searchResult: IMovieRequests, rootFolderSelected: IRadarrRootFolder, event: any) { event.preventDefault(); @@ -287,19 +295,6 @@ export class MovieRequestsComponent implements OnInit { }); } - private denyRequest(request: IMovieRequests) { - this.requestService.denyMovie({ id: request.id }) - .subscribe(x => { - if (x.result) { - this.notificationService.success( - `Request for ${request.title} has been denied successfully`); - } else { - this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); - request.denied = false; - } - }); - } - private loadInit() { this.requestService.getMovieRequests(this.amountToLoad, 0, this.orderType, this.filter) .subscribe(x => { diff --git a/src/Ombi/ClientApp/app/requests/requests.module.ts b/src/Ombi/ClientApp/app/requests/requests.module.ts index ca77c8f8c..63d7117f5 100644 --- a/src/Ombi/ClientApp/app/requests/requests.module.ts +++ b/src/Ombi/ClientApp/app/requests/requests.module.ts @@ -6,7 +6,7 @@ import { OrderModule } from "ngx-order-pipe"; import { InfiniteScrollModule } from "ngx-infinite-scroll"; -import { ButtonModule, ConfirmDialogModule, DialogModule, PaginatorModule } from "primeng/primeng"; +import { ButtonModule, DialogModule, PaginatorModule } from "primeng/primeng"; import { MovieRequestsComponent } from "./movierequests.component"; import { MusicRequestsComponent } from "./music/musicrequests.component"; // Request @@ -38,7 +38,6 @@ const routes: Routes = [ OrderModule, PaginatorModule, TooltipModule, - ConfirmDialogModule, ], declarations: [ RequestComponent, diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 0021dc208..c157cb72f 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -5,8 +5,8 @@ import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; import { TreeNode } from "primeng/primeng"; -import { FilterType, IAlbumRequest, IAlbumRequestModel, IAlbumUpdateModel, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, - IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces"; +import { FilterType, IAlbumRequest, IAlbumRequestModel, IAlbumUpdateModel, IChildRequests, IDenyMovieModel, IFilter, IMovieRequestModel, + IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces"; import { ITvRequestViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @@ -50,7 +50,7 @@ export class RequestService extends ServiceHelpers { return this.http.post(`${this.url}Movie/Approve`, JSON.stringify(movie), {headers: this.headers}); } - public denyMovie(movie: IMovieUpdateModel): Observable { + public denyMovie(movie: IDenyMovieModel): Observable { return this.http.put(`${this.url}Movie/Deny`, JSON.stringify(movie), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index 5be0a4509..59f3ea5d8 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -8,6 +8,16 @@ import { ConfirmationService } from "primeng/primeng"; @Component({ templateUrl: "./usermanagement-user.component.html", + styles: [` + + ::ng-deep ngb-accordion > div.card > div.card-header { + padding:0px; + } + ::ng-deep ngb-accordion > div.card { + color:white; + padding-top: 0px; + } + `], }) export class UserManagementUserComponent implements OnInit { diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 1245f63ab..9c7756d8f 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -1008,4 +1008,13 @@ a > h4:hover { .album-cover { width:300px; -} \ No newline at end of file +} + + +::ng-deep ngb-accordion > div.card > div.card-header { + padding:0px; +} +::ng-deep ngb-accordion > div.card { + color:white; + padding-top: 0px; +} From e6d48e5364e7125f68f13ea71182aaa31e67bd3e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 17 Dec 2018 15:56:24 +0000 Subject: [PATCH 168/325] Added the ability to deny a request with a reason --- .../NotificationMessageCurlys.cs | 7 ++- .../ClientApp/app/interfaces/IRequestModel.ts | 8 ++++ .../music/musicrequests.component.html | 15 ++++++- .../requests/music/musicrequests.component.ts | 45 +++++++------------ .../tvrequest-children.component.html | 16 ++++++- .../requests/tvrequest-children.component.ts | 14 +++++- .../ClientApp/app/services/request.service.ts | 8 ++-- 7 files changed, 73 insertions(+), 40 deletions(-) diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index b178f0545..1e1224342 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -49,7 +49,7 @@ namespace Ombi.Notifications } Overview = req?.Overview; Year = req?.ReleaseDate.Year.ToString(); - + DenyReason = req?.DeniedReason; if (req?.RequestType == RequestType.Movie) { PosterImage = string.Format((req?.PosterPath ?? string.Empty).StartsWith("/", StringComparison.InvariantCultureIgnoreCase) @@ -88,6 +88,7 @@ namespace Ombi.Notifications UserName = req?.RequestedUser?.UserName; } + DenyReason = req?.DeniedReason; Alias = (req?.RequestedUser?.Alias.HasValue() ?? false) ? req?.RequestedUser?.Alias : req?.RequestedUser?.UserName; Title = title; RequestedDate = req?.RequestedDate.ToString("D"); @@ -126,6 +127,7 @@ namespace Ombi.Notifications { title = req?.ParentRequest.Title; } + DenyReason = req?.DeniedReason; ApplicationUrl = (s?.ApplicationUrl.HasValue() ?? false) ? s.ApplicationUrl : string.Empty; ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName; RequestedUser = req?.RequestedUser?.UserName; @@ -217,7 +219,6 @@ namespace Ombi.Notifications public string UserName { get; set; } public string IssueUser => UserName; public string Alias { get; set; } - public string Title { get; set; } public string RequestedDate { get; set; } public string Type { get; set; } @@ -235,6 +236,7 @@ namespace Ombi.Notifications public string IssueSubject { get; set; } public string NewIssueComment { get; set; } public string UserPreference { get; set; } + public string DenyReason { get; set; } // System Defined private string LongDate => DateTime.Now.ToString("D"); @@ -269,6 +271,7 @@ namespace Ombi.Notifications {nameof(UserName),UserName}, {nameof(Alias),Alias}, {nameof(UserPreference),UserPreference}, + {nameof(DenyReason),DenyReason}, }; } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index 16a1511e9..4bb43f3fe 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -55,6 +55,10 @@ export interface IAlbumUpdateModel { id: number; } +export interface IDenyAlbumModel extends IAlbumUpdateModel { + reason: string; +} + export interface IFullBaseRequest extends IBaseRequest { imdbId: string; overview: string; @@ -117,6 +121,10 @@ export interface ITvUpdateModel { id: number; } +export interface ITvDenyModel extends ITvUpdateModel { + reason: string; +} + export enum OrderType { RequestedDateAsc = 1, RequestedDateDesc = 2, diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index c4c903da2..5b274589b 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -92,7 +92,7 @@
{{ 'Requests.Denied' | translate }} - +
@@ -265,4 +265,15 @@ - \ No newline at end of file + + + + + + Please enter a rejection reason, the user will be notified of this: + + + + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts index e70d44a38..7cda9ab29 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts @@ -34,6 +34,9 @@ export class MusicRequestsComponent implements OnInit { public orderType: OrderType = OrderType.RequestedDateDesc; public OrderType = OrderType; + public denyDisplay: boolean; + public requestToDeny: IAlbumRequest; + public rejectionReason: string; public totalAlbums: number = 100; private currentlyLoaded: number; @@ -126,23 +129,22 @@ export class MusicRequestsComponent implements OnInit { } public deny(request: IAlbumRequest) { - request.denied = true; - this.denyRequest(request); + this.requestToDeny = request; + this.denyDisplay = true; } - // public selectRootFolder(searchResult: IAlbumRequest, rootFolderSelected: IRadarrRootFolder, event: any) { - // event.preventDefault(); - // // searchResult.rootPathOverride = rootFolderSelected.id; - // this.setOverride(searchResult); - // this.updateRequest(searchResult); - // } - - // public selectQualityProfile(searchResult: IMovieRequests, profileSelected: IRadarrProfile, event: any) { - // event.preventDefault(); - // searchResult.qualityOverride = profileSelected.id; - // this.setOverride(searchResult); - // this.updateRequest(searchResult); - // } + public denyRequest() { + this.requestService.denyAlbum({ id: this.requestToDeny.id, reason: this.rejectionReason }) + .subscribe(x => { + if (x.result) { + this.notificationService.success( + `Request for ${this.requestToDeny.title} has been denied successfully`); + } else { + this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); + this.requestToDeny.denied = false; + } + }); + } public reportIssue(catId: IIssueCategory, req: IAlbumRequest) { this.issueRequest = req; @@ -266,19 +268,6 @@ export class MusicRequestsComponent implements OnInit { }); } - private denyRequest(request: IAlbumRequest) { - this.requestService.denyAlbum({ id: request.id }) - .subscribe(x => { - if (x.result) { - this.notificationService.success( - `Request for ${request.title} has been denied successfully`); - } else { - this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); - request.denied = false; - } - }); - } - private loadInit() { this.requestService.getAlbumRequests(this.amountToLoad, 0, this.orderType, this.filter) .subscribe(x => { diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html index 1492a00f9..003ceea6a 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html @@ -21,7 +21,8 @@ - +
@@ -76,7 +77,9 @@ {{ep.airDate | amLocal | amDateFormat: 'L' }}
"); @@ -392,7 +397,7 @@ namespace Ombi.Schedule.Jobs.Ombi return sb.ToString(); } - private async Task ProcessPlexMovies(IQueryable plexContentToSend, StringBuilder sb) + private async Task ProcessPlexMovies(IQueryable plexContentToSend, StringBuilder sb, string defaultLanguageCode) { int count = 0; var ordered = plexContentToSend.OrderByDescending(x => x.AddedAt); @@ -403,7 +408,7 @@ namespace Ombi.Schedule.Jobs.Ombi { continue; } - var info = await _movieApi.GetMovieInformationWithExtraInfo(movieDbId); + var info = await _movieApi.GetMovieInformationWithExtraInfo(movieDbId, defaultLanguageCode); var mediaurl = content.Url; if (info == null) { @@ -466,7 +471,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb) + private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb, string defaultLangaugeCode) { int count = 0; var ordered = embyContent.OrderByDescending(x => x.AddedAt); @@ -487,7 +492,7 @@ namespace Ombi.Schedule.Jobs.Ombi } var mediaurl = content.Url; - var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId)); + var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode); if (info == null) { continue; From cdab76da40b1f1f0c34849cd34081b6397923e7e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 7 Jan 2019 14:46:40 +0000 Subject: [PATCH 206/325] !wip changelog --- CHANGELOG.md | 138 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7da4cd6d8..52e9d19c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,144 @@ # Changelog -## v3.0.3988 (2018-11-23) - - +## (unreleased) ### **New Features** +- Added a global language flag that now applies to the search by default. [tidusjar] + +- Updated the frontend packages (Using Angular 7 now) [TidusJar] + +- Added capture of anonymous analytical data. [tidusjar] + +- Added {AvailableDate} as a Notification Variable, this is the date the request was marked as available. See here: https://github.com/tidusjar/Ombi/wiki/Notification-Template-Variables. [tidusjar] + +- Added the ability to search movies via the movie db with a different language! [tidusjar] + +- Added the ability to specify a year when searching for movies. [tidusjar] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update HtmlTemplateGenerator.cs. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update HtmlTemplateGenerator.cs. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update HtmlTemplateGenerator.cs. [d1slact0r] + +- Updated boostrap #2694. [Jamie] + +- Added the ability to deny a request with a reason. [TidusJar] + +- Update EmbyEpisodeSync.cs. [Jamie] + +- Updated to .net core 2.2 and included a linux-arm64 build. [TidusJar] + +### **Fixes** + +- Made the newsletter use the default lanuage code set in the Ombi settings for movie information. [TidusJar] + +- Save the language code against the request so we can use it later e.g. Sending to the DVR apps. [tidusjar] + +- Fixed #2716. [tidusjar] + +- Make the newsletter BCC the users rather than creating a million newsletters (Hopefully will stop SMTP providers from marking as spam). This does mean that the custom user customization in the newsletter will no longer work. [TidusJar] + +- If we don't know the Plex agent, then see if it's a ImdbId, if it's not check the string for any episode and season hints #2695. [tidusjar] + +- 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] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- Made the search results the language specified in the search refinement. [tidusjar] + +- Fixed #2704. [tidusjar] + +- Now it is fixed :) [d1slact0r] + +- Android please be nice now. [d1slact0r] + +- Fixed title bit better. [d1slact0r] + +- Fixed titles. [d1slact0r] + +- This should fix the build for sure (stupid quotes) [d1slact0r] + +- Fixes build. [d1slact0r] + +- Rewritten the whole newsletter template. [d1slact0r] + +- Fixed #2697. [tidusjar] + +- Add linux-arm runtime identifier. [aptalca] + +- Add back arm packages. [aptalca] + +- Add arm32 package. [aptalca] + +- Fixed #2691. [tidusjar] + +- Fixed linting. [TidusJar] + +- Fixed the Plex OAuth when going through the wizard. [TidusJar] + +- Fixed #2678. [TidusJar] + +- Deny reason for movie requests. [TidusJar] + +- Set the landing and login pages background refresh to 15 seconds rather than 10 and 7. [TidusJar] + +- Fixed a bug with us thinking future dated emby episodes are not available, Consoldated the emby and plex search rules (since they have the same logic) [TidusJar] + +- Fixed build. [TidusJar] + + +## v3.0.4036 (2018-12-11) + +### **New Features** + +- Changelog. [Jamie] + - Added Sonarr v3 #2359. [TidusJar] ### **Fixes** +- !changelog. [Jamie] + +- Fixed a missing translation. [Jamie] + - Fixed a potential security vulnerability. [Jamie] - Sorted out some of the settings pages, trying to make it consistent. [Jamie] @@ -37,8 +166,7 @@ ### **Fixes** - -- Fixed #2601 [TidusJar] +- !changelog. [Jamie] - Made the subscribe/unsubscribe button more obvious on the UI #2309. [Jamie] From b30541335175f36c4892ebe6938b26d20b9c0d50 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 8 Jan 2019 12:56:32 +0000 Subject: [PATCH 207/325] Fixed #2725 and #2721 --- src/Ombi.Notifications/NotificationMessageCurlys.cs | 6 +++--- src/Ombi/Controllers/IdentityController.cs | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 407490240..cedda3735 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -39,7 +39,7 @@ namespace Ombi.Notifications Alias = (req?.RequestedUser?.Alias.HasValue() ?? false) ? req?.RequestedUser?.Alias : req?.RequestedUser?.UserName; if (pref != null) { - UserPreference = pref.Enabled ? pref.Value : Alias; + UserPreference = pref.Value.HasValue() ? pref.Value : Alias; } Title = title; RequestedDate = req?.RequestedDate.ToString("D"); @@ -91,7 +91,7 @@ namespace Ombi.Notifications Alias = (req?.RequestedUser?.Alias.HasValue() ?? false) ? req?.RequestedUser?.Alias : req?.RequestedUser?.UserName; if (pref != null) { - UserPreference = pref.Enabled ? pref.Value : Alias; + UserPreference = pref.Value.HasValue() ? pref.Value : Alias; } Title = title; RequestedDate = req?.RequestedDate.ToString("D"); @@ -136,7 +136,7 @@ namespace Ombi.Notifications Alias = (req?.RequestedUser?.Alias.HasValue() ?? false) ? req?.RequestedUser?.Alias : req?.RequestedUser?.UserName; if (pref != null) { - UserPreference = pref.Enabled ? pref.Value : Alias; + UserPreference = pref.Value.HasValue() ? pref.Value : Alias; } Title = title; RequestedDate = req?.RequestedDate.ToString("D"); diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index ec884ace6..2976069ed 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -965,7 +965,6 @@ namespace Ombi.Controllers { // Update it existingPreference.Value = pref.Value; - existingPreference.Enabled = pref.Enabled; await _userNotificationPreferences.SaveChangesAsync(); } else @@ -973,7 +972,6 @@ namespace Ombi.Controllers await _userNotificationPreferences.Add(new UserNotificationPreferences { Agent = pref.Agent, - Enabled = pref.Enabled, UserId = pref.UserId, Value = pref.Value }); From edf87bf296171ce0b3244b451dc20a9e0f6a743b Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 8 Jan 2019 15:04:08 +0000 Subject: [PATCH 208/325] !wip on the new custom page --- .../Settings/Models/CustomPageSettings.cs | 9 ++++ src/Ombi/ClientApp/app/app.module.ts | 8 +++- .../app/custompage/custompage.component.html | 7 +++ .../app/custompage/custompage.component.scss | 44 +++++++++++++++++++ .../app/custompage/custompage.component.ts | 19 ++++++++ src/Ombi/Controllers/SettingsController.cs | 21 +++++++++ src/Ombi/package.json | 16 ++++--- src/Ombi/webpack.config.vendor.ts | 2 + src/Ombi/yarn.lock | 10 +++++ 9 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 src/Ombi.Settings/Settings/Models/CustomPageSettings.cs create mode 100644 src/Ombi/ClientApp/app/custompage/custompage.component.html create mode 100644 src/Ombi/ClientApp/app/custompage/custompage.component.scss create mode 100644 src/Ombi/ClientApp/app/custompage/custompage.component.ts diff --git a/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs b/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs new file mode 100644 index 000000000..9a33b799c --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs @@ -0,0 +1,9 @@ +namespace Ombi.Settings.Settings.Models +{ + public class CustomPageSettings : Settings + { + public bool Enabled { get; set; } + public string Title { get; set; } + public string Html { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/app.module.ts b/src/Ombi/ClientApp/app/app.module.ts index 0f268e4d2..6917cc85b 100644 --- a/src/Ombi/ClientApp/app/app.module.ts +++ b/src/Ombi/ClientApp/app/app.module.ts @@ -14,13 +14,16 @@ import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { TranslateLoader, TranslateModule } from "@ngx-translate/core"; import { TranslateHttpLoader } from "@ngx-translate/http-loader"; import { CookieService } from "ng2-cookies"; +import { NgxEditorModule } from "ngx-editor"; import { GrowlModule } from "primeng/components/growl/growl"; -import { ButtonModule, CaptchaModule, ConfirmationService, ConfirmDialogModule, DataTableModule, DialogModule, OverlayPanelModule, SharedModule, SidebarModule, TooltipModule } from "primeng/primeng"; +import { ButtonModule, CaptchaModule, ConfirmationService, ConfirmDialogModule, DataTableModule, DialogModule, OverlayPanelModule, SharedModule, SidebarModule, + TooltipModule } from "primeng/primeng"; // Components import { AppComponent } from "./app.component"; import { CookieComponent } from "./auth/cookie.component"; +import { CustomPageComponent } from "./custompage/custompage.component"; import { PageNotFoundComponent } from "./errors/not-found.component"; import { LandingPageComponent } from "./landingpage/landingpage.component"; import { LoginComponent } from "./login/login.component"; @@ -43,6 +46,7 @@ const routes: Routes = [ { path: "", redirectTo: "/search", pathMatch: "full" }, { path: "login", component: LoginComponent }, { path: "Login/OAuth/:pin", component: LoginOAuthComponent }, + { path: "Custom", component: CustomPageComponent }, { path: "login/:landing", component: LoginComponent }, { path: "reset", component: ResetPasswordComponent }, { path: "token", component: TokenResetPasswordComponent }, @@ -88,6 +92,7 @@ export function JwtTokenGetter() { FormsModule, DataTableModule, SharedModule, + NgxEditorModule, DialogModule, MatButtonModule, NgbModule.forRoot(), @@ -121,6 +126,7 @@ export function JwtTokenGetter() { LandingPageComponent, ResetPasswordComponent, TokenResetPasswordComponent, + CustomPageComponent, CookieComponent, LoginOAuthComponent, ], diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.html b/src/Ombi/ClientApp/app/custompage/custompage.component.html new file mode 100644 index 000000000..545f56cb5 --- /dev/null +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.html @@ -0,0 +1,7 @@ + +
+ + +
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.scss b/src/Ombi/ClientApp/app/custompage/custompage.component.scss new file mode 100644 index 000000000..127ee8b74 --- /dev/null +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.scss @@ -0,0 +1,44 @@ +$primary-colour: #df691a; +$primary-colour-outline: #ff761b; +$bg-colour: #333333; +$bg-colour-disabled: #252424; + +:host app-ngx-editor /deep/ .ngx-toolbar { + background-color: $bg-colour; + border: 1px solid $primary-colour-outline; +} + +:host app-ngx-editor /deep/ .ngx-toolbar-set { + background-color: transparent !important; + border: 1px solid $primary-colour-outline !important; +} + +:host app-ngx-editor /deep/ .ngx-editor-button { + -o-transition: all 0.218s; + -moz-transition: all 0.218s; + -webkit-transition: all 0.218s; + transition: all 0.218s; + color: $primary-colour-outline; + background-color: transparent; + background-image: none; + border-color: $primary-colour-outline !important; +} + +:host app-ngx-editor /deep/ .ngx-editor-button:hover { + color: black; + background-color: $primary-colour !important; + border-color: $primary-colour-outline !important; +} + +:host app-ngx-editor /deep/ .ngx-editor-grippie { + background-color: $bg-colour; + border: 1px solid $primary-colour-outline; +} + +:host app-ngx-editor /deep/ .ngx-editor-textarea { + border: 1px solid $primary-colour-outline !important; +} + +:host app-ngx-editor /deep/ .ngx-editor-message { + display:none !important; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.ts b/src/Ombi/ClientApp/app/custompage/custompage.component.ts new file mode 100644 index 000000000..dd9259dae --- /dev/null +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.ts @@ -0,0 +1,19 @@ +import { Component, OnInit } from "@angular/core"; + +@Component({ + templateUrl: "./custompage.component.html", + styleUrls: ["./custompage.component.scss"], +}) +export class CustomPageComponent implements OnInit { + + public html: string; + public isEditing: boolean; + + constructor() { +// + } + + public ngOnInit() { + // + } +} diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 45efc8067..770745786 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -706,6 +706,27 @@ namespace Ombi.Controllers return emailSettings.Enabled; } + /// + /// Gets the Custom Page Settings. + /// + /// + [HttpGet("CustomPage")] + [AllowAnonymous] + public async Task CustomPageSettings() + { + return await Get(); + } + + /// + /// Saves the Custom Page Settings. + /// + /// + [HttpGet("CustomPage")] + public async Task CustomPageSettings([FromBody] CustomPageSettings page) + { + return await Save(page); + } + /// /// Saves the discord notification settings. /// diff --git a/src/Ombi/package.json b/src/Ombi/package.json index 0d4c31f21..5713b1061 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -15,20 +15,20 @@ "@angular/animations": "^7.1.4", "@angular/cdk": "^7.2.0", "@angular/common": "^7.1.4", - "@angular/compiler":"^7.1.4", + "@angular/compiler": "^7.1.4", "@angular/compiler-cli": "^7.1.4", "@angular/core": "^7.1.4", - "@angular/forms":"^7.1.4", + "@angular/forms": "^7.1.4", "@angular/http": "^7.1.4", - "@angular/material":"^7.2.0", + "@angular/material": "^7.2.0", "@angular/platform-browser": "^7.1.4", "@angular/platform-browser-dynamic": "^7.1.4", - "@angular/platform-server":"^7.1.4", - "@angular/router":"^7.1.4", + "@angular/platform-server": "^7.1.4", + "@angular/router": "^7.1.4", "@auth0/angular-jwt": "^2.0.0", "@ng-bootstrap/ng-bootstrap": "^3.3.1", - "@ngtools/webpack":"^7.1.4", - "@ngu/carousel": "^1.4.9-beta-2", + "@ngtools/webpack": "^7.1.4", + "@ngu/carousel": "^1.4.9-beta-2", "@ngx-translate/core": "^11.0.1", "@ngx-translate/http-loader": "^4.0.0", "@types/core-js": "^2.5.0", @@ -62,7 +62,9 @@ "moment": "^2.22.2", "natives": "1.1.6", "ng2-cookies": "^1.0.12", + "ngx-bootstrap": "^3.1.4", "ngx-clipboard": "^11.1.1", + "ngx-editor": "^4.1.0", "ngx-infinite-scroll": "^6.0.1", "ngx-moment": "^3.0.1", "ngx-order-pipe": "^2.0.1", diff --git a/src/Ombi/webpack.config.vendor.ts b/src/Ombi/webpack.config.vendor.ts index dc7c282bd..3f360af10 100644 --- a/src/Ombi/webpack.config.vendor.ts +++ b/src/Ombi/webpack.config.vendor.ts @@ -53,6 +53,8 @@ module.exports = (env: any) => { "@ngx-translate/http-loader", "ngx-order-pipe", "@yellowspot/ng-truncate", + "ngx-editor", + "ngx-bootstrap", ]), }, plugins: prod ? [] : [ diff --git a/src/Ombi/yarn.lock b/src/Ombi/yarn.lock index ae028221a..95d3e136b 100644 --- a/src/Ombi/yarn.lock +++ b/src/Ombi/yarn.lock @@ -4182,6 +4182,10 @@ ng2-cookies@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/ng2-cookies/-/ng2-cookies-1.0.12.tgz#3f3e613e0137b0649b705c678074b4bd08149ccc" +ngx-bootstrap@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.1.4.tgz#5105c0227da3b51a1972d04efa1504a79474fd57" + ngx-clipboard@^11.1.1: version "11.1.9" resolved "https://registry.yarnpkg.com/ngx-clipboard/-/ngx-clipboard-11.1.9.tgz#a391853dc49e436de407260863a2c814d73a9332" @@ -4189,6 +4193,12 @@ ngx-clipboard@^11.1.1: ngx-window-token "^1.0.2" tslib "^1.9.0" +ngx-editor@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ngx-editor/-/ngx-editor-4.1.0.tgz#3ec5820627f25a2239094747cccf88a7ca02f79f" + dependencies: + tslib "^1.9.0" + ngx-infinite-scroll@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-6.0.1.tgz#571e54860ce32839451569bcf6e7a63cfae327bd" From 656f8511b4a128861d1705c84dd69606302cf4d7 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 8 Jan 2019 20:06:45 +0000 Subject: [PATCH 209/325] !wip added the custom page into the settings --- .../Settings/Models/CustomPageSettings.cs | 1 - .../Settings/Models/CustomizationSettings.cs | 1 + .../Entities/Requests/MovieRequests.cs | 2 ++ .../app/custompage/custompage.component.html | 29 ++++++++++++---- .../app/custompage/custompage.component.ts | 34 ++++++++++++++++--- .../ClientApp/app/interfaces/ISettings.ts | 7 ++++ .../app/services/settings.service.ts | 9 +++++ .../customization.component.html | 7 ++++ src/Ombi/Controllers/SettingsController.cs | 2 +- 9 files changed, 79 insertions(+), 13 deletions(-) diff --git a/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs b/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs index 9a33b799c..0087bbe02 100644 --- a/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs +++ b/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs @@ -2,7 +2,6 @@ { public class CustomPageSettings : Settings { - public bool Enabled { get; set; } public string Title { get; set; } public string Html { get; set; } } diff --git a/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs b/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs index 6c18c712f..5f0287fc4 100644 --- a/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs @@ -10,6 +10,7 @@ public string CustomDonationMessage { get; set; } public string Logo { get; set; } public bool RecentlyAddedPage { get; set; } + public bool UseCustomPage { get; set; } public void AddToUrl(string part) { diff --git a/src/Ombi.Store/Entities/Requests/MovieRequests.cs b/src/Ombi.Store/Entities/Requests/MovieRequests.cs index e5957ca63..677a4292c 100644 --- a/src/Ombi.Store/Entities/Requests/MovieRequests.cs +++ b/src/Ombi.Store/Entities/Requests/MovieRequests.cs @@ -1,6 +1,7 @@ using Ombi.Helpers; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; namespace Ombi.Store.Entities.Requests { @@ -26,6 +27,7 @@ namespace Ombi.Store.Entities.Requests public string LangCode { get; set; } [NotMapped] + [JsonIgnore] public string LanguageCode => LangCode.IsNullOrEmpty() ? "en" : LangCode; } } diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.html b/src/Ombi/ClientApp/app/custompage/custompage.component.html index 545f56cb5..3188f5d4e 100644 --- a/src/Ombi/ClientApp/app/custompage/custompage.component.html +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.html @@ -1,7 +1,22 @@ - -
- - -
-
-
\ No newline at end of file +
+
+ +
+
+ + + +
+ + + +
+
+ + + +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.ts b/src/Ombi/ClientApp/app/custompage/custompage.component.ts index dd9259dae..e5968cc6e 100644 --- a/src/Ombi/ClientApp/app/custompage/custompage.component.ts +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.ts @@ -1,4 +1,7 @@ import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { AuthService } from "../auth/auth.service"; +import { NotificationService, SettingsService } from "../services"; @Component({ templateUrl: "./custompage.component.html", @@ -6,14 +9,37 @@ }) export class CustomPageComponent implements OnInit { - public html: string; + public form: FormGroup; public isEditing: boolean; + public isAdmin: boolean; - constructor() { -// + constructor(private auth: AuthService, private settings: SettingsService, private fb: FormBuilder, + private notificationService: NotificationService) { } public ngOnInit() { - // + this.settings.getCustomPage().subscribe(x => { + + this.form = this.fb.group({ + enabled: [x.enabled], + title: [x.title, [Validators.required]], + html: [x.html, [Validators.required]], + }); + }); + this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + } + + public onSubmit() { + if (this.form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + this.settings.saveCustomPage(this.form.value).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved Custom Page settings"); + } else { + this.notificationService.success("There was an error when saving the Custom Page settings"); + } + }); } } diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index f2453c273..18a509bb2 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -120,6 +120,7 @@ export interface ICustomizationSettings extends ISettings { customDonationUrl: string; customDonationMessage: string; recentlyAddedPage: boolean; + useCustomPage: boolean; } export interface IJobSettings { @@ -158,6 +159,12 @@ export interface IAuthenticationSettings extends ISettings { enableOAuth: boolean; } +export interface ICustomPage extends ISettings { + enabled: boolean; + title: string; + html: string; +} + export interface IUserManagementSettings extends ISettings { importPlexUsers: boolean; importPlexAdmin: boolean; diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 64a6edd14..4e68d28df 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -10,6 +10,7 @@ import { ICronTestModel, ICronViewModelBody, ICustomizationSettings, + ICustomPage, IDiscordNotifcationSettings, IDogNzbSettings, IEmailNotificationSettings, @@ -112,6 +113,14 @@ export class SettingsService extends ServiceHelpers { return this.http.get(`${this.url}/Authentication`, {headers: this.headers}); } + public getCustomPage(): Observable { + return this.http.get(`${this.url}/CustomPage`, {headers: this.headers}); + } + + public saveCustomPage(model: ICustomPage): Observable { + return this.http.post(`${this.url}/CustomPage`, model, {headers: this.headers}); + } + public getClientId(): Observable { return this.http.get(`${this.url}/clientid`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/customization/customization.component.html b/src/Ombi/ClientApp/app/settings/customization/customization.component.html index 32d91aed9..90c6fb5bc 100644 --- a/src/Ombi/ClientApp/app/settings/customization/customization.component.html +++ b/src/Ombi/ClientApp/app/settings/customization/customization.component.html @@ -69,6 +69,13 @@ tooltipPosition="top" pTooltip="Set a custom message to be displayed in the navigation bar."> +
+ +
+ +
+
diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 770745786..892471d94 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -721,7 +721,7 @@ namespace Ombi.Controllers /// Saves the Custom Page Settings. /// /// - [HttpGet("CustomPage")] + [HttpPost("CustomPage")] public async Task CustomPageSettings([FromBody] CustomPageSettings page) { return await Save(page); From 7c97b104d23b2c8b66a9dfeebe92ed92cc9640fd Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 9 Jan 2019 08:04:59 +0000 Subject: [PATCH 210/325] Updated the AspnetCore.App package to remove the CVE-2019-0564 vulnerability --- src/Ombi.Core/Ombi.Core.csproj | 2 +- src/Ombi.Store/Ombi.Store.csproj | 4 ++-- src/Ombi/Ombi.csproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 3dad3eb5f..35688a6fe 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index f68d1d752..f905c9ffe 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 9da5a860f..881a6cc54 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -71,7 +71,7 @@ - + From 145166064a4dfca65de437b2fa1540e737e678ac Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 9 Jan 2019 08:44:35 +0000 Subject: [PATCH 211/325] Added a page where the admin can write/style/basically do whatever they want with e.g. FAQ for the users #2715 This needs to be enabled in the Customization Settings and then it's all configured on the page. --- .../Settings/Models/CustomPageSettings.cs | 1 + src/Ombi/ClientApp/app/app.component.html | 8 +++++ src/Ombi/ClientApp/app/app.component.ts | 16 +++++++-- .../app/custompage/custompage.component.html | 9 +++++ .../app/custompage/custompage.component.scss | 2 +- .../app/custompage/custompage.component.ts | 9 +++-- .../ClientApp/app/interfaces/ISettings.ts | 3 +- .../customization.component.html | 35 ++++++++++--------- src/Ombi/Ombi.csproj | 6 ++-- 9 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs b/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs index 0087bbe02..18c0125cb 100644 --- a/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs +++ b/src/Ombi.Settings/Settings/Models/CustomPageSettings.cs @@ -4,5 +4,6 @@ { public string Title { get; set; } public string Html { get; set; } + public string FontAwesomeIcon { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index 9f6d00a7e..08c153f31 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -34,6 +34,14 @@ {{ 'NavigationBar.Requests' | translate }} +
+
+ + + +
+
diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.scss b/src/Ombi/ClientApp/app/custompage/custompage.component.scss index 127ee8b74..702973737 100644 --- a/src/Ombi/ClientApp/app/custompage/custompage.component.scss +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.scss @@ -41,4 +41,4 @@ $bg-colour-disabled: #252424; :host app-ngx-editor /deep/ .ngx-editor-message { display:none !important; -} \ No newline at end of file +} diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.ts b/src/Ombi/ClientApp/app/custompage/custompage.component.ts index e5968cc6e..f346bef2b 100644 --- a/src/Ombi/ClientApp/app/custompage/custompage.component.ts +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.ts @@ -1,5 +1,6 @@ -import { Component, OnInit } from "@angular/core"; +import { Component, OnInit, SecurityContext } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { DomSanitizer } from "@angular/platform-browser"; import { AuthService } from "../auth/auth.service"; import { NotificationService, SettingsService } from "../services"; @@ -14,16 +15,18 @@ export class CustomPageComponent implements OnInit { public isAdmin: boolean; constructor(private auth: AuthService, private settings: SettingsService, private fb: FormBuilder, - private notificationService: NotificationService) { + private notificationService: NotificationService, + private sanitizer: DomSanitizer) { } public ngOnInit() { this.settings.getCustomPage().subscribe(x => { - + x.html = this.sanitizer.sanitize(SecurityContext.HTML, this.sanitizer.bypassSecurityTrustHtml(x.html)); this.form = this.fb.group({ enabled: [x.enabled], title: [x.title, [Validators.required]], html: [x.html, [Validators.required]], + fontAwesomeIcon: [x.fontAwesomeIcon, [Validators.required]], }); }); this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 18a509bb2..2f8a4e80b 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -161,8 +161,9 @@ export interface IAuthenticationSettings extends ISettings { export interface ICustomPage extends ISettings { enabled: boolean; + fontAwesomeIcon: string; title: string; - html: string; + html: any; } export interface IUserManagementSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/settings/customization/customization.component.html b/src/Ombi/ClientApp/app/settings/customization/customization.component.html index 90c6fb5bc..21a992c32 100644 --- a/src/Ombi/ClientApp/app/settings/customization/customization.component.html +++ b/src/Ombi/ClientApp/app/settings/customization/customization.component.html @@ -21,8 +21,8 @@
- +
@@ -36,8 +36,8 @@
- +
@@ -50,14 +50,16 @@
- +
-
@@ -65,17 +67,19 @@
-
-
- -
- -
+
+
+ + +
+
@@ -92,9 +96,8 @@
- +
diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 881a6cc54..dc447dd20 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -14,12 +14,12 @@ false - bin\Debug\netcoreapp2.0\Swagger.xml + bin\Debug\netcoreapp2.2\Swagger.xml 1701;1702;1705;1591; - bin\Release\netcoreapp2.0\Swagger.xml + bin\Release\netcoreapp2.2\Swagger.xml 1701;1702;1705;1591; TRACE;RELEASE;NETCOREAPP2_0 @@ -71,7 +71,7 @@ - + From dcc28ff26ee2ccbcd07df8b33212ebccfa9c4056 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 9 Jan 2019 12:24:47 +0000 Subject: [PATCH 212/325] Potentially fix #2726 --- src/Ombi.Core/Engine/MovieSearchEngine.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index 51e189db9..5e56e8abd 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -195,6 +195,10 @@ namespace Ombi.Core.Engine { // Check if this user requested it var user = await GetUser(); + if (user == null) + { + return; + } var request = await RequestService.MovieRequestService.GetAll() .AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id); if (request) From b375dd888b9b7798cbb4188a7b71a85cc9ef91c4 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 9 Jan 2019 13:10:38 +0000 Subject: [PATCH 213/325] There is now a new Job in ombi that will clear out the Plex/Emby data and recache. This will prevent the issues going forward that we have when Ombi and the Media server fall out of sync with deletions/updates #2641 #2362 #1566 --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 + src/Ombi.Helpers/LoggingEvents.cs | 1 + src/Ombi.Schedule/JobSetup.cs | 7 +- .../Ombi/{ => Interfaces}/IIssuesPurge.cs | 0 .../Ombi/Interfaces/IMediaDatabaseRefresh.cs | 9 ++ .../Ombi/{ => Interfaces}/INewsletterJob.cs | 0 .../{ => Interfaces}/IOmbiAutomaticUpdater.cs | 0 .../Ombi/{ => Interfaces}/IRefreshMetadata.cs | 0 .../{ => Interfaces}/IResendFailedRequests.cs | 0 .../Ombi/{ => Interfaces}/IWelcomeEmail.cs | 0 .../Jobs/Ombi/{ => Interfaces}/IssuesPurge.cs | 0 .../Jobs/Ombi/MediaDatabaseRefresh.cs | 120 ++++++++++++++++++ .../Settings/Models/JobSettings.cs | 1 + .../Settings/Models/JobSettingsHelper.cs | 5 +- .../ClientApp/app/interfaces/ISettings.ts | 1 + .../app/settings/jobs/jobs.component.html | 7 + .../app/settings/jobs/jobs.component.ts | 1 + src/Ombi/Controllers/SettingsController.cs | 1 + 18 files changed, 151 insertions(+), 3 deletions(-) rename src/Ombi.Schedule/Jobs/Ombi/{ => Interfaces}/IIssuesPurge.cs (100%) create mode 100644 src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs rename src/Ombi.Schedule/Jobs/Ombi/{ => Interfaces}/INewsletterJob.cs (100%) rename src/Ombi.Schedule/Jobs/Ombi/{ => Interfaces}/IOmbiAutomaticUpdater.cs (100%) rename src/Ombi.Schedule/Jobs/Ombi/{ => Interfaces}/IRefreshMetadata.cs (100%) rename src/Ombi.Schedule/Jobs/Ombi/{ => Interfaces}/IResendFailedRequests.cs (100%) rename src/Ombi.Schedule/Jobs/Ombi/{ => Interfaces}/IWelcomeEmail.cs (100%) rename src/Ombi.Schedule/Jobs/Ombi/{ => Interfaces}/IssuesPurge.cs (100%) create mode 100644 src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 190e79203..09dbf4e79 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -200,6 +200,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi.Helpers/LoggingEvents.cs b/src/Ombi.Helpers/LoggingEvents.cs index 40ec3fd2b..3893dc879 100644 --- a/src/Ombi.Helpers/LoggingEvents.cs +++ b/src/Ombi.Helpers/LoggingEvents.cs @@ -21,6 +21,7 @@ namespace Ombi.Helpers public static EventId PlexContentCacher => new EventId(2008); public static EventId SickRageCacher => new EventId(2009); public static EventId LidarrArtistCache => new EventId(2010); + public static EventId MediaReferesh => new EventId(2011); public static EventId MovieSender => new EventId(3000); diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index fa111d5f4..5cc818441 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -7,6 +7,7 @@ using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Lidarr; using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Plex; +using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Schedule.Jobs.Radarr; using Ombi.Schedule.Jobs.SickRage; using Ombi.Schedule.Jobs.Sonarr; @@ -21,7 +22,7 @@ namespace Ombi.Schedule IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache, ISettingsService jobsettings, ISickRageSync srSync, IRefreshMetadata refresh, INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist, - IIssuesPurge purge, IResendFailedRequests resender) + IIssuesPurge purge, IResendFailedRequests resender, IMediaDatabaseRefresh dbRefresh) { _plexContentSync = plexContentSync; _radarrSync = radarrSync; @@ -39,6 +40,7 @@ namespace Ombi.Schedule _lidarrArtistSync = artist; _issuesPurge = purge; _resender = resender; + _mediaDatabaseRefresh = dbRefresh; } private readonly IPlexContentSync _plexContentSync; @@ -57,6 +59,7 @@ namespace Ombi.Schedule private readonly ILidarrArtistSync _lidarrArtistSync; private readonly IIssuesPurge _issuesPurge; private readonly IResendFailedRequests _resender; + private readonly IMediaDatabaseRefresh _mediaDatabaseRefresh; public void Setup() { @@ -80,9 +83,9 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s)); + RecurringJob.AddOrUpdate(() => _mediaDatabaseRefresh.Start(), JobSettingsHelper.MediaDatabaseRefresh(s)); } - private bool _disposed; protected virtual void Dispose(bool disposing) { diff --git a/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IIssuesPurge.cs similarity index 100% rename from src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs rename to src/Ombi.Schedule/Jobs/Ombi/Interfaces/IIssuesPurge.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs new file mode 100644 index 000000000..11fe7c51a --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IMediaDatabaseRefresh.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Plex.Interfaces +{ + public interface IMediaDatabaseRefresh : IBaseJob + { + Task Start(); + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/INewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/INewsletterJob.cs similarity index 100% rename from src/Ombi.Schedule/Jobs/Ombi/INewsletterJob.cs rename to src/Ombi.Schedule/Jobs/Ombi/Interfaces/INewsletterJob.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/IOmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs similarity index 100% rename from src/Ombi.Schedule/Jobs/Ombi/IOmbiAutomaticUpdater.cs rename to src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/IRefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs similarity index 100% rename from src/Ombi.Schedule/Jobs/Ombi/IRefreshMetadata.cs rename to src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/IResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IResendFailedRequests.cs similarity index 100% rename from src/Ombi.Schedule/Jobs/Ombi/IResendFailedRequests.cs rename to src/Ombi.Schedule/Jobs/Ombi/Interfaces/IResendFailedRequests.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/IWelcomeEmail.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IWelcomeEmail.cs similarity index 100% rename from src/Ombi.Schedule/Jobs/Ombi/IWelcomeEmail.cs rename to src/Ombi.Schedule/Jobs/Ombi/Interfaces/IWelcomeEmail.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs similarity index 100% rename from src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs rename to src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs new file mode 100644 index 000000000..baa7fdcae --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs @@ -0,0 +1,120 @@ +using System; +using System.Threading.Tasks; +using Hangfire; +using Microsoft.Extensions.Logging; +using Ombi.Api.Plex; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; +using Ombi.Schedule.Jobs.Emby; +using Ombi.Schedule.Jobs.Plex.Interfaces; +using Ombi.Store.Repository; + +namespace Ombi.Schedule.Jobs.Plex +{ + public class MediaDatabaseRefresh : IMediaDatabaseRefresh + { + public MediaDatabaseRefresh(ISettingsService s, ILogger log, IPlexApi plexApi, + IPlexContentRepository plexRepo, IPlexContentSync c, IEmbyContentRepository embyRepo, IEmbyContentSync embySync) + { + _settings = s; + _log = log; + _api = plexApi; + _plexRepo = plexRepo; + _plexContentSync = c; + _embyRepo = embyRepo; + _embyContentSync = embySync; + _settings.ClearCache(); + } + + private readonly ISettingsService _settings; + private readonly ILogger _log; + private readonly IPlexApi _api; + private readonly IPlexContentRepository _plexRepo; + private readonly IPlexContentSync _plexContentSync; + private readonly IEmbyContentRepository _embyRepo; + private readonly IEmbyContentSync _embyContentSync; + + public async Task Start() + { + try + { + await RemovePlexData(); + await RemoveEmbyData(); + } + catch (Exception e) + { + _log.LogError(LoggingEvents.MediaReferesh, e, "Refreshing Media Data Failed"); + } + + } + + private async Task RemoveEmbyData() + { + try + { + var s = await _settings.GetSettingsAsync(); + if (!s.Enable) + { + return; + } + + const string episodeSQL = "DELETE FROM EmbyEpisode"; + const string mainSql = "DELETE FROM EmbyContent"; + await _embyRepo.ExecuteSql(episodeSQL); + await _embyRepo.ExecuteSql(mainSql); + + BackgroundJob.Enqueue(() => _embyContentSync.Start()); + } + catch (Exception e) + { + _log.LogError(LoggingEvents.MediaReferesh, e, "Refreshing Emby Data Failed"); + } + } + + private async Task RemovePlexData() + { + try + { + var s = await _settings.GetSettingsAsync(); + if (!s.Enable) + { + return; + } + + const string episodeSQL = "DELETE FROM PlexEpisode"; + const string seasonsSql = "DELETE FROM PlexSeasonsContent"; + const string mainSql = "DELETE FROM PlexServerContent"; + await _plexRepo.ExecuteSql(episodeSQL); + await _plexRepo.ExecuteSql(seasonsSql); + await _plexRepo.ExecuteSql(mainSql); + } + catch (Exception e) + { + _log.LogError(LoggingEvents.MediaReferesh, e, "Refreshing Plex Data Failed"); + } + } + + + + private bool _disposed; + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + _plexRepo?.Dispose(); + _settings?.Dispose(); + } + _disposed = true; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index 46a950185..4376088a3 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -16,5 +16,6 @@ public string LidarrArtistSync { get; set; } public string IssuesPurge { get; set; } public string RetryRequests { get; set; } + public string MediaDatabaseRefresh { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index 1aca72344..e2080e3cb 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -65,7 +65,10 @@ namespace Ombi.Settings.Settings.Models { return Get(s.RetryRequests, Cron.Daily(6)); } - + public static string MediaDatabaseRefresh(JobSettings s) + { + return Get(s.MediaDatabaseRefresh, Cron.DayInterval(5)); + } private static string Get(string settings, string defaultCron) { return settings.HasValue() ? settings : defaultCron; diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 2f8a4e80b..1f62a2c8d 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -138,6 +138,7 @@ export interface IJobSettings { lidarrArtistSync: string; issuesPurge: string; retryRequests: string; + mediaDatabaseRefresh: string; } export interface IIssueSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index e889c0fca..4532af9b3 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -105,6 +105,13 @@ The Issues Purge is required + +
+ + + The Media Database Refresh is required + +
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index 853005185..747a4bfde 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -37,6 +37,7 @@ export class JobsComponent implements OnInit { lidarrArtistSync: [x.lidarrArtistSync, Validators.required], issuesPurge: [x.issuesPurge, Validators.required], retryRequests: [x.retryRequests, Validators.required], + mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required], }); }); } diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 892471d94..0fe67edfd 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -522,6 +522,7 @@ namespace Ombi.Controllers j.LidarrArtistSync = j.LidarrArtistSync.HasValue() ? j.LidarrArtistSync : JobSettingsHelper.LidarrArtistSync(j); j.IssuesPurge = j.IssuesPurge.HasValue() ? j.IssuesPurge : JobSettingsHelper.IssuePurge(j); j.RetryRequests = j.RetryRequests.HasValue() ? j.RetryRequests : JobSettingsHelper.ResendFailedRequests(j); + j.MediaDatabaseRefresh = j.MediaDatabaseRefresh.HasValue() ? j.MediaDatabaseRefresh : JobSettingsHelper.MediaDatabaseRefresh(j); return j; } From 0e744f0fe0b9a48654df691d3e811c05a8a26158 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 9 Jan 2019 22:28:39 +0000 Subject: [PATCH 214/325] Update CHANGELOG.md --- CHANGELOG.md | 108 +++++++++------------------------------------------ 1 file changed, 18 insertions(+), 90 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0035180dc..f83641e45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,18 @@ # Changelog -## (unreleased) +## v3.0.4119 (2019-1-09) ### **New Features** +- Added a new Custom Page, this will allow you to completely change the page via a WYSIWYG editor! [TidusJar] + +- Added the ability to search movies via the movie db with a different language! [tidusjar] + +- Added the ability to specify a year when searching for movies. [tidusjar] + +- Made the newsletter use the default lanuage code set in the Ombi settings for movie information. [TidusJar] + - Added a global language flag that now applies to the search by default. [tidusjar] - Updated the frontend packages (Using Angular 7 now) [TidusJar] @@ -13,105 +21,28 @@ - Added {AvailableDate} as a Notification Variable, this is the date the request was marked as available. See here: https://github.com/tidusjar/Ombi/wiki/Notification-Template-Variables. [tidusjar] -- Added the ability to search movies via the movie db with a different language! [tidusjar] +- Updated the Newsletter template! Better mail client support [d1slact0r] -- Added the ability to specify a year when searching for movies. [tidusjar] - -- Update NewsletterTemplate.html. [d1slact0r] - -- Update NewsletterTemplate.html. [d1slact0r] - -- Update NewsletterTemplate.html. [d1slact0r] - -- Update HtmlTemplateGenerator.cs. [d1slact0r] - -- Update NewsletterTemplate.html. [d1slact0r] - -- Update HtmlTemplateGenerator.cs. [d1slact0r] - -- Update NewsletterTemplate.html. [d1slact0r] - -- Update NewsletterTemplate.html. [d1slact0r] - -- Update NewsletterTemplate.html. [d1slact0r] - -- Update HtmlTemplateGenerator.cs. [d1slact0r] - -- Updated boostrap #2694. [Jamie] +- Updated boostrap #2694. [TidusJar] - Added the ability to deny a request with a reason. [TidusJar] -## v3.0.4036 (2018-12-11) - - -- Update EmbyEpisodeSync.cs. [Jamie] - -- Updated to .net core 2.2 and included a linux-arm64 build. [TidusJar] - -### **Fixes** - -- Made the newsletter use the default lanuage code set in the Ombi settings for movie information. [TidusJar] - -- Save the language code against the request so we can use it later e.g. Sending to the DVR apps. [tidusjar] - -- Fixed #2716. [tidusjar] +- Updated to .net core 2.2 and included a linux-arm64 build. [aptalca] - Make the newsletter BCC the users rather than creating a million newsletters (Hopefully will stop SMTP providers from marking as spam). This does mean that the custom user customization in the newsletter will no longer work. [TidusJar] +- New translations [TidusJar] + +### **Fixes** + +- Fixed #2716. [tidusjar] + - If we don't know the Plex agent, then see if it's a ImdbId, if it's not check the string for any episode and season hints #2695. [tidusjar] -- 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] - -- New translations en.json (Dutch) [Jamie] - -- New translations en.json (Dutch) [Jamie] - -- New translations en.json (Dutch) [Jamie] - -- Made the search results the language specified in the search refinement. [tidusjar] - - Fixed #2704. [tidusjar] -- Now it is fixed :) [d1slact0r] - -- Android please be nice now. [d1slact0r] - -- Fixed title bit better. [d1slact0r] - -- Fixed titles. [d1slact0r] - -- This should fix the build for sure (stupid quotes) [d1slact0r] - -- Fixes build. [d1slact0r] - -- Rewritten the whole newsletter template. [d1slact0r] - - Fixed #2697. [tidusjar] -- Add linux-arm runtime identifier. [aptalca] - -- Add back arm packages. [aptalca] - -- Add arm32 package. [aptalca] - - Fixed #2691. [tidusjar] - Fixed linting. [TidusJar] @@ -120,13 +51,10 @@ - Fixed #2678. [TidusJar] -- Deny reason for movie requests. [TidusJar] - - Set the landing and login pages background refresh to 15 seconds rather than 10 and 7. [TidusJar] - Fixed a bug with us thinking future dated emby episodes are not available, Consoldated the emby and plex search rules (since they have the same logic) [TidusJar] -- Fixed build. [TidusJar] ## v3.0.4036 (2018-12-11) From e645d4d41a066716caef7a504ca60e361ab598b6 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 10 Jan 2019 08:11:34 +0000 Subject: [PATCH 215/325] Added new classes to the posters #2732 --- src/Ombi/ClientApp/app/search/moviesearch.component.html | 2 +- src/Ombi/ClientApp/app/search/music/artistsearch.component.html | 2 +- src/Ombi/ClientApp/app/search/tvsearch.component.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index e2ba69cb6..bc30a1fff 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -70,7 +70,7 @@
- poster + poster
diff --git a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html index 77a68a841..cc1f093df 100644 --- a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html @@ -3,7 +3,7 @@
- poster + poster
diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index 9193e9174..3fb349f88 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -50,7 +50,7 @@
- poster + poster
From c8ee14d8d7d744260136f01fc337340f18e37d67 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 08:13:29 +0000 Subject: [PATCH 216/325] Update README.md --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6347a8a5f..61cda24f3 100644 --- a/README.md +++ b/README.md @@ -117,13 +117,12 @@ Please feel free to submit a pull request! # Donation If you feel like donating you can donate with the below buttons! -[![Patreon](https://www.ombi.io/img/patreondonate.svg)](https://patreon.com/tidusjar/Ombi) -[![Paypal](https://www.ombi.io/img/paypaldonate.svg)](https://paypal.me/PlexRequestsNet) + +[![Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://patreon.com/tidusjar/Ombi) +[![Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://paypal.me/PlexRequestsNet) ### A massive thanks to everyone for all their help! -## Stats -[![Throughput Graph](https://graphs.waffle.io/tidusjar/PlexRequests.Net/throughput.svg)](https://waffle.io/tidusjar/PlexRequests.Net/metrics/throughput) ### Sponsors ### - [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools From 47f3240c73be3e267ae3a7ba70a92308accc8efe Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 10 Jan 2019 08:14:20 +0000 Subject: [PATCH 217/325] !wip changelog --- CHANGELOG.md | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0035180dc..9e7ea6f21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,22 @@ # Changelog - ## (unreleased) ### **New Features** +- Added new classes to the posters #2732. [TidusJar] + + +## v3.0.4119 (2019-01-09) + +### **New Features** + +- Update CHANGELOG.md. [Jamie] + +- Added a page where the admin can write/style/basically do whatever they want with e.g. FAQ for the users #2715 This needs to be enabled in the Customization Settings and then it's all configured on the page. [TidusJar] + +- Updated the AspnetCore.App package to remove the CVE-2019-0564 vulnerability. [TidusJar] + - Added a global language flag that now applies to the search by default. [tidusjar] - Updated the frontend packages (Using Angular 7 now) [TidusJar] @@ -41,15 +53,24 @@ - Added the ability to deny a request with a reason. [TidusJar] -## v3.0.4036 (2018-12-11) - - - Update EmbyEpisodeSync.cs. [Jamie] - Updated to .net core 2.2 and included a linux-arm64 build. [TidusJar] ### **Fixes** +- There is now a new Job in ombi that will clear out the Plex/Emby data and recache. This will prevent the issues going forward that we have when Ombi and the Media server fall out of sync with deletions/updates #2641 #2362 #1566. [TidusJar] + +- Potentially fix #2726. [TidusJar] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- Fixed #2725 and #2721. [TidusJar] + - Made the newsletter use the default lanuage code set in the Ombi settings for movie information. [TidusJar] - Save the language code against the request so we can use it later e.g. Sending to the DVR apps. [tidusjar] From 6072f3f31c381504e553d8ff500b78af64709229 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 17:05:34 +0000 Subject: [PATCH 218/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index b00bcc97f..8111151e5 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -48,7 +48,7 @@ "Requests": "Förfrågningar", "UserManagement": "Användarhantering", "Issues": "Problem", - "Vote": "Vote", + "Vote": "Rösta", "Donate": "Donera!", "DonateLibraryMaintainer": "Donera till bibliotekets utvecklare", "DonateTooltip": "Det är så här jag övertygar min fru att jag vill spendera min fritid att utveckla Ombi ;)", @@ -74,7 +74,7 @@ "ViewOnEmby": "Visa på Emby", "RequestAdded": "Efterfrågan om {{title}} har lagts till", "Similar": "Liknande", - "Refine": "Refine", + "Refine": "Förfina", "Movies": { "PopularMovies": "Populära filmer", "UpcomingMovies": "Kommande filmer", From fa5a05e99e25f351ee93b1bed5a28b9bebb90462 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 17:23:39 +0000 Subject: [PATCH 219/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 8111151e5..803ceee70 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -171,15 +171,15 @@ "PendingApproval": "Väntar på godkännande" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "TV: {{remaining}}/{{total}} återstående", + "MovieRemaining": "Movies: {{remaining}}/{{total}} återstående", + "MusicRemaining": "Music: {{remaining}}/{{total}} återstående", "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", + "CompletedVotesTab": "Röstat", "VotesTab": "Votes Needed" } } From bae9ac225c0d1fa701e121e4648c920f8babaf0c Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 17:35:54 +0000 Subject: [PATCH 220/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 803ceee70..f03db6b33 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -12,9 +12,9 @@ "Common": { "ContinueButton": "Fortsätt", "Available": "Tillgänglig", - "PartiallyAvailable": "Delvis tillgänliga", + "PartiallyAvailable": "Delvis tillgänglig", "Monitored": "Övervakad", - "NotAvailable": "Finns ej", + "NotAvailable": "Inte tillgänglig", "ProcessingRequest": "Bearbetar förfrågan", "PendingApproval": "Väntar på godkännande", "RequestDenied": "Efterfrågan nekas", @@ -180,6 +180,6 @@ }, "Votes": { "CompletedVotesTab": "Röstat", - "VotesTab": "Votes Needed" + "VotesTab": "Röster krävs" } } From c010dac5025be2bafdf7067f51d7076208b58039 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 17:48:44 +0000 Subject: [PATCH 221/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index f03db6b33..13e2de03c 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -18,11 +18,11 @@ "ProcessingRequest": "Bearbetar förfrågan", "PendingApproval": "Väntar på godkännande", "RequestDenied": "Efterfrågan nekas", - "NotRequested": "Inte önskad", - "Requested": "Begärd önskan", + "NotRequested": "Inte begärd", + "Requested": "Begärd", "Request": "Begär", "Denied": "Nekad", - "Approve": "Godkän", + "Approve": "Godkänn", "PartlyAvailable": "Delvis tillgänglig", "Errors": { "Validation": "Vänligen kontrollera din angivna värden" From 9e970985a9fc7814012542aeb7520b3d26e1837a Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 17:55:30 +0000 Subject: [PATCH 222/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 13e2de03c..9de893458 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -34,11 +34,11 @@ }, "LandingPage": { "OnlineHeading": "Online just nu", - "OnlineParagraph": "Medieservern är online för tillfället", + "OnlineParagraph": "Medieservern är för närvarande online", "PartiallyOnlineHeading": "Delvis online", "PartiallyOnlineParagraph": "Medieservern är delvis online.", - "MultipleServersUnavailable": "Det är {{serversUnavailable}} servrar offline just nu utav {{totalServers}} servrar totalt.", - "SingleServerUnavailable": "Det finns {{serversUnavailable}} servrar offline utav {{totalServers}}.", + "MultipleServersUnavailable": "Servrar offline: {{serversUnavailable}}, av totalt {{totalServers}}.", + "SingleServerUnavailable": "Servrar offline: {{serversUnavailable}}, av totalt {{totalServers}}.", "OfflineHeading": "För närvarande Offline", "OfflineParagraph": "Medieservern är för närvarande offline.", "CheckPageForUpdates": "Kontrollera sidan för kontinuerlig platsuppdateringar." From 880a2e7d2342d671a1d4d37e096320bf8b1eca53 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 18:02:34 +0000 Subject: [PATCH 223/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 9de893458..42deebd24 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -41,7 +41,7 @@ "SingleServerUnavailable": "Servrar offline: {{serversUnavailable}}, av totalt {{totalServers}}.", "OfflineHeading": "För närvarande Offline", "OfflineParagraph": "Medieservern är för närvarande offline.", - "CheckPageForUpdates": "Kontrollera sidan för kontinuerlig platsuppdateringar." + "CheckPageForUpdates": "Håll utkik här för uppdateringar på denna sida." }, "NavigationBar": { "Search": "Sök", From 602a2c22801a15aaa35073b369957cff09b7ae0e Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 18:11:03 +0000 Subject: [PATCH 224/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 42deebd24..c1096aefe 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -51,7 +51,7 @@ "Vote": "Rösta", "Donate": "Donera!", "DonateLibraryMaintainer": "Donera till bibliotekets utvecklare", - "DonateTooltip": "Det är så här jag övertygar min fru att jag vill spendera min fritid att utveckla Ombi ;)", + "DonateTooltip": "Det är så här jag övertygar min fru att låta mig spendera min fritid att utveckla Ombi ;)", "UpdateAvailableTooltip": "Uppdatering tillgänglig!", "Settings": "Inställningar", "Welcome": "Välkommen {{username}}", @@ -67,8 +67,8 @@ "TvTab": "TV-serier", "MusicTab": "Musik", "Suggestions": "Förslag", - "NoResults": "Tyvärr, hittade vi inte några resultat!", - "DigitalDate": "Digitalt släpp: {{date}}", + "NoResults": "Tyvärr hittade vi inte några resultat!", + "DigitalDate": "Digitalt releasedatum: {{date}}", "TheatricalRelease": "Biopremiär: {{date}}", "ViewOnPlex": "Visa på Plex", "ViewOnEmby": "Visa på Emby", From b1be8bdddb91f0df4ba6ff9ee32db0615485def0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 18:31:01 +0000 Subject: [PATCH 225/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index c1096aefe..e9212d960 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -72,7 +72,7 @@ "TheatricalRelease": "Biopremiär: {{date}}", "ViewOnPlex": "Visa på Plex", "ViewOnEmby": "Visa på Emby", - "RequestAdded": "Efterfrågan om {{title}} har lagts till", + "RequestAdded": "Begäran av {{title}} har lagts till", "Similar": "Liknande", "Refine": "Förfina", "Movies": { @@ -85,7 +85,7 @@ }, "TvShows": { "Popular": "Populära", - "Trending": "Trendar", + "Trending": "Hetast just nu", "MostWatched": "Mest sedda", "MostAnticipated": "Mest efterlängtade", "Results": "Resultat", @@ -94,26 +94,26 @@ "FirstSeason": "Första säsongen", "LatestSeason": "Senaste säsongen", "Select": "Välj...", - "SubmitRequest": "Skicka förfrågan", + "SubmitRequest": "Skicka begäran", "Season": "Säsong: {{seasonNumber}}", - "SelectAllInSeason": "Välj alla i denna säsong {{seasonNumber}}" + "SelectAllInSeason": "Välj alla avsnitt i säsong {{seasonNumber}}" } }, "Requests": { "Title": "Efterfrågningar", - "Paragraph": "Nedan kan du se din och andras efterfrågningar, samt nedladdnings och godkännande status.", + "Paragraph": "Nedan kan du se dina och alla andras förfrågningar, samt deras nedladdnings-och godkännandestatus.", "MoviesTab": "Filmer", "TvTab": "TV-serier", "MusicTab": "Musik", "RequestedBy": "Efterfrågats av:", "Status": "Status:", - "RequestStatus": "Status för efterfrågan:", + "RequestStatus": "Status för begäran:", "Denied": " Nekad:", "TheatricalRelease": "Biopremiär: {{date}}", - "ReleaseDate": "Släppt: {{date}}", + "ReleaseDate": "Releasedatum: {{date}}", "TheatricalReleaseSort": "Biopremiär", "DigitalRelease": "Digitalt Releasedatum: {{date}}", - "RequestDate": "Datum för efterfrågan:", + "RequestDate": "Datum för begäran:", "QualityOverride": "Kvalité överskridande:", "RootFolderOverride": "Root mapp överskridande:", "ChangeRootFolder": "Byt Root mapp", From d3ae35f80ea36f893d162b6ac7264b4e4a2ba3e9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 18:34:42 +0000 Subject: [PATCH 226/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index e9212d960..11970f87b 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -114,10 +114,10 @@ "TheatricalReleaseSort": "Biopremiär", "DigitalRelease": "Digitalt Releasedatum: {{date}}", "RequestDate": "Datum för begäran:", - "QualityOverride": "Kvalité överskridande:", - "RootFolderOverride": "Root mapp överskridande:", - "ChangeRootFolder": "Byt Root mapp", - "ChangeQualityProfile": "Byt kvalité profil", + "QualityOverride": "Kvalitétsöverskridande:", + "RootFolderOverride": "Rotmappsöverskridande:", + "ChangeRootFolder": "Byt rotmapp", + "ChangeQualityProfile": "Byt kvalitétsprofil", "MarkUnavailable": "Markera Otillgänglig", "MarkAvailable": "Markera Tillgänglig", "Remove": "Ta bort", From 62b8a6d57aeaadad1675e792e7d377dea95c9205 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 10 Jan 2019 18:41:07 +0000 Subject: [PATCH 227/325] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 11970f87b..78ea25051 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -124,29 +124,29 @@ "Deny": "Neka", "Season": "Säsong:", "GridTitle": "Titel", - "AirDate": "Sändningsdatum", + "AirDate": "Releasedatum", "GridStatus": "Status", - "ReportIssue": "Rapportera Problem", + "ReportIssue": "Rapportera problem", "Filter": "Filtrera", "Sort": "Sortera", "SeasonNumberHeading": "Säsong: {seasonNumber}", "SortTitleAsc": "Titel ▲", "SortTitleDesc": "Titel ▼", - "SortRequestDateAsc": "Efterfrågades ▲", - "SortRequestDateDesc": "Efterfrågades ▼", + "SortRequestDateAsc": "Datum för begäran ▲", + "SortRequestDateDesc": "Datum för begäran ▼", "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { "Quota": "{{remaining}}/{{total}} återstående förfrågningar", - "NextDays": "En annan begäran kommer att läggas till om {{time}} Dagar", - "NextHours": "En annan begäran kommer att läggas till om {{time}} Timmar", - "NextMinutes": "En annan begäran kommer att läggas till om {{time}} Minuter", - "NextMinute": "En annan begäran kommer att läggas till om {{time}} Minut" + "NextDays": "En ny begäran kommer att läggas till om {{time}} Dagar", + "NextHours": "En ny begäran kommer att läggas till om {{time}} Timmar", + "NextMinutes": "En ny begäran kommer att läggas till om {{time}} Minuter", + "NextMinute": "En ny begäran kommer att läggas till om {{time}} Minut" } }, "Issues": { "Title": "Problem", - "PendingTitle": "Väntande Problem", + "PendingTitle": "Väntande problem", "InProgressTitle": "Pågående problem", "ResolvedTitle": "Lösta problem", "ColumnTitle": "Titel", From a1fdca3c3701f0b5b34b1d1c4edc78217b4c0705 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 16 Jan 2019 20:58:36 +0000 Subject: [PATCH 228/325] Removed the Add user to Plex from Ombi --- .../usermanagement/addplexuser.component.html | 66 --------------- .../usermanagement/addplexuser.component.ts | 84 ------------------- .../usermanagement.component.html | 4 +- .../usermanagement.component.ts | 10 +-- 4 files changed, 2 insertions(+), 162 deletions(-) delete mode 100644 src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html delete mode 100644 src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts diff --git a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html deleted file mode 100644 index 5f56ee710..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts deleted file mode 100644 index 1c77a0181..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Component, Input, OnInit } from "@angular/core"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; - -import { NotificationService, PlexService } from "../services"; - -import { IPlexSection, IPlexServersAdd } from "../interfaces"; - -@Component({ - selector: "ngbd-modal-content", - templateUrl: "./addplexuser.component.html", -}) -export class AddPlexUserComponent implements OnInit { - - @Input() public name: string; - - public plexServers: IPlexServersAdd[]; - public plexLibs: IPlexSection[]; - - public libsSelected: number[] = []; - - public form: FormGroup; - - constructor(public activeModal: NgbActiveModal, - private plexService: PlexService, - private notificationService: NotificationService, - private fb: FormBuilder) { - } - - public ngOnInit(): void { - this.form = this.fb.group({ - selectedServer: [null, Validators.required], - allLibsSelected: [true], - username:[null, Validators.required], - }); - this.getServers(); - } - - public getServers() { - this.plexService.getServersFromSettings().subscribe(x => { - if (x.success) { - this.plexServers = x.servers; - } - }); - } - - public getPlexLibs(machineId: string) { - this.plexService.getLibrariesFromSettings(machineId).subscribe(x => { - if (x.successful) { - this.plexLibs = x.data; - } - }); - } - - public selected() { - this.getPlexLibs(this.form.value.selectedServer); - } - - public checkedLib(checked: boolean, value: number) { - if(checked) { - this.libsSelected.push(value); - } else { - this.libsSelected = this.libsSelected.filter(v => v !== value); - } - } - - public onSubmit(form: FormGroup) { - if (form.invalid) { - this.notificationService.error("Please check your entered values"); - return; - } - const libs = form.value.allLibsSelected ? [] : this.libsSelected; - - this.plexService.addUserToServer({ username: form.value.username, machineIdentifier: form.value.selectedServer, libsSelected: libs }).subscribe(x => { - if (x.success) { - this.notificationService.success("User added to Plex"); - } else { - this.notificationService.error(x.error); - } - this.activeModal.close(); - }); - - } -} diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index b8a89c2b3..5040e53a9 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -5,9 +5,7 @@ -
- -
+
diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts index 082a6086c..98ec35081 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts @@ -1,9 +1,7 @@ import { Component, OnInit } from "@angular/core"; -import { NgbModal } from "@ng-bootstrap/ng-bootstrap"; import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IUser } from "../interfaces"; import { IdentityService, NotificationService, SettingsService } from "../services"; -import { AddPlexUserComponent } from "./addplexuser.component"; @Component({ templateUrl: "./usermanagement.component.html", @@ -27,8 +25,7 @@ export class UserManagementComponent implements OnInit { constructor(private identityService: IdentityService, private settingsService: SettingsService, private notificationService: NotificationService, - private plexSettings: SettingsService, - private modalService: NgbModal) { } + private plexSettings: SettingsService) { } public ngOnInit() { this.users = []; @@ -43,11 +40,6 @@ export class UserManagementComponent implements OnInit { this.settingsService.getEmailNotificationSettings().subscribe(x => this.emailSettings = x); } - public open() { - const modalRef = this.modalService.open(AddPlexUserComponent, {container:"ombi", backdropClass:"custom-modal-backdrop", windowClass:"window"}); - modalRef.componentInstance.name = "World"; - } - public welcomeEmail(user: IUser) { if (!user.emailAddress) { this.notificationService.error("The user needs an email address."); From 3b913923233ec65976b8a33ede0104860f757e93 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 16 Jan 2019 21:33:15 +0000 Subject: [PATCH 229/325] #2363 Added the ability to pass any username into the API using the ApiAlias header --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 3 +- src/Ombi.Core/Engine/MusicRequestEngine.cs | 3 +- src/Ombi.Core/Helpers/TvShowRequestBuilder.cs | 1 + .../Models/Requests/MovieRequestViewModel.cs | 9 + .../Requests/MusicArtistRequestViewModel.cs | 1 + .../Models/Requests/TvRequestViewModel.cs | 3 + src/Ombi.Store/Entities/OmbiUser.cs | 2 +- .../Entities/Requests/BaseRequest.cs | 1 + ...0190116212601_RequestedByAlias.Designer.cs | 1212 +++++++++++++++++ .../20190116212601_RequestedByAlias.cs | 40 + .../Migrations/OmbiContextModelSnapshot.cs | 8 +- .../ClientApp/app/interfaces/IRequestModel.ts | 1 + .../app/requests/movierequests.component.html | 96 +- .../music/musicrequests.component.html | 88 +- .../tvrequest-children.component.html | 74 +- .../usermanagement/usermanagement.module.ts | 5 - .../Controllers/MusicRequestController.cs | 10 + src/Ombi/Controllers/RequestController.cs | 14 + 18 files changed, 1455 insertions(+), 116 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.cs diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index b584a4bed..8f4693be1 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -83,7 +83,8 @@ namespace Ombi.Core.Engine Approved = false, RequestedUserId = userDetails.Id, Background = movieInfo.BackdropPath, - LangCode = model.LanguageCode + LangCode = model.LanguageCode, + RequestedByAlias = model.RequestedByAlias }; var usDates = movieInfo.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US"); diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index 66be18cf6..8457de515 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -83,7 +83,8 @@ namespace Ombi.Core.Engine Title = album.title, Disk = album.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url, Cover = album.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url, - ForeignArtistId = album?.artist?.foreignArtistId ?? string.Empty + ForeignArtistId = album?.artist?.foreignArtistId ?? string.Empty, + RequestedByAlias = model.RequestedByAlias }; if (requestModel.Cover.IsNullOrEmpty()) { diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs index 334284484..56d227ad0 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs @@ -72,6 +72,7 @@ namespace Ombi.Core.Helpers SeasonRequests = new List(), Title = ShowInfo.name, ReleaseYear = FirstAir, + RequestedByAlias = model.RequestedByAlias, SeriesType = ShowInfo.genres.Any( s => s.Equals("Anime", StringComparison.InvariantCultureIgnoreCase)) ? SeriesType.Anime : SeriesType.Standard }; diff --git a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs index 92e221abd..5a79d2982 100644 --- a/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/MovieRequestViewModel.cs @@ -24,11 +24,20 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion + +using Newtonsoft.Json; + namespace Ombi.Core.Models.Requests { public class MovieRequestViewModel { public int TheMovieDbId { get; set; } public string LanguageCode { get; set; } = "en"; + + /// + /// This is only set from a HTTP Header + /// + [JsonIgnore] + public string RequestedByAlias { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/MusicArtistRequestViewModel.cs b/src/Ombi.Core/Models/Requests/MusicArtistRequestViewModel.cs index 4c3426c9e..cd799406b 100644 --- a/src/Ombi.Core/Models/Requests/MusicArtistRequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/MusicArtistRequestViewModel.cs @@ -3,5 +3,6 @@ public class MusicAlbumRequestViewModel { public string ForeignAlbumId { get; set; } + public string RequestedByAlias { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs b/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs index 78f9edd6d..c17925b1b 100644 --- a/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Newtonsoft.Json; namespace Ombi.Core.Models.Requests { @@ -9,6 +10,8 @@ namespace Ombi.Core.Models.Requests public bool FirstSeason { get; set; } public int TvDbId { get; set; } public List Seasons { get; set; } = new List(); + [JsonIgnore] + public string RequestedByAlias { get; set; } } public class SeasonsViewModel diff --git a/src/Ombi.Store/Entities/OmbiUser.cs b/src/Ombi.Store/Entities/OmbiUser.cs index 801a50cb1..edb9708a9 100644 --- a/src/Ombi.Store/Entities/OmbiUser.cs +++ b/src/Ombi.Store/Entities/OmbiUser.cs @@ -34,7 +34,7 @@ namespace Ombi.Store.Entities public bool IsEmbyConnect => UserType == UserType.EmbyUser && EmbyConnectUserId.HasValue(); [NotMapped] - public string UserAlias => string.IsNullOrEmpty(Alias) ? UserName : Alias; + public virtual string UserAlias => string.IsNullOrEmpty(Alias) ? UserName : Alias; [NotMapped] public bool EmailLogin { get; set; } diff --git a/src/Ombi.Store/Entities/Requests/BaseRequest.cs b/src/Ombi.Store/Entities/Requests/BaseRequest.cs index f224032f1..596041a51 100644 --- a/src/Ombi.Store/Entities/Requests/BaseRequest.cs +++ b/src/Ombi.Store/Entities/Requests/BaseRequest.cs @@ -17,6 +17,7 @@ namespace Ombi.Store.Entities.Requests public DateTime MarkedAsDenied { get; set; } public string DeniedReason { get; set; } public RequestType RequestType { get; set; } + public string RequestedByAlias { get; set; } [ForeignKey(nameof(RequestedUserId))] public OmbiUser RequestedUser { get; set; } diff --git a/src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.Designer.cs b/src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.Designer.cs new file mode 100644 index 000000000..45197bdfb --- /dev/null +++ b/src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.Designer.cs @@ -0,0 +1,1212 @@ +// +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 +{ + [DbContext(typeof(OmbiContext))] + [Migration("20190116212601_RequestedByAlias")] + partial class RequestedByAlias + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.cs b/src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.cs new file mode 100644 index 000000000..1e55c2f6e --- /dev/null +++ b/src/Ombi.Store/Migrations/20190116212601_RequestedByAlias.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class RequestedByAlias : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequestedByAlias", + table: "MovieRequests", + nullable: true); + + migrationBuilder.AddColumn( + name: "RequestedByAlias", + table: "ChildRequests", + nullable: true); + + migrationBuilder.AddColumn( + name: "RequestedByAlias", + table: "AlbumRequests", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequestedByAlias", + table: "MovieRequests"); + + migrationBuilder.DropColumn( + name: "RequestedByAlias", + table: "ChildRequests"); + + migrationBuilder.DropColumn( + name: "RequestedByAlias", + table: "AlbumRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 9baf6712b..50a34a931 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687"); + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -583,6 +583,8 @@ namespace Ombi.Store.Migrations b.Property("RequestType"); + b.Property("RequestedByAlias"); + b.Property("RequestedDate"); b.Property("RequestedUserId"); @@ -621,6 +623,8 @@ namespace Ombi.Store.Migrations b.Property("RequestType"); + b.Property("RequestedByAlias"); + b.Property("RequestedDate"); b.Property("RequestedUserId"); @@ -749,6 +753,8 @@ namespace Ombi.Store.Migrations b.Property("RequestType"); + b.Property("RequestedByAlias"); + b.Property("RequestedDate"); b.Property("RequestedUserId"); diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index 343db5acc..e9b7c53f7 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -87,6 +87,7 @@ export interface IBaseRequest { requestedUser: IUser; canApprove: boolean; title: string; + requestedByAlias: string; } export interface ITvRequests { diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index f8ea31950..8d2158236 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -1,36 +1,39 @@
- + -
@@ -105,8 +121,8 @@ Please enter a rejection reason, the user will be notified of this: - - - - - + + + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index 4171fbfbc..166f42673 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -16,7 +16,6 @@ import { IdentityService, PlexService, RadarrService, SonarrService } from "../s import { AuthGuard } from "../auth/auth.guard"; import { OrderModule } from "ngx-order-pipe"; -import { AddPlexUserComponent } from "./addplexuser.component"; import { SharedModule } from "../shared/shared.module"; @@ -45,12 +44,8 @@ const routes: Routes = [ declarations: [ UserManagementComponent, UpdateDetailsComponent, - AddPlexUserComponent, UserManagementUserComponent, ], - entryComponents:[ - AddPlexUserComponent, - ], exports: [ RouterModule, ], diff --git a/src/Ombi/Controllers/MusicRequestController.cs b/src/Ombi/Controllers/MusicRequestController.cs index ea3f615f0..a4605904b 100644 --- a/src/Ombi/Controllers/MusicRequestController.cs +++ b/src/Ombi/Controllers/MusicRequestController.cs @@ -76,6 +76,7 @@ namespace Ombi.Controllers [HttpPost] public async Task RequestAlbum([FromBody] MusicAlbumRequestViewModel album) { + album.RequestedByAlias = GetApiAlias(); var result = await _engine.RequestAlbum(album); if (result.Result) { @@ -168,5 +169,14 @@ namespace Ombi.Controllers { return await _engine.GetRemainingRequests(); } + private string GetApiAlias() + { + if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias)) + { + return apiAlias; + } + + return null; + } } } \ No newline at end of file diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index b3cccf9d1..36073a294 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -8,12 +8,14 @@ using System.Collections.Generic; using System.Threading.Tasks; using Ombi.Store.Entities.Requests; using System.Diagnostics; +using System.Linq; using Microsoft.Extensions.Logging; using Ombi.Attributes; using Ombi.Core.Models.UI; using Ombi.Models; using Ombi.Store.Entities; using Ombi.Core.Models; +using Ombi.Helpers; namespace Ombi.Controllers { @@ -82,6 +84,7 @@ namespace Ombi.Controllers [HttpPost("movie")] public async Task RequestMovie([FromBody] MovieRequestViewModel movie) { + movie.RequestedByAlias = GetApiAlias(); var result = await MovieRequestEngine.RequestMovie(movie); if (result.Result) { @@ -277,6 +280,7 @@ namespace Ombi.Controllers [HttpPost("tv")] public async Task RequestTv([FromBody] TvRequestViewModel tv) { + tv.RequestedByAlias = GetApiAlias(); var result = await TvRequestEngine.RequestTvShow(tv); if (result.Result) { @@ -521,5 +525,15 @@ namespace Ombi.Controllers { return await TvRequestEngine.GetRemainingRequests(); } + + private string GetApiAlias() + { + if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias)) + { + return apiAlias; + } + + return null; + } } } \ No newline at end of file From b16ac277014f406c40cfb0fc3f0ae8a44bd9a2e0 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 16 Jan 2019 21:38:11 +0000 Subject: [PATCH 230/325] Make sure we can only set the ApiAlias when using the API Key --- src/Ombi.Tests/TestStartup.cs | 124 +++++++++--------- .../Controllers/MusicRequestController.cs | 13 +- src/Ombi/Controllers/RequestController.cs | 11 +- 3 files changed, 79 insertions(+), 69 deletions(-) diff --git a/src/Ombi.Tests/TestStartup.cs b/src/Ombi.Tests/TestStartup.cs index fad346df0..07d54a936 100644 --- a/src/Ombi.Tests/TestStartup.cs +++ b/src/Ombi.Tests/TestStartup.cs @@ -1,71 +1,71 @@ -using System; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features.Authentication; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Moq; -using Ombi.Api.Emby; -using Ombi.Api.Plex; -using Ombi.Core.Authentication; -using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; -using Ombi.Models.Identity; -using Ombi.Store.Context; -using Ombi.Store.Entities; -using Ombi.Store.Repository; +//using System; +//using Microsoft.AspNetCore.Builder; +//using Microsoft.AspNetCore.Hosting; +//using Microsoft.AspNetCore.Http; +//using Microsoft.AspNetCore.Http.Features.Authentication; +//using Microsoft.AspNetCore.Identity; +//using Microsoft.Extensions.DependencyInjection; +//using Microsoft.Extensions.Options; +//using Moq; +//using Ombi.Api.Emby; +//using Ombi.Api.Plex; +//using Ombi.Core.Authentication; +//using Ombi.Core.Settings; +//using Ombi.Core.Settings.Models.External; +//using Ombi.Models.Identity; +//using Ombi.Store.Context; +//using Ombi.Store.Entities; +//using Ombi.Store.Repository; -namespace Ombi.Tests -{ - public class TestStartup - { - public IServiceProvider ConfigureServices(IServiceCollection services) - { - var _plexApi = new Mock(); - var _embyApi = new Mock(); - var _tokenSettings = new Mock>(); - var _embySettings = new Mock>(); - var _plexSettings = new Mock>(); - var audit = new Mock(); - var tokenRepo = new Mock(); +//namespace Ombi.Tests +//{ +// public class TestStartup +// { +// public IServiceProvider ConfigureServices(IServiceCollection services) +// { +// var _plexApi = new Mock(); +// var _embyApi = new Mock(); +// var _tokenSettings = new Mock>(); +// var _embySettings = new Mock>(); +// var _plexSettings = new Mock>(); +// var audit = new Mock(); +// var tokenRepo = new Mock(); - services.AddEntityFrameworkInMemoryDatabase() - .AddDbContext(); - services.AddIdentity() - .AddEntityFrameworkStores().AddUserManager(); +// services.AddEntityFrameworkInMemoryDatabase() +// .AddDbContext(); +// services.AddIdentity() +// .AddEntityFrameworkStores().AddUserManager(); - services.AddTransient(x => _plexApi.Object); - services.AddTransient(x => _embyApi.Object); - services.AddTransient(x => _tokenSettings.Object); - services.AddTransient(x => _embySettings.Object); - services.AddTransient(x => _plexSettings.Object); - services.AddTransient(x => audit.Object); - services.AddTransient(x => tokenRepo.Object); - // Taken from https://github.com/aspnet/MusicStore/blob/dev/test/MusicStore.Test/ManageControllerTest.cs (and modified) - var context = new DefaultHttpContext(); - context.Features.Set(new HttpAuthenticationFeature()); - services.AddSingleton(h => new HttpContextAccessor { HttpContext = context }); +// services.AddTransient(x => _plexApi.Object); +// services.AddTransient(x => _embyApi.Object); +// services.AddTransient(x => _tokenSettings.Object); +// services.AddTransient(x => _embySettings.Object); +// services.AddTransient(x => _plexSettings.Object); +// services.AddTransient(x => audit.Object); +// services.AddTransient(x => tokenRepo.Object); +// // Taken from https://github.com/aspnet/MusicStore/blob/dev/test/MusicStore.Test/ManageControllerTest.cs (and modified) +// var context = new DefaultHttpContext(); +// context.Features.Set(new HttpAuthenticationFeature()); +// services.AddSingleton(h => new HttpContextAccessor { HttpContext = context }); - services.Configure(options => - { - options.Password.RequireDigit = false; - options.Password.RequiredLength = 1; - options.Password.RequireLowercase = false; - options.Password.RequireNonAlphanumeric = false; - options.Password.RequireUppercase = false; - options.User.AllowedUserNameCharacters = string.Empty; - }); +// services.Configure(options => +// { +// options.Password.RequireDigit = false; +// options.Password.RequiredLength = 1; +// options.Password.RequireLowercase = false; +// options.Password.RequireNonAlphanumeric = false; +// options.Password.RequireUppercase = false; +// options.User.AllowedUserNameCharacters = string.Empty; +// }); - return services.BuildServiceProvider(); +// return services.BuildServiceProvider(); - } +// } - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { +// public void Configure(IApplicationBuilder app, IHostingEnvironment env) +// { - } - } -} \ No newline at end of file +// } +// } +//} \ No newline at end of file diff --git a/src/Ombi/Controllers/MusicRequestController.cs b/src/Ombi/Controllers/MusicRequestController.cs index a4605904b..01c0c494d 100644 --- a/src/Ombi/Controllers/MusicRequestController.cs +++ b/src/Ombi/Controllers/MusicRequestController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Authorization; +using System; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Ombi.Core.Engine; using Ombi.Core.Models.Requests; @@ -11,6 +12,7 @@ using Ombi.Core.Models; using Ombi.Core.Models.UI; using Ombi.Store.Entities; using ILogger = Microsoft.Extensions.Logging.ILogger; +using System.Linq; namespace Ombi.Controllers { @@ -171,11 +173,14 @@ namespace Ombi.Controllers } private string GetApiAlias() { - if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias)) + // Make sure this only applies when using the API KEY + if (HttpContext.Request.Headers.Keys.Contains("ApiKey", StringComparer.InvariantCultureIgnoreCase)) { - return apiAlias; + if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias)) + { + return apiAlias; + } } - return null; } } diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index 36073a294..0cad4ab62 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Authorization; +using System; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; @@ -528,9 +529,13 @@ namespace Ombi.Controllers private string GetApiAlias() { - if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias)) + // Make sure this only applies when using the API KEY + if (HttpContext.Request.Headers.Keys.Contains("ApiKey", StringComparer.InvariantCultureIgnoreCase)) { - return apiAlias; + if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias)) + { + return apiAlias; + } } return null; From 1593e3e93a301ec2e13f16da5534a531e35c1f30 Mon Sep 17 00:00:00 2001 From: Andrew Metzger Date: Sun, 20 Jan 2019 10:49:24 -0500 Subject: [PATCH 231/325] Minor grammatical edits Minor changes to grammar and spelling --- .github/ISSUE_TEMPLATE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 2684ccc3e..87a94617f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -2,10 +2,10 @@ !! Please use the Support / bug report template, otherwise we will close the Github issue !! -Version 2.X is not supported anymore. Please don't open a issue for the 2.x version. +Version 2.X is not supported anymore. Please don't open an issue for the 2.x version. See https://github.com/tidusjar/Ombi/issues/1455 for more information. -(Pleas submit a feature request over here: http://feathub.com/tidusjar/Ombi) +(Please submit a feature request over here: http://feathub.com/tidusjar/Ombi) ---> @@ -18,7 +18,7 @@ V 3.0.XX Open Beta -#### Media Sever: +#### Media Server: Plex/Emby @@ -45,4 +45,4 @@ Plex/Emby #### Reproduction Steps: -Please include any steps to reproduce the issue, this the request that is causing the problem etc. +Please include any steps to reproduce the issue, this is the request that is causing the problem etc. From 8bc96d1129edf87617246ed90d88d59bd8a3fc99 Mon Sep 17 00:00:00 2001 From: Andrew Metzger Date: Sun, 20 Jan 2019 11:07:11 -0500 Subject: [PATCH 232/325] More minor grammatical edits Edited the last sentence to improve clarity a bit. --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 87a94617f..d2492d590 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -45,4 +45,4 @@ Plex/Emby #### Reproduction Steps: -Please include any steps to reproduce the issue, this is the request that is causing the problem etc. +Please include any steps to reproduce the issue, the request that is causing the problem, etc. From 02f73fc60a2043515a4f8364a21c2529e045bbaf Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 21 Jan 2019 12:44:28 +0000 Subject: [PATCH 233/325] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..2236cc395 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,37 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Logs (Logs directory where Ombi is located)** +If applicable, a snippet of the logs that seems relevant to the bug if present. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + +**Ombi Version (please complete the following information):** + - Version [e.g. 3.0.1158] +- Media Server [e.g. Plex] + +**Additional context** +Add any other context about the problem here. From 1ac7aa0fd44a392baf3a715666e2e3ab9c8e21b3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 21 Jan 2019 12:44:56 +0000 Subject: [PATCH 234/325] Delete ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 48 --------------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index d2492d590..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,48 +0,0 @@ - - -#### Ombi build Version: - -V 3.0.XX - -#### Update Branch: - -Open Beta - -#### Media Server: - -Plex/Emby - -#### Media Server Version: - - - -#### Operating System: - -(Place text here) - - -#### Ombi Applicable Logs (from `/logs/` directory or the Admin page): - -``` - -(Logs go here. Don't remove the ' tags for showing your logs correctly. Please make sure you remove any personal information from the logs) - -``` - -#### Problem Description: - -(Place text here) - -#### Reproduction Steps: - -Please include any steps to reproduce the issue, the request that is causing the problem, etc. From f1bca13586e4eb8ffe014211aba963a073870e85 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 21 Jan 2019 13:16:35 +0000 Subject: [PATCH 235/325] Added the request queue to the notifications UI so you can turn it off per notification agent #2747 --- .../Agents/DiscordNotification.cs | 138 +++--------------- .../Agents/EmailNotification.cs | 33 +---- .../Agents/MattermostNotification.cs | 133 +++-------------- .../Agents/MobileNotification.cs | 20 +-- .../Agents/PushbulletNotification.cs | 123 ++++------------ .../Agents/PushoverNotification.cs | 122 +++------------- .../Agents/SlackNotification.cs | 128 +++------------- .../Agents/TelegramNotification.cs | 123 +++------------- src/Ombi.Store/Context/OmbiContext.cs | 10 +- 9 files changed, 169 insertions(+), 661 deletions(-) diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs index c0671fc90..77580e5e4 100644 --- a/src/Ombi.Notifications/Agents/DiscordNotification.cs +++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs @@ -56,148 +56,42 @@ namespace Ombi.Notifications.Agents protected override async Task NewRequest(NotificationOptions model, DiscordNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.NewRequest, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Discord}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.NewRequest); } protected override async Task NewIssue(NotificationOptions model, DiscordNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.Issue, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Discord}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.Issue); } protected override async Task IssueComment(NotificationOptions model, DiscordNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.IssueComment, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Discord}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueComment); } protected override async Task IssueResolved(NotificationOptions model, DiscordNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.IssueResolved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Discord}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueResolved); } protected override async Task AddedToRequestQueue(NotificationOptions model, DiscordNotificationSettings settings) { - var user = string.Empty; - var title = string.Empty; - var image = string.Empty; - if (model.RequestType == RequestType.Movie) - { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; - image = MovieRequest.PosterPath; - } - else if (model.RequestType == RequestType.TvShow) - { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - image = TvRequest.ParentRequest.PosterPath; - } - else if (model.RequestType == RequestType.Album) - { - user = AlbumRequest.RequestedUser.UserAlias; - title = AlbumRequest.Title; - image = AlbumRequest.Cover; - } - var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; - var notification = new NotificationMessage - { - Message = message - }; - notification.Other.Add("image", image); - await Send(notification, settings); + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); } protected override async Task RequestDeclined(NotificationOptions model, DiscordNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.RequestDeclined, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Discord}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestDeclined); } protected override async Task RequestApproved(NotificationOptions model, DiscordNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.RequestApproved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Discord}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestApproved); } protected override async Task AvailableRequest(NotificationOptions model, DiscordNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Discord, NotificationType.RequestAvailable, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Discord}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestAvailable); } protected override async Task Send(NotificationMessage model, DiscordNotificationSettings settings) @@ -242,5 +136,21 @@ namespace Ombi.Notifications.Agents }; await Send(notification, settings); } + + private async Task Run(NotificationOptions model, DiscordNotificationSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Discord, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Discord}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } } } diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index 9621fed43..a7f9334fb 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -89,7 +89,6 @@ namespace Ombi.Notifications.Agents } else { - // Send to admin message.To = settings.AdminEmail; } @@ -183,37 +182,21 @@ namespace Ombi.Notifications.Agents protected override async Task AddedToRequestQueue(NotificationOptions model, EmailNotificationSettings settings) { - var email = new EmailBasicTemplate(); - var user = string.Empty; - var title = string.Empty; - var img = string.Empty; - if (model.RequestType == RequestType.Movie) + if (!model.Recipient.HasValue()) { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; - img = $"https://image.tmdb.org/t/p/w300/{MovieRequest.PosterPath}"; + return; } - else + var message = await LoadTemplate(NotificationType.ItemAddedToFaultQueue, model, settings); + if (message == null) { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - img = TvRequest.ParentRequest.PosterPath; + return; } - var html = email.LoadTemplate( - $"{Customization.ApplicationName}: A request could not be added.", - $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying", img, Customization.Logo); - - var message = new NotificationMessage - { - Message = html, - Subject = $"{Customization.ApplicationName}: A request could not be added", - To = settings.AdminEmail, - }; - - var plaintext = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; + var plaintext = await LoadPlainTextMessage(NotificationType.ItemAddedToFaultQueue, model, settings); message.Other.Add("PlainTextBody", plaintext); + // Issues resolved should be sent to the user + message.To = settings.AdminEmail; await Send(message, settings); } diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs index 62c5505c5..f64a0fe21 100644 --- a/src/Ombi.Notifications/Agents/MattermostNotification.cs +++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs @@ -46,20 +46,7 @@ namespace Ombi.Notifications.Agents protected override async Task NewRequest(NotificationOptions model, MattermostNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.NewRequest, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Mattermost}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - AddOtherInformation(model, notification, parsed); - //notification.Other.Add("overview", model.RequestType == RequestType.Movie ? base.MovieRequest.Overview : TvRequest.); - await Send(notification, settings); + await Run(model, settings, NotificationType.NewRequest); } private void AddOtherInformation(NotificationOptions model, NotificationMessage notification, @@ -71,125 +58,37 @@ namespace Ombi.Notifications.Agents protected override async Task NewIssue(NotificationOptions model, MattermostNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.Issue, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Mattermost}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - AddOtherInformation(model, notification, parsed); - await Send(notification, settings); + await Run(model, settings, NotificationType.Issue); } protected override async Task IssueComment(NotificationOptions model, MattermostNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.IssueComment, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Mattermost}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - AddOtherInformation(model, notification, parsed); - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueComment); } protected override async Task IssueResolved(NotificationOptions model, MattermostNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.IssueResolved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Mattermost}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - AddOtherInformation(model, notification, parsed); - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueResolved); } protected override async Task AddedToRequestQueue(NotificationOptions model, MattermostNotificationSettings settings) { - var user = string.Empty; - var title = string.Empty; - var image = string.Empty; - if (model.RequestType == RequestType.Movie) - { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; - image = MovieRequest.PosterPath; - } - else - { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - image = TvRequest.ParentRequest.PosterPath; - } - var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; - var notification = new NotificationMessage - { - Message = message - }; - notification.Other.Add("image", image); - await Send(notification, settings); + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); } protected override async Task RequestDeclined(NotificationOptions model, MattermostNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.RequestDeclined, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Mattermost}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - AddOtherInformation(model, notification, parsed); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestDeclined); } protected override async Task RequestApproved(NotificationOptions model, MattermostNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.RequestApproved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Mattermost}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - AddOtherInformation(model, notification, parsed); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestApproved); } protected override async Task AvailableRequest(NotificationOptions model, MattermostNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.RequestAvailable, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Mattermost}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - AddOtherInformation(model, notification, parsed); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestAvailable); } protected override async Task Send(NotificationMessage model, MattermostNotificationSettings settings) @@ -228,5 +127,21 @@ namespace Ombi.Notifications.Agents }; await Send(notification, settings); } + + private async Task Run(NotificationOptions model, MattermostNotificationSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Mattermost, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Mattermost}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + AddOtherInformation(model, notification, parsed); + await Send(notification, settings); + } } } diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs index de904ecfd..4e3e55fc4 100644 --- a/src/Ombi.Notifications/Agents/MobileNotification.cs +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -130,23 +130,18 @@ namespace Ombi.Notifications.Agents protected override async Task AddedToRequestQueue(NotificationOptions model, MobileNotificationSettings settings) { - string user; - string title; - if (model.RequestType == RequestType.Movie) + + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.ItemAddedToFaultQueue, model); + if (parsed.Disabled) { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; + _logger.LogInformation($"Template {NotificationType.ItemAddedToFaultQueue} is disabled for {NotificationAgent.Mobile}"); + return; } - else - { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - } - var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; var notification = new NotificationMessage { - Message = message + Message = parsed.Message, }; + // Get admin devices var playerIds = await GetAdmins(NotificationType.Test); await Send(playerIds, notification, settings, model); @@ -294,6 +289,5 @@ namespace Ombi.Notifications.Agents } } } - } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/PushbulletNotification.cs b/src/Ombi.Notifications/Agents/PushbulletNotification.cs index 8440ad319..91a8120b2 100644 --- a/src/Ombi.Notifications/Agents/PushbulletNotification.cs +++ b/src/Ombi.Notifications/Agents/PushbulletNotification.cs @@ -44,131 +44,43 @@ namespace Ombi.Notifications.Agents protected override async Task NewRequest(NotificationOptions model, PushbulletSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushbullet, NotificationType.NewRequest, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Pushbullet}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - await Send(notification, settings); + await Run(model, settings, NotificationType.NewRequest); } + protected override async Task NewIssue(NotificationOptions model, PushbulletSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushbullet, NotificationType.Issue, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Pushbullet}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.Issue); } protected override async Task IssueComment(NotificationOptions model, PushbulletSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushbullet, NotificationType.IssueComment, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Pushbullet}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueComment); } protected override async Task IssueResolved(NotificationOptions model, PushbulletSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushbullet, NotificationType.IssueResolved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Pushbullet}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueResolved); } protected override async Task AddedToRequestQueue(NotificationOptions model, PushbulletSettings settings) { - string user; - string title; - if (model.RequestType == RequestType.Movie) - { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; - } - else - { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - } - var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; - var notification = new NotificationMessage - { - Message = message - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); } protected override async Task RequestDeclined(NotificationOptions model, PushbulletSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushbullet, NotificationType.RequestDeclined, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Pushbullet}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestDeclined); } protected override async Task RequestApproved(NotificationOptions model, PushbulletSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushbullet, NotificationType.RequestApproved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Pushbullet}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestApproved); } protected override async Task AvailableRequest(NotificationOptions model, PushbulletSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushbullet, NotificationType.RequestAvailable, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Pushbullet}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestAvailable); } protected override async Task Send(NotificationMessage model, PushbulletSettings settings) @@ -192,5 +104,22 @@ namespace Ombi.Notifications.Agents }; await Send(notification, settings); } + + private async Task Run(NotificationOptions model, PushbulletSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Pushbullet, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Pushbullet}"); + return; + } + + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + await Send(notification, settings); + } } } diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index 0d1675f82..d41e6d911 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -45,132 +45,42 @@ namespace Ombi.Notifications.Agents protected override async Task NewRequest(NotificationOptions model, PushoverSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.NewRequest, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Pushover}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - await Send(notification, settings); + await Run(model, settings, NotificationType.NewRequest); } protected override async Task NewIssue(NotificationOptions model, PushoverSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.Issue, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Pushover}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.Issue); } protected override async Task IssueComment(NotificationOptions model, PushoverSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.IssueComment, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Pushover}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueComment); } protected override async Task IssueResolved(NotificationOptions model, PushoverSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.IssueResolved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Pushover}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueResolved); } protected override async Task AddedToRequestQueue(NotificationOptions model, PushoverSettings settings) { - string user; - string title; - if (model.RequestType == RequestType.Movie) - { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; - } - else - { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - } - var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; - var notification = new NotificationMessage - { - Message = message - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); } protected override async Task RequestDeclined(NotificationOptions model, PushoverSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.RequestDeclined, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Pushover}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestDeclined); } protected override async Task RequestApproved(NotificationOptions model, PushoverSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.RequestApproved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Pushover}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestApproved); } protected override async Task AvailableRequest(NotificationOptions model, PushoverSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.RequestAvailable, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Pushover}"); - return; - } - - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestAvailable); } protected override async Task Send(NotificationMessage model, PushoverSettings settings) @@ -195,5 +105,21 @@ namespace Ombi.Notifications.Agents }; await Send(notification, settings); } + + private async Task Run(NotificationOptions model, PushoverSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Pushover, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Pushover}"); + return; + } + + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + await Send(notification, settings); + } } } diff --git a/src/Ombi.Notifications/Agents/SlackNotification.cs b/src/Ombi.Notifications/Agents/SlackNotification.cs index fdbd7ba64..58b2da651 100644 --- a/src/Ombi.Notifications/Agents/SlackNotification.cs +++ b/src/Ombi.Notifications/Agents/SlackNotification.cs @@ -54,138 +54,42 @@ namespace Ombi.Notifications.Agents protected override async Task NewRequest(NotificationOptions model, SlackNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Slack, NotificationType.NewRequest, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Slack}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.NewRequest); } protected override async Task NewIssue(NotificationOptions model, SlackNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Slack, NotificationType.Issue, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Slack}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.Issue); } protected override async Task IssueComment(NotificationOptions model, SlackNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Slack, NotificationType.IssueComment, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Slack}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueComment); } protected override async Task IssueResolved(NotificationOptions model, SlackNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Slack, NotificationType.IssueResolved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Slack}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueResolved); } protected override async Task AddedToRequestQueue(NotificationOptions model, SlackNotificationSettings settings) { - var user = string.Empty; - var title = string.Empty; - if (model.RequestType == RequestType.Movie) - { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; - } - else - { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - } - var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; - var notification = new NotificationMessage - { - Message = message - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); } protected override async Task RequestDeclined(NotificationOptions model, SlackNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Slack, NotificationType.RequestDeclined, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Slack}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestAvailable); } protected override async Task RequestApproved(NotificationOptions model, SlackNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Slack, NotificationType.RequestApproved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Slack}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestApproved); } protected override async Task AvailableRequest(NotificationOptions model, SlackNotificationSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Slack, NotificationType.RequestAvailable, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Slack}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - notification.Other.Add("image", parsed.Image); - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestAvailable); } protected override async Task Send(NotificationMessage model, SlackNotificationSettings settings) @@ -218,5 +122,21 @@ namespace Ombi.Notifications.Agents }; await Send(notification, settings); } + + private async Task Run(NotificationOptions model, SlackNotificationSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Slack, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Slack}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + notification.Other.Add("image", parsed.Image); + await Send(notification, settings); + } } } diff --git a/src/Ombi.Notifications/Agents/TelegramNotification.cs b/src/Ombi.Notifications/Agents/TelegramNotification.cs index 8e4c4e898..3acfc7331 100644 --- a/src/Ombi.Notifications/Agents/TelegramNotification.cs +++ b/src/Ombi.Notifications/Agents/TelegramNotification.cs @@ -41,134 +41,42 @@ namespace Ombi.Notifications.Agents protected override async Task NewRequest(NotificationOptions model, TelegramSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Telegram, NotificationType.NewRequest, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Telegram}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - - await Send(notification, settings); + await Run(model, settings, NotificationType.NewRequest); } protected override async Task NewIssue(NotificationOptions model, TelegramSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Telegram, NotificationType.Issue, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Telegram}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.Issue); } protected override async Task IssueComment(NotificationOptions model, TelegramSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Telegram, NotificationType.IssueComment, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Telegram}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueComment); } protected override async Task IssueResolved(NotificationOptions model, TelegramSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Telegram, NotificationType.IssueResolved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Telegram}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.IssueResolved); } protected override async Task AddedToRequestQueue(NotificationOptions model, TelegramSettings settings) { - var user = string.Empty; - var title = string.Empty; - var image = string.Empty; - if (model.RequestType == RequestType.Movie) - { - user = MovieRequest.RequestedUser.UserAlias; - title = MovieRequest.Title; - image = MovieRequest.PosterPath; - } - else - { - user = TvRequest.RequestedUser.UserAlias; - title = TvRequest.ParentRequest.Title; - image = TvRequest.ParentRequest.PosterPath; - } - var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; - var notification = new NotificationMessage - { - Message = message - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); } protected override async Task RequestDeclined(NotificationOptions model, TelegramSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Telegram, NotificationType.RequestDeclined, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Telegram}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestDeclined); } protected override async Task RequestApproved(NotificationOptions model, TelegramSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Telegram, NotificationType.RequestApproved, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Telegram}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message ?? string.Empty, - }; - - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestApproved); } protected override async Task AvailableRequest(NotificationOptions model, TelegramSettings settings) { - var parsed = await LoadTemplate(NotificationAgent.Telegram, NotificationType.RequestAvailable, model); - if (parsed.Disabled) - { - Logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Telegram}"); - return; - } - var notification = new NotificationMessage - { - Message = parsed.Message, - }; - await Send(notification, settings); + await Run(model, settings, NotificationType.RequestAvailable); } protected override async Task Send(NotificationMessage model, TelegramSettings settings) @@ -192,5 +100,20 @@ namespace Ombi.Notifications.Agents }; await Send(notification, settings); } + + private async Task Run(NotificationOptions model, TelegramSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Telegram, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Telegram}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + await Send(notification, settings); + } } } diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 3d8c05daa..bb84f1272 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -209,7 +209,15 @@ namespace Ombi.Store.Context }; break; case NotificationType.ItemAddedToFaultQueue: - continue; + notificationToAdd = new NotificationTemplates + { + NotificationType = notificationType, + Message = "Hello! The user '{UserName}' has requested {Title} but it could not be added. This has been added into the requests queue and will keep retrying", + Subject = "Item Added To Retry Queue", + Agent = agent, + Enabled = true, + }; + break; case NotificationType.WelcomeEmail: notificationToAdd = new NotificationTemplates { From 1f59693c7e04277dc738c1836f4ba5a67659e2ae Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 21 Jan 2019 13:53:46 +0000 Subject: [PATCH 236/325] Added the ability to change where the View on Emby link goes to #2730 --- src/Ombi.Helpers/EmbyHelper.cs | 13 +++++++++---- src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs | 10 +++++----- .../Settings/Models/External/EmbySettings.cs | 1 + src/Ombi/ClientApp/app/interfaces/ISettings.ts | 1 + .../ClientApp/app/settings/emby/emby.component.html | 12 ++++++++++++ .../ClientApp/app/wizard/emby/emby.component.ts | 1 + 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Helpers/EmbyHelper.cs b/src/Ombi.Helpers/EmbyHelper.cs index 567bcfe7e..a9967f21f 100644 --- a/src/Ombi.Helpers/EmbyHelper.cs +++ b/src/Ombi.Helpers/EmbyHelper.cs @@ -7,11 +7,16 @@ namespace Ombi.Helpers { public class EmbyHelper { - public static string GetEmbyMediaUrl(string mediaId) + public static string GetEmbyMediaUrl(string mediaId, string customerServerUrl = null) { - var url = - $"http://app.emby.media/#!/itemdetails.html?id={mediaId}"; - return url; + if (customerServerUrl.HasValue()) + { + return $"{customerServerUrl}#!/itemdetails.html?id={mediaId}"; + } + else + { + return $"https://app.emby.media/#!/itemdetails.html?id={mediaId}"; + } } } } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 7002eec41..4972f940f 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -87,7 +87,7 @@ namespace Ombi.Schedule.Jobs.Emby await _api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri); foreach (var item in movieInfo.Items) { - await ProcessMovies(item, mediaToAdd); + await ProcessMovies(item, mediaToAdd, server); } processed++; @@ -96,7 +96,7 @@ namespace Ombi.Schedule.Jobs.Emby { processed++; // Regular movie - await ProcessMovies(movie, mediaToAdd); + await ProcessMovies(movie, mediaToAdd, server); } } @@ -138,7 +138,7 @@ namespace Ombi.Schedule.Jobs.Emby Title = tvShow.Name, Type = EmbyMediaType.Series, EmbyId = tvShow.Id, - Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id), + Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id, server.ServerHostname), AddedAt = DateTime.UtcNow }); } @@ -164,7 +164,7 @@ namespace Ombi.Schedule.Jobs.Emby await _repo.AddRange(mediaToAdd); } - private async Task ProcessMovies(EmbyMovie movieInfo, ICollection content) + private async Task ProcessMovies(EmbyMovie movieInfo, ICollection content, EmbyServers server) { // Check if it exists var existingMovie = await _repo.GetByEmbyId(movieInfo.Id); @@ -179,7 +179,7 @@ namespace Ombi.Schedule.Jobs.Emby Title = movieInfo.Name, Type = EmbyMediaType.Movie, EmbyId = movieInfo.Id, - Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id), + Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server.ServerHostname), AddedAt = DateTime.UtcNow, }); } diff --git a/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs b/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs index 96df77281..595733dc1 100644 --- a/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs @@ -14,6 +14,7 @@ namespace Ombi.Core.Settings.Models.External public string Name { get; set; } public string ApiKey { get; set; } public string AdministratorId { get; set; } + public string ServerHostname { get; set; } public bool EnableEpisodeSearching { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 1f62a2c8d..070dabb8d 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -41,6 +41,7 @@ export interface IEmbyServer extends IExternalSettings { apiKey: string; administratorId: string; enableEpisodeSearching: boolean; + serverHostname: string; } export interface IPlexSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/settings/emby/emby.component.html b/src/Ombi/ClientApp/app/settings/emby/emby.component.html index ec966acf5..62188aaf6 100644 --- a/src/Ombi/ClientApp/app/settings/emby/emby.component.html +++ b/src/Ombi/ClientApp/app/settings/emby/emby.component.html @@ -63,6 +63,18 @@ + +
+ +
+ + Current URL: "{{server.serverHostname}}/#!/itemdetails.html?id=1" + Current URL: "https://app.emby.media/#!/itemdetails.html?id=1 +
+
diff --git a/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts b/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts index d7114e489..f22fa915b 100644 --- a/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts +++ b/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts @@ -41,6 +41,7 @@ export class EmbyComponent implements OnInit { port: 8096, ssl: false, subDir: "", + serverHostname: "", }); } From 3e4b2a8e9f8ccbff79cc06174094e25b9e057415 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 21 Jan 2019 14:06:30 +0000 Subject: [PATCH 237/325] Small fix when denying a request with a reason, we wasn't updating the ui --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 1 + .../ClientApp/app/requests/movierequests.component.html | 3 --- src/Ombi/ClientApp/app/requests/movierequests.component.ts | 7 ++++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 8f4693be1..456ba267a 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -326,6 +326,7 @@ namespace Ombi.Core.Engine return new RequestEngineResult { + Result = true, Message = "Request successfully deleted", }; } diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 8d2158236..6f3b4dd00 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -87,9 +87,6 @@ - - - diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 3c7a4f993..daff9a455 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -135,15 +135,20 @@ export class MovieRequestsComponent implements OnInit { public deny(request: IMovieRequests) { this.requestToDeny = request; this.denyDisplay = true; - } + } public denyRequest() { this.requestService.denyMovie({ id: this.requestToDeny.id, reason: this.rejectionReason }) .subscribe(x => { + debugger; this.denyDisplay = false; if (x.result) { this.notificationService.success( `Request for ${this.requestToDeny.title} has been denied successfully`); + const index = this.movieRequests.indexOf(this.requestToDeny, 0); + if (index > -1) { + this.movieRequests[index].denied = true; + } } else { this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); this.requestToDeny.denied = false; From ff73e78e2c8ac24443a196fcf94f3af6805fb339 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 21 Jan 2019 14:54:29 +0000 Subject: [PATCH 238/325] !wip added a search by actor methodin the Movie Search Engine --- .../Engine/Interfaces/IMovieEngine.cs | 1 + src/Ombi.Core/Engine/MovieSearchEngine.cs | 29 ++++++++++- src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 2 + src/Ombi.TheMovieDbApi/Models/ActorCredits.cs | 51 +++++++++++++++++++ .../Models/ActorSearchResult.cs | 33 ++++++++++++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 22 ++++++++ 6 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 src/Ombi.TheMovieDbApi/Models/ActorCredits.cs create mode 100644 src/Ombi.TheMovieDbApi/Models/ActorSearchResult.cs diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs index b80d132d1..9b4cd9831 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs @@ -19,5 +19,6 @@ namespace Ombi.Core Task LookupImdbInformation(int theMovieDbId, string langCode = null); Task> SimilarMovies(int theMovieDbId, string langCode); + Task> SearchActor(string search, string langaugeCode); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index 5e56e8abd..a82feb28a 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -54,8 +54,6 @@ namespace Ombi.Core.Engine /// /// Searches the specified movie. /// - /// The search. - /// public async Task> Search(string search, int? year, string langaugeCode) { langaugeCode = await DefaultLanguageCode(langaugeCode); @@ -68,6 +66,33 @@ namespace Ombi.Core.Engine return null; } + public async Task> SearchActor(string search, string langaugeCode) + { + langaugeCode = await DefaultLanguageCode(langaugeCode); + var people = await MovieApi.SearchByActor(search, langaugeCode); + var person = people?.results?.Count > 0 ? people.results.FirstOrDefault() : null; + + var resultSet = new List(); + if (person == null) + { + return resultSet; + } + + // Get this person movie credits + var credits = await MovieApi.GetActorMovieCredits(person.id, langaugeCode); + // Grab results from both cast and crew, prefer items in cast. we can handle directors like this. + var movieResults = (from role in credits.cast select new { Id = role.id, Title = role.title, ReleaseDate = role.release_date }).ToList(); + movieResults.AddRange((from job in credits.crew select new { Id = job.id, Title = job.title, ReleaseDate = job.release_date }).ToList()); + + movieResults = movieResults.Take(10).ToList(); + foreach (var movieResult in movieResults) + { + resultSet.Add(await LookupImdbInformation(movieResult.Id, langaugeCode)); + } + + return resultSet; + } + /// /// Get similar movies to the id passed in /// diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 5fa5b73bd..43d8b02c1 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -19,5 +19,7 @@ namespace Ombi.Api.TheMovieDb Task Find(string externalId, ExternalSource source); Task GetTvExternals(int theMovieDbId); Task GetTVInfo(string themoviedbid); + Task> SearchByActor(string searchTerm, string langCode); + Task GetActorMovieCredits(int actorId, string langCode); } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/Models/ActorCredits.cs b/src/Ombi.TheMovieDbApi/Models/ActorCredits.cs new file mode 100644 index 000000000..cb27bc677 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/ActorCredits.cs @@ -0,0 +1,51 @@ +namespace Ombi.Api.TheMovieDb.Models +{ + public class ActorCredits + { + public Cast[] cast { get; set; } + public Crew[] crew { get; set; } + public int id { get; set; } + } + + public class Cast + { + public string character { get; set; } + public string credit_id { get; set; } + public string poster_path { get; set; } + public int id { get; set; } + public bool video { get; set; } + public int vote_count { get; set; } + public bool adult { get; set; } + public string backdrop_path { get; set; } + public int?[] genre_ids { get; set; } + public string original_language { get; set; } + public string original_title { get; set; } + public float popularity { get; set; } + public string title { get; set; } + public float vote_average { get; set; } + public string overview { get; set; } + public string release_date { get; set; } + } + + public class Crew + { + public int id { get; set; } + public string department { get; set; } + public string original_language { get; set; } + public string original_title { get; set; } + public string job { get; set; } + public string overview { get; set; } + public int vote_count { get; set; } + public bool video { get; set; } + public string release_date { get; set; } + public float vote_average { get; set; } + public string title { get; set; } + public float popularity { get; set; } + public int?[] genre_ids { get; set; } + public string backdrop_path { get; set; } + public bool adult { get; set; } + public string poster_path { get; set; } + public string credit_id { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/Models/ActorSearchResult.cs b/src/Ombi.TheMovieDbApi/Models/ActorSearchResult.cs new file mode 100644 index 000000000..b16b35ab9 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/ActorSearchResult.cs @@ -0,0 +1,33 @@ +namespace Ombi.Api.TheMovieDb.Models +{ + + public class ActorResult + { + public float popularity { get; set; } + public int id { get; set; } + public string profile_path { get; set; } + public string name { get; set; } + public Known_For[] known_for { get; set; } + public bool adult { get; set; } + } + + public class Known_For + { + public float vote_average { get; set; } + public int vote_count { get; set; } + public int id { get; set; } + public bool video { get; set; } + public string media_type { get; set; } + public string title { get; set; } + public float popularity { get; set; } + public string poster_path { get; set; } + public string original_language { get; set; } + public string original_title { get; set; } + public int[] genre_ids { get; set; } + public string backdrop_path { get; set; } + public bool adult { get; set; } + public string overview { get; set; } + public string release_date { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 0500171c9..34875a50f 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -43,6 +43,28 @@ namespace Ombi.Api.TheMovieDb return await Api.Request(request); } + public async Task> SearchByActor(string searchTerm, string langCode) + { + var request = new Request($"search/person", BaseUri, HttpMethod.Get); + request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); + request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + + var result = await Api.Request>(request); + return result; + } + + public async Task GetActorMovieCredits(int actorId, string langCode) + { + var request = new Request($"search/person", BaseUri, HttpMethod.Get); + request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.FullUri = request.FullUri.AddQueryParameter("person_id", actorId.ToString()); + request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + + var result = await Api.Request(request); + return result; + } + public async Task> SearchTv(string searchTerm) { var request = new Request($"search/tv", BaseUri, HttpMethod.Get); From 01ff2acb9aa264c0ed8b6c65954b6e5aad63cf07 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 22 Jan 2019 21:12:00 +0000 Subject: [PATCH 239/325] Log the error to the ui to figure out what's going on with #2755 --- src/Ombi/ClientApp/app/login/login.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 4a9ad4aaf..34edcd687 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -161,7 +161,8 @@ export class LoginComponent implements OnDestroy, OnInit { } }, err => { - this.notify.error(err.statusText); + console.log(err); + this.notify.error(err.body); this.router.navigate(["login"]); }); From 619ea4dbc4ee6893f9e1ead919952c187caf07e6 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 22 Jan 2019 21:33:23 +0000 Subject: [PATCH 240/325] fixed build !wip --- src/Ombi/ClientApp/app/requests/movierequests.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index daff9a455..3459ac0c7 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -140,7 +140,6 @@ export class MovieRequestsComponent implements OnInit { public denyRequest() { this.requestService.denyMovie({ id: this.requestToDeny.id, reason: this.rejectionReason }) .subscribe(x => { - debugger; this.denyDisplay = false; if (x.result) { this.notificationService.success( From a6b733e9546c4bac32ba4737b58c48845ba2f3d1 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 23 Jan 2019 10:18:23 +0000 Subject: [PATCH 241/325] Fixed the exception that sometimes makes ombi fallover. --- src/Ombi/Program.cs | 272 +++++++++++++++++++++----------------------- src/Ombi/Startup.cs | 7 +- 2 files changed, 133 insertions(+), 146 deletions(-) diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index d9631410e..62e8e4dfe 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -47,49 +47,47 @@ namespace Ombi instance.StoragePath = storagePath ?? string.Empty; // Check if we need to migrate the settings CheckAndMigrate(); - using (var ctx = new SettingsContext()) + var ctx = new SettingsContext(); + var config = ctx.ApplicationConfigurations.ToList(); + var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); + var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); + if (url == null) { - var config = ctx.ApplicationConfigurations.ToList(); - var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); - var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); - if (url == null) + url = new ApplicationConfiguration { - url = new ApplicationConfiguration + Type = ConfigurationTypes.Url, + Value = "http://*:5000" + }; + + ctx.ApplicationConfigurations.Add(url); + ctx.SaveChanges(); + urlValue = url.Value; + } + if (!url.Value.Equals(host)) + { + url.Value = UrlArgs; + ctx.SaveChanges(); + urlValue = url.Value; + } + + if (dbBaseUrl == null) + { + if (baseUrl.HasValue() && baseUrl.StartsWith("/")) + { + dbBaseUrl = new ApplicationConfiguration { - Type = ConfigurationTypes.Url, - Value = "http://*:5000" + Type = ConfigurationTypes.BaseUrl, + Value = baseUrl }; - - ctx.ApplicationConfigurations.Add(url); - ctx.SaveChanges(); - urlValue = url.Value; - } - if (!url.Value.Equals(host)) - { - url.Value = UrlArgs; - ctx.SaveChanges(); - urlValue = url.Value; - } - - if (dbBaseUrl == null) - { - if (baseUrl.HasValue() && baseUrl.StartsWith("/")) - { - dbBaseUrl = new ApplicationConfiguration - { - Type = ConfigurationTypes.BaseUrl, - Value = baseUrl - }; - ctx.ApplicationConfigurations.Add(dbBaseUrl); - ctx.SaveChanges(); - } - } - else if (baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) - { - dbBaseUrl.Value = baseUrl; + ctx.ApplicationConfigurations.Add(dbBaseUrl); ctx.SaveChanges(); } } + else if (baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) + { + dbBaseUrl.Value = baseUrl; + ctx.SaveChanges(); + } DeleteSchedulesDb(); @@ -111,124 +109,118 @@ namespace Ombi { var doneGlobal = false; var doneConfig = false; - using (var ombi = new OmbiContext()) - using (var settings = new SettingsContext()) + var ombi = new OmbiContext(); + var settings = new SettingsContext(); + + try { - try + if (ombi.Settings.Any()) { - 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; + // OK migrate it! + var allSettings = ombi.Settings.ToList(); + settings.Settings.AddRange(allSettings); + doneGlobal = true; } - // Now delete the old stuff - if (doneGlobal) - ombi.Database.ExecuteSqlCommand("DELETE FROM GlobalSettings"); - if (doneConfig) - ombi.Database.ExecuteSqlCommand("DELETE FROM ApplicationConfiguration"); + // 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()) + var external = new ExternalContext(); + + try { - try + if (ombi.PlexEpisode.Any()) { - - 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(); + external.PlexEpisode.AddRange(ombi.PlexEpisode.ToList()); + ombi.Database.ExecuteSqlCommand("DELETE FROM PlexEpisode"); } - catch (Exception e) + + if (ombi.PlexSeasonsContent.Any()) { - Console.WriteLine(e); - throw; + 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() diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 9358a4ebb..282034ea5 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -209,7 +209,7 @@ namespace Ombi app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire", new DashboardOptions { - Authorization = new[] {new HangfireAuthorizationFilter()} + Authorization = new[] { new HangfireAuthorizationFilter() } }); } @@ -237,15 +237,12 @@ namespace Ombi app.UseMiddleware(); app.UseCors("MyPolicy"); - //app.ApiKeyMiddlewear(app.ApplicationServices); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); - - app.UseMvc(routes => { routes.MapRoute( @@ -256,8 +253,6 @@ namespace Ombi name: "spa-fallback", defaults: new { controller = "Home", action = "Index" }); }); - - ombiService.Dispose(); } } From 76bfec1667d020f827c2339a4e30657e90503ffe Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 23 Jan 2019 10:18:35 +0000 Subject: [PATCH 242/325] Added Actor Searching for Movies! --- src/Ombi.Api/Api.cs | 13 +++-- src/Ombi.Core/Engine/MovieSearchEngine.cs | 7 +-- src/Ombi.Store/Context/SettingsContext.cs | 5 ++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 3 +- .../requests/remainingrequests.component.ts | 9 +--- .../app/search/moviesearch.component.html | 50 +++++++++++-------- .../app/search/moviesearch.component.ts | 36 ++++++++----- .../ClientApp/app/services/search.service.ts | 4 ++ src/Ombi/Controllers/SearchController.cs | 19 +++++++ 9 files changed, 96 insertions(+), 50 deletions(-) diff --git a/src/Ombi.Api/Api.cs b/src/Ombi.Api/Api.cs index 19dab7530..e405b6bca 100644 --- a/src/Ombi.Api/Api.cs +++ b/src/Ombi.Api/Api.cs @@ -41,7 +41,7 @@ namespace Ombi.Api { if (!request.IgnoreErrors) { - LogError(request, httpResponseMessage); + await LogError(request, httpResponseMessage); } if (request.Retry) @@ -105,7 +105,7 @@ namespace Ombi.Api { if (!request.IgnoreErrors) { - LogError(request, httpResponseMessage); + await LogError(request, httpResponseMessage); } } // do something with the response @@ -126,7 +126,7 @@ namespace Ombi.Api { if (!request.IgnoreErrors) { - LogError(request, httpResponseMessage); + await LogError(request, httpResponseMessage); } } } @@ -149,10 +149,15 @@ namespace Ombi.Api } } - private void LogError(Request request, HttpResponseMessage httpResponseMessage) + private async Task LogError(Request request, HttpResponseMessage httpResponseMessage) { Logger.LogError(LoggingEvents.Api, $"StatusCode: {httpResponseMessage.StatusCode}, Reason: {httpResponseMessage.ReasonPhrase}, RequestUri: {request.FullUri}"); + if (Logger.IsEnabled(LogLevel.Debug)) + { + var content = await httpResponseMessage.Content.ReadAsStringAsync(); + Logger.LogDebug(content); + } } } } diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index a82feb28a..dda58348f 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -197,15 +197,16 @@ namespace Ombi.Core.Engine private async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, bool lookupExtraInfo = false) { - if (lookupExtraInfo) + if (lookupExtraInfo && viewMovie.ImdbId.IsNullOrEmpty()) { var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id); viewMovie.Id = showInfo.Id; // TheMovieDbId viewMovie.ImdbId = showInfo.ImdbId; - var usDates = viewMovie.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US"); - viewMovie.DigitalReleaseDate = usDates?.ReleaseDate?.FirstOrDefault(x => x.Type == ReleaseDateType.Digital)?.ReleaseDate; } + var usDates = viewMovie.ReleaseDates?.Results?.FirstOrDefault(x => x.IsoCode == "US"); + viewMovie.DigitalReleaseDate = usDates?.ReleaseDate?.FirstOrDefault(x => x.Type == ReleaseDateType.Digital)?.ReleaseDate; + viewMovie.TheMovieDbId = viewMovie.Id.ToString(); await RunSearchRules(viewMovie); diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs index af5c91d20..6a53e598f 100644 --- a/src/Ombi.Store/Context/SettingsContext.cs +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -66,5 +66,10 @@ namespace Ombi.Store.Context SaveChanges(); } + + ~SettingsContext() + { + + } } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 34875a50f..79ccc5bb7 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -56,9 +56,8 @@ namespace Ombi.Api.TheMovieDb public async Task GetActorMovieCredits(int actorId, string langCode) { - var request = new Request($"search/person", BaseUri, HttpMethod.Get); + var request = new Request($"person/{actorId}/movie_credits", BaseUri, HttpMethod.Get); request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("person_id", actorId.ToString()); request.FullUri = request.FullUri.AddQueryParameter("language", langCode); var result = await Api.Request(request); diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index bf43b7330..b7d23a3df 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -23,17 +23,11 @@ export class RemainingRequestsComponent implements OnInit { } public ngOnInit() { - const self = this; - this.update(); - this.quotaRefreshEvents.subscribe(() => { + this.quotaRefreshEvents.subscribe(() => { this.update(); }); - - setInterval(() => { - self.update(); - }, 60000); } public update(): void { @@ -43,7 +37,6 @@ export class RemainingRequestsComponent implements OnInit { this.calculateTime(); } }); - if (this.movie) { this.requestService.getRemainingMovieRequests().subscribe(callback); } diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index bc30a1fff..7d8a4653a 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -27,28 +27,35 @@
-
-
- - - -
-
+
+
+ - -
-
- -
- -
-
- +
-
+
+ + +
+
+ +
+ +
+
+
+ +
+
+
+ + +
+
+
+
@@ -70,7 +77,8 @@
- poster + poster
diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 8c82b58fd..90502bb93 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -27,6 +27,7 @@ export class MovieSearchComponent implements OnInit { public searchApplied = false; public refineSearchEnabled = false; public searchYear?: number; + public actorSearch: boolean; public selectedLanguage: string; public langauges: ILanguageRefine[]; @@ -204,7 +205,7 @@ export class MovieSearchComponent implements OnInit { } val.background = this.sanitizer.bypassSecurityTrustStyle ("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")"); - + if (this.applyRefinedSearch) { this.searchService.getMovieInformationWithRefined(val.id, this.selectedLanguage) .subscribe(m => { @@ -212,9 +213,9 @@ export class MovieSearchComponent implements OnInit { }); } else { this.searchService.getMovieInformation(val.id) - .subscribe(m => { - this.updateItem(val, m); - }); + .subscribe(m => { + this.updateItem(val, m); + }); } }); } @@ -239,14 +240,25 @@ export class MovieSearchComponent implements OnInit { return; } if (this.refineOpen) { - this.searchService.searchMovieWithRefined(this.searchText, this.searchYear, this.selectedLanguage) - .subscribe(x => { - this.movieResults = x; - this.searchApplied = true; - // Now let's load some extra info including IMDB Id - // This way the search is fast at displaying results. - this.getExtraInfo(); - }); + if (!this.actorSearch) { + this.searchService.searchMovieWithRefined(this.searchText, this.searchYear, this.selectedLanguage) + .subscribe(x => { + this.movieResults = x; + this.searchApplied = true; + // Now let's load some extra info including IMDB Id + // This way the search is fast at displaying results. + this.getExtraInfo(); + }); + } else { + this.searchService.searchMovieByActor(this.searchText, this.selectedLanguage) + .subscribe(x => { + this.movieResults = x; + this.searchApplied = true; + // Now let's load some extra info including IMDB Id + // This way the search is fast at displaying results. + this.getExtraInfo(); + }); + } } else { this.searchService.searchMovie(this.searchText) .subscribe(x => { diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index a0abd6d24..5379e23e7 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -49,6 +49,10 @@ export class SearchService extends ServiceHelpers { return this.http.post(`${this.url}/Movie/info`, { theMovieDbId, languageCode: langCode }); } + public searchMovieByActor(searchTerm: string, langCode: string): Observable { + return this.http.post(`${this.url}/Movie/Actor`, { searchTerm, languageCode: langCode }); + } + // TV public searchTv(searchTerm: string): Observable { return this.http.get(`${this.url}/Tv/${searchTerm}`, { headers: this.headers }); diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 872a3305e..08f889f08 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -51,6 +51,25 @@ namespace Ombi.Controllers } } + /// + /// Searches for movies by a certain actor. + /// + /// The refinement model, language code and year are both optional. Language code uses ISO 639-1 + /// + [HttpPost("movie/actor")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesDefaultResponseType] + public async Task SearchActor([FromBody] SearchMovieRefineModel model) + { + if (model == null) + { + return BadRequest(); + } + + return Json(await MovieEngine.SearchActor(model.SearchTerm, model.LanguageCode)); + } + /// /// Searches for a movie. /// From 183c242334a42f27c49830c9a0217b612aa20dd3 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 23 Jan 2019 13:49:26 +0000 Subject: [PATCH 243/325] !wip improved the api for the actor search --- src/Ombi/Controllers/SearchController.cs | 4 ++-- src/Ombi/Models/SearchActorModel.cs | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 src/Ombi/Models/SearchActorModel.cs diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 08f889f08..535581447 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -54,13 +54,13 @@ namespace Ombi.Controllers /// /// Searches for movies by a certain actor. /// - /// The refinement model, language code and year are both optional. Language code uses ISO 639-1 + /// language code is optional, by default it will be en. Language code uses ISO 639-1 /// [HttpPost("movie/actor")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesDefaultResponseType] - public async Task SearchActor([FromBody] SearchMovieRefineModel model) + public async Task SearchActor([FromBody] SearchActorModel model) { if (model == null) { diff --git a/src/Ombi/Models/SearchActorModel.cs b/src/Ombi/Models/SearchActorModel.cs new file mode 100644 index 000000000..ad49282e9 --- /dev/null +++ b/src/Ombi/Models/SearchActorModel.cs @@ -0,0 +1,8 @@ +namespace Ombi.Models +{ + public class SearchActorModel + { + public string SearchTerm { get; set; } + public string LanguageCode { get; set; } = "en"; + } +} From c2c8a772dd0c9aeb004091eb874132890da9fa27 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 23 Jan 2019 16:30:15 +0000 Subject: [PATCH 244/325] Did #2756 --- src/Ombi.Helpers/OmbiRoles.cs | 1 + src/Ombi/ClientApp/app/app.module.ts | 3 +- .../app/custompage/custompage.component.ts | 6 +-- .../app/services/custompage.service.ts | 25 +++++++++ src/Ombi/ClientApp/app/services/index.ts | 1 + .../customization.component.html | 2 +- src/Ombi/Controllers/CustomPageController.cs | 53 +++++++++++++++++++ src/Ombi/Controllers/IdentityController.cs | 1 + src/Ombi/Controllers/SettingsController.cs | 21 -------- src/Ombi/Startup.cs | 35 +++--------- 10 files changed, 93 insertions(+), 55 deletions(-) create mode 100644 src/Ombi/ClientApp/app/services/custompage.service.ts create mode 100644 src/Ombi/Controllers/CustomPageController.cs diff --git a/src/Ombi.Helpers/OmbiRoles.cs b/src/Ombi.Helpers/OmbiRoles.cs index e0cfc5398..02a480fdf 100644 --- a/src/Ombi.Helpers/OmbiRoles.cs +++ b/src/Ombi.Helpers/OmbiRoles.cs @@ -15,5 +15,6 @@ public const string Disabled = nameof(Disabled); public const string ReceivesNewsletter = nameof(ReceivesNewsletter); public const string ManageOwnRequests = nameof(ManageOwnRequests); + public const string EditCustomPage = nameof(EditCustomPage); } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/app.module.ts b/src/Ombi/ClientApp/app/app.module.ts index 6917cc85b..a68405f75 100644 --- a/src/Ombi/ClientApp/app/app.module.ts +++ b/src/Ombi/ClientApp/app/app.module.ts @@ -39,7 +39,7 @@ import { ImageService } from "./services"; import { LandingPageService } from "./services"; import { NotificationService } from "./services"; import { SettingsService } from "./services"; -import { IssuesService, JobService, PlexTvService, StatusService } from "./services"; +import { CustomPageService, IssuesService, JobService, PlexTvService, StatusService } from "./services"; const routes: Routes = [ { path: "*", component: PageNotFoundComponent }, @@ -144,6 +144,7 @@ export function JwtTokenGetter() { JobService, IssuesService, PlexTvService, + CustomPageService, ], bootstrap: [AppComponent], }) diff --git a/src/Ombi/ClientApp/app/custompage/custompage.component.ts b/src/Ombi/ClientApp/app/custompage/custompage.component.ts index f346bef2b..61094e793 100644 --- a/src/Ombi/ClientApp/app/custompage/custompage.component.ts +++ b/src/Ombi/ClientApp/app/custompage/custompage.component.ts @@ -2,7 +2,7 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { DomSanitizer } from "@angular/platform-browser"; import { AuthService } from "../auth/auth.service"; -import { NotificationService, SettingsService } from "../services"; +import { CustomPageService, NotificationService } from "../services"; @Component({ templateUrl: "./custompage.component.html", @@ -14,7 +14,7 @@ export class CustomPageComponent implements OnInit { public isEditing: boolean; public isAdmin: boolean; - constructor(private auth: AuthService, private settings: SettingsService, private fb: FormBuilder, + constructor(private auth: AuthService, private settings: CustomPageService, private fb: FormBuilder, private notificationService: NotificationService, private sanitizer: DomSanitizer) { } @@ -29,7 +29,7 @@ export class CustomPageComponent implements OnInit { fontAwesomeIcon: [x.fontAwesomeIcon, [Validators.required]], }); }); - this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + this.isAdmin = this.auth.hasRole("EditCustomPage"); } public onSubmit() { diff --git a/src/Ombi/ClientApp/app/services/custompage.service.ts b/src/Ombi/ClientApp/app/services/custompage.service.ts new file mode 100644 index 000000000..1fc1ea028 --- /dev/null +++ b/src/Ombi/ClientApp/app/services/custompage.service.ts @@ -0,0 +1,25 @@ +import { PlatformLocation } from "@angular/common"; +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; + +import { + ICustomPage, +} from "../interfaces"; + +import { ServiceHelpers } from "./service.helpers"; + +@Injectable() +export class CustomPageService extends ServiceHelpers { + constructor(public http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/CustomPage", platformLocation); + } + + public getCustomPage(): Observable { + return this.http.get(this.url, {headers: this.headers}); + } + + public saveCustomPage(model: ICustomPage): Observable { + return this.http.post(this.url, model, {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/app/services/index.ts b/src/Ombi/ClientApp/app/services/index.ts index edffdd625..5065ce938 100644 --- a/src/Ombi/ClientApp/app/services/index.ts +++ b/src/Ombi/ClientApp/app/services/index.ts @@ -16,3 +16,4 @@ export * from "./notificationMessage.service"; export * from "./recentlyAdded.service"; export * from "./vote.service"; export * from "./requestretry.service"; +export * from "./custompage.service"; diff --git a/src/Ombi/ClientApp/app/settings/customization/customization.component.html b/src/Ombi/ClientApp/app/settings/customization/customization.component.html index 21a992c32..1f7a158ae 100644 --- a/src/Ombi/ClientApp/app/settings/customization/customization.component.html +++ b/src/Ombi/ClientApp/app/settings/customization/customization.component.html @@ -75,7 +75,7 @@
-
diff --git a/src/Ombi/Controllers/CustomPageController.cs b/src/Ombi/Controllers/CustomPageController.cs new file mode 100644 index 000000000..6ee6fa159 --- /dev/null +++ b/src/Ombi/Controllers/CustomPageController.cs @@ -0,0 +1,53 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Settings.Settings.Models; + +namespace Ombi.Controllers +{ + [ApiV1] + [Produces("application/json")] + [ApiController] + public class CustomPageController : ControllerBase + { + public CustomPageController(ISettingsService settings) + { + _settings = settings; + } + + private readonly ISettingsService _settings; + + /// + /// Gets the Custom Page Settings. + /// + /// + [HttpGet] + [AllowAnonymous] + public async Task CustomPageSettings() + { + return await Get(); + } + + /// + /// Saves the Custom Page Settings. + /// + /// + [HttpPost] + [Authorize(OmbiRoles.EditCustomPage)] + public async Task CustomPageSettings([FromBody] CustomPageSettings page) + { + return await Save(page); + } + private async Task Get() + { + return await _settings.GetSettingsAsync(); + } + + private async Task Save(CustomPageSettings settingsModel) + { + return await _settings.SaveSettingsAsync(settingsModel); + } + } +} \ No newline at end of file diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 2976069ed..4838eabf1 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -239,6 +239,7 @@ namespace Ombi.Controllers await CreateRole(OmbiRoles.Disabled); await CreateRole(OmbiRoles.ReceivesNewsletter); await CreateRole(OmbiRoles.ManageOwnRequests); + await CreateRole(OmbiRoles.EditCustomPage); } private async Task CreateRole(string role) diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 0fe67edfd..b5ec57e29 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -707,27 +707,6 @@ namespace Ombi.Controllers return emailSettings.Enabled; } - /// - /// Gets the Custom Page Settings. - /// - /// - [HttpGet("CustomPage")] - [AllowAnonymous] - public async Task CustomPageSettings() - { - return await Get(); - } - - /// - /// Saves the Custom Page Settings. - /// - /// - [HttpPost("CustomPage")] - public async Task CustomPageSettings([FromBody] CustomPageSettings page) - { - return await Save(page); - } - /// /// Saves the discord notification settings. /// diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 282034ea5..bbf56c517 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -26,6 +26,7 @@ using Ombi.Store.Context; using Ombi.Store.Entities; using Ombi.Store.Repository; using Serilog; +using ILogger = Serilog.ILogger; namespace Ombi { @@ -42,35 +43,12 @@ namespace Ombi .AddEnvironmentVariables(); Configuration = builder.Build(); - //if (env.IsDevelopment()) - //{ - Serilog.ILogger config; - if (string.IsNullOrEmpty(StoragePath.StoragePath)) - { - config = new LoggerConfiguration() - .MinimumLevel.Debug() - .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "Logs", "log-{Date}.txt")) - .CreateLogger(); - } - else - { - config = new LoggerConfiguration() - .MinimumLevel.Debug() - .WriteTo.RollingFile(Path.Combine(StoragePath.StoragePath, "Logs", "log-{Date}.txt")) - .CreateLogger(); - } + ILogger config = new LoggerConfiguration() + .MinimumLevel.Debug() + .WriteTo.RollingFile(Path.Combine(StoragePath.StoragePath.IsNullOrEmpty() ? env.ContentRootPath : StoragePath.StoragePath, "Logs", "log-{Date}.txt")) + .CreateLogger(); + Log.Logger = config; - - - //} - //if (env.IsProduction()) - //{ - // Log.Logger = new LoggerConfiguration() - // .MinimumLevel.Debug() - // .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "Logs", "log-{Date}.txt")) - // .WriteTo.SQLite("Ombi.db", "Logs", LogEventLevel.Debug) - // .CreateLogger(); - //} } public IConfigurationRoot Configuration { get; } @@ -126,7 +104,6 @@ namespace Ombi { x.UseSQLiteStorage(sqliteStorage); x.UseActivator(new IoCJobActivator(services.BuildServiceProvider())); - //x.UseConsole(); }); services.AddCors(o => o.AddPolicy("MyPolicy", builder => From 7048f2738a3ea7ef8b37c9eb2ad32f444671c5eb Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Jan 2019 20:23:55 +0000 Subject: [PATCH 245/325] Fixed #2759 --- src/Ombi.Store/Context/OmbiContext.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index bb84f1272..a8e84c942 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -124,6 +124,16 @@ namespace Ombi.Store.Context SaveChanges(); } + var editCustomPage = Roles.Where(x => x.Name == OmbiRoles.EditCustomPage); + if (!editCustomPage.Any()) + { + Roles.Add(new IdentityRole(OmbiRoles.EditCustomPage) + { + NormalizedName = OmbiRoles.EditCustomPage.ToUpper() + }); + SaveChanges(); + } + // Make sure we have the API User var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); if (!apiUserExists) From 634928a3af97cf1812f25031971740c1f4872136 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Jan 2019 21:02:00 +0000 Subject: [PATCH 246/325] !wip really fixed it --- src/Ombi/Controllers/CustomPageController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/Controllers/CustomPageController.cs b/src/Ombi/Controllers/CustomPageController.cs index 6ee6fa159..70a167dc0 100644 --- a/src/Ombi/Controllers/CustomPageController.cs +++ b/src/Ombi/Controllers/CustomPageController.cs @@ -35,7 +35,7 @@ namespace Ombi.Controllers /// /// [HttpPost] - [Authorize(OmbiRoles.EditCustomPage)] + [Authorize(Roles = OmbiRoles.EditCustomPage)] public async Task CustomPageSettings([FromBody] CustomPageSettings page) { return await Save(page); From 1565ebce0dc366f96138b817fe66113fc4b581c6 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Jan 2019 21:32:42 +0000 Subject: [PATCH 247/325] Ignore the UserName header as part of the Api is the value is an empty string --- src/Ombi/ApiKeyMiddlewear.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ApiKeyMiddlewear.cs b/src/Ombi/ApiKeyMiddlewear.cs index f3c956df4..e8fa02d78 100644 --- a/src/Ombi/ApiKeyMiddlewear.cs +++ b/src/Ombi/ApiKeyMiddlewear.cs @@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Ombi.Core.Authentication; using Ombi.Core.Settings; +using Ombi.Helpers; using Ombi.Settings.Settings.Models; namespace Ombi @@ -98,6 +99,10 @@ namespace Ombi if (context.Request.Headers.Keys.Contains("UserName", StringComparer.InvariantCultureIgnoreCase)) { var username = context.Request.Headers["UserName"].FirstOrDefault(); + if (username.IsNullOrEmpty()) + { + UseApiUser(context); + } var um = context.RequestServices.GetService(); var user = await um.Users.FirstOrDefaultAsync(x => x.UserName.Equals(username, StringComparison.InvariantCultureIgnoreCase)); @@ -114,13 +119,18 @@ namespace Ombi } else { - var identity = new GenericIdentity("API"); - var principal = new GenericPrincipal(identity, new[] { "Admin", "ApiUser" }); - context.User = principal; + UseApiUser(context); } await next.Invoke(context); } } + + private void UseApiUser(HttpContext context) + { + var identity = new GenericIdentity("API"); + var principal = new GenericPrincipal(identity, new[] { "Admin", "ApiUser" }); + context.User = principal; + } } } \ No newline at end of file From 65ea88925adc6f05a3c88847ae58c3c5a057ad9a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Jan 2019 22:30:20 +0000 Subject: [PATCH 248/325] Added a demo mode, this will only show movies and shows that are in the public domain. Dam that stupid fruit company --- .../Engine/Demo/DemoMovieSearchEngine.cs | 106 ++++++++++++++++++ .../Engine/Demo/DemoTvSearchEngine.cs | 96 ++++++++++++++++ src/Ombi.Core/Engine/MovieSearchEngine.cs | 12 +- src/Ombi.Core/Engine/TvSearchEngine.cs | 8 +- src/Ombi.DependencyInjection/IocExtensions.cs | 3 + src/Ombi.Helpers/DemoLists.cs | 10 ++ src/Ombi.Helpers/DemoSingleton.cs | 13 +++ src/Ombi/Controllers/SearchController.cs | 52 ++++++++- src/Ombi/Program.cs | 8 +- src/Ombi/StartupExtensions.cs | 1 + src/Ombi/appsettings.json | 64 ++++++++++- 11 files changed, 360 insertions(+), 13 deletions(-) create mode 100644 src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs create mode 100644 src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs create mode 100644 src/Ombi.Helpers/DemoLists.cs create mode 100644 src/Ombi.Helpers/DemoSingleton.cs diff --git a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs new file mode 100644 index 000000000..86582fb4d --- /dev/null +++ b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; +using Ombi.Config; +using Ombi.Core.Authentication; +using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Core.Engine.Demo +{ + public class DemoMovieSearchEngine : MovieSearchEngine, IDemoMovieSearchEngine + { + public DemoMovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, + IRepository sub, IOptions lists) + : base(identity, service, movApi, mapper, logger, r, um, mem, s, sub) + { + _demoLists = lists.Value; + } + + private readonly DemoLists _demoLists; + + public async Task> Search(string search) + { + var result = await MovieApi.SearchMovie(search, null, "en"); + + for (var i = 0; i < result.Count; i++) + { + if (!_demoLists.Movies.Contains(result[i].Id)) + { + result.RemoveAt(i); + } + } + if(result.Count > 0) + return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return null; + } + + public async Task> NowPlayingMovies() + { + var rand = new Random(); + var responses = new List(); + for (int i = 0; i < 10; i++) + { + var item = rand.Next(_demoLists.Movies.Length); + var movie = _demoLists.Movies[item]; + if (responses.Any(x => x.Id == movie)) + { + i--; + continue; + } + var movieResult = await MovieApi.GetMovieInformationWithExtraInfo(movie); + var viewMovie = Mapper.Map(movieResult); + + responses.Add(await ProcessSingleMovie(viewMovie)); + } + + return responses; + } + + public async Task> PopularMovies() + { + return await NowPlayingMovies(); + } + + + public async Task> TopRatedMovies() + { + return await NowPlayingMovies(); + } + + public async Task> UpcomingMovies() + { + + return await NowPlayingMovies(); + } + } + + public interface IDemoMovieSearchEngine + { + Task> NowPlayingMovies(); + + Task> PopularMovies(); + + Task> Search(string search); + + Task> TopRatedMovies(); + + Task> UpcomingMovies(); + + } +} diff --git a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs new file mode 100644 index 000000000..edf9c430d --- /dev/null +++ b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs @@ -0,0 +1,96 @@ +using AutoMapper; +using Microsoft.Extensions.Options; +using Ombi.Api.Trakt; +using Ombi.Api.TvMaze; +using Ombi.Config; +using Ombi.Core.Authentication; +using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Ombi.Core.Engine.Demo +{ + public class DemoTvSearchEngine : TvSearchEngine, IDemoTvSearchEngine + { + + public DemoTvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + ISettingsService plexSettings, ISettingsService embySettings, IPlexContentRepository repo, + IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, + ISettingsService s, IRepository sub, IOptions lists) + : base(identity, service, tvMaze, mapper, plexSettings, embySettings, repo, embyRepo, trakt, r, um, memCache, s, sub) + { + _demoLists = lists.Value; + } + + private readonly DemoLists _demoLists; + + public async Task> Search(string search) + { + var searchResult = await TvMazeApi.Search(search); + + for (var i = 0; i < searchResult.Count; i++) + { + if (!_demoLists.TvShows.Contains(searchResult[i].show?.externals?.thetvdb ?? 0)) + { + searchResult.RemoveAt(i); + } + } + + if (searchResult != null) + { + var retVal = new List(); + foreach (var tvMazeSearch in searchResult) + { + if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) + { + continue; + } + retVal.Add(ProcessResult(tvMazeSearch)); + } + return retVal; + } + return null; + } + + public async Task> NowPlayingMovies() + { + var rand = new Random(); + var responses = new List(); + for (int i = 0; i < 10; i++) + { + var item = rand.Next(_demoLists.TvShows.Length); + var tv = _demoLists.TvShows[item]; + if (responses.Any(x => x.Id == tv)) + { + i--; + continue; + } + + var movieResult = await TvMazeApi.ShowLookup(tv); + responses.Add(ProcessResult(movieResult)); + } + + return responses; + } + + + + } + + public interface IDemoTvSearchEngine + { + Task> Search(string search); + Task> NowPlayingMovies(); + } +} diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index dda58348f..84cb8afcf 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -31,11 +31,11 @@ namespace Ombi.Core.Engine Logger = logger; } - private IMovieDbApi MovieApi { get; } - private IMapper Mapper { get; } + protected IMovieDbApi MovieApi { get; } + protected IMapper Mapper { get; } private ILogger Logger { get; } - private const int MovieLimit = 10; + protected const int MovieLimit = 10; /// /// Lookups the imdb information. @@ -184,7 +184,7 @@ namespace Ombi.Core.Engine return null; } - private async Task> TransformMovieResultsToResponse( + protected async Task> TransformMovieResultsToResponse( IEnumerable movies) { var viewMovies = new List(); @@ -195,7 +195,7 @@ namespace Ombi.Core.Engine return viewMovies; } - private async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, bool lookupExtraInfo = false) + protected async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, bool lookupExtraInfo = false) { if (lookupExtraInfo && viewMovie.ImdbId.IsNullOrEmpty()) { @@ -213,7 +213,7 @@ namespace Ombi.Core.Engine // This requires the rules to be run first to populate the RequestId property await CheckForSubscription(viewMovie); - + return viewMovie; } diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index c8e958002..b2e07f05e 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -40,8 +40,8 @@ namespace Ombi.Core.Engine EmbyContentRepo = embyRepo; } - private ITvMazeApi TvMazeApi { get; } - private IMapper Mapper { get; } + protected ITvMazeApi TvMazeApi { get; } + protected IMapper Mapper { get; } private ISettingsService PlexSettings { get; } private ISettingsService EmbySettings { get; } private IPlexContentRepository PlexContentRepo { get; } @@ -149,7 +149,7 @@ namespace Ombi.Core.Engine return processed; } - private IEnumerable ProcessResults(IEnumerable items) + protected IEnumerable ProcessResults(IEnumerable items) { var retVal = new List(); foreach (var tvMazeSearch in items) @@ -159,7 +159,7 @@ namespace Ombi.Core.Engine return retVal; } - private SearchTvShowViewModel ProcessResult(T tvMazeSearch) + protected SearchTvShowViewModel ProcessResult(T tvMazeSearch) { return Mapper.Map(tvMazeSearch); } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 09dbf4e79..68a363706 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -53,6 +53,7 @@ using Ombi.Updater; using PlexContentCacher = Ombi.Schedule.Jobs.Plex; using Ombi.Api.Telegram; using Ombi.Core.Authentication; +using Ombi.Core.Engine.Demo; using Ombi.Core.Processor; using Ombi.Schedule.Jobs.Lidarr; using Ombi.Schedule.Jobs.Plex.Interfaces; @@ -92,6 +93,8 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } public static void RegisterHttp(this IServiceCollection services) { diff --git a/src/Ombi.Helpers/DemoLists.cs b/src/Ombi.Helpers/DemoLists.cs new file mode 100644 index 000000000..42deb3845 --- /dev/null +++ b/src/Ombi.Helpers/DemoLists.cs @@ -0,0 +1,10 @@ +namespace Ombi.Config +{ + public class DemoLists + { + public int[] Movies { get; set; } + public int[] TvShows { get; set; } + } + + +} \ No newline at end of file diff --git a/src/Ombi.Helpers/DemoSingleton.cs b/src/Ombi.Helpers/DemoSingleton.cs new file mode 100644 index 000000000..22b6b2f31 --- /dev/null +++ b/src/Ombi.Helpers/DemoSingleton.cs @@ -0,0 +1,13 @@ +namespace Ombi.Helpers +{ + public class DemoSingleton + { + private static DemoSingleton instance; + + private DemoSingleton() { } + + public static DemoSingleton Instance => instance ?? (instance = new DemoSingleton()); + + public bool Demo { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 535581447..bdeacee2a 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -10,6 +10,8 @@ using Ombi.Core.Models.Search; using Ombi.Models; using StackExchange.Profiling; using Microsoft.AspNetCore.Http; +using Ombi.Core.Engine.Demo; +using Ombi.Helpers; namespace Ombi.Controllers { @@ -19,18 +21,26 @@ namespace Ombi.Controllers [ApiController] public class SearchController : Controller { - public SearchController(IMovieEngine movie, ITvSearchEngine tvEngine, ILogger logger, IMusicSearchEngine music) + public SearchController(IMovieEngine movie, ITvSearchEngine tvEngine, ILogger logger, IMusicSearchEngine music, + IDemoMovieSearchEngine demoMovieSearch, IDemoTvSearchEngine demoTvSearchEngine) { MovieEngine = movie; TvEngine = tvEngine; Logger = logger; MusicEngine = music; + DemoMovieSearch = demoMovieSearch; + DemoTvSearch = demoTvSearchEngine; + IsDemo = DemoSingleton.Instance.Demo; } + private ILogger Logger { get; } private IMovieEngine MovieEngine { get; } private ITvSearchEngine TvEngine { get; } private IMusicSearchEngine MusicEngine { get; } + private IDemoMovieSearchEngine DemoMovieSearch { get; } + private IDemoTvSearchEngine DemoTvSearch { get; } + private readonly bool IsDemo; /// /// Searches for a movie. @@ -47,6 +57,10 @@ namespace Ombi.Controllers { Logger.LogDebug("Searching : {searchTerm}", searchTerm); + if (IsDemo) + { + return await DemoMovieSearch.Search(searchTerm); + } return await MovieEngine.Search(searchTerm, null, null); } } @@ -173,6 +187,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> Popular() { + if (IsDemo) + { + return await DemoMovieSearch.PopularMovies(); + } return await MovieEngine.PopularMovies(); } /// @@ -185,6 +203,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> NowPlayingMovies() { + if (IsDemo) + { + return await DemoMovieSearch.NowPlayingMovies(); + } return await MovieEngine.NowPlayingMovies(); } /// @@ -197,6 +219,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> TopRatedMovies() { + if (IsDemo) + { + return await DemoMovieSearch.TopRatedMovies(); + } return await MovieEngine.TopRatedMovies(); } /// @@ -209,6 +235,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> UpcomingMovies() { + if (IsDemo) + { + return await DemoMovieSearch.UpcomingMovies(); + } return await MovieEngine.UpcomingMovies(); } @@ -223,6 +253,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> SearchTv(string searchTerm) { + if (IsDemo) + { + return await DemoTvSearch.Search(searchTerm); + } return await TvEngine.Search(searchTerm); } @@ -250,6 +284,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> PopularTv() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.Popular(); } @@ -263,6 +301,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> AnticipatedTv() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.Anticipated(); } @@ -277,6 +319,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> MostWatched() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.MostWatches(); } @@ -290,6 +336,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> Trending() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.Trending(); } diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 62e8e4dfe..acc904875 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -3,7 +3,6 @@ using System.IO; using System.Linq; using System.Text; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; using Ombi.Store.Context; using Ombi.Store.Entities; using CommandLine; @@ -24,12 +23,14 @@ namespace Ombi var host = string.Empty; var storagePath = string.Empty; var baseUrl = string.Empty; + var demo = false; var result = Parser.Default.ParseArguments(args) .WithParsed(o => { host = o.Host; storagePath = o.StoragePath; baseUrl = o.BaseUrl; + demo = o.Demo; }).WithNotParsed(err => { foreach (var e in err) @@ -44,6 +45,8 @@ namespace Ombi var urlValue = string.Empty; var instance = StoragePathSingleton.Instance; + var demoInstance = DemoSingleton.Instance; + demoInstance.Demo = demo; instance.StoragePath = storagePath ?? string.Empty; // Check if we need to migrate the settings CheckAndMigrate(); @@ -269,5 +272,8 @@ namespace Ombi [Option("baseurl", Required = false, HelpText = "The base URL for reverse proxy scenarios")] public string BaseUrl { get; set; } + [Option("demo", Required = false, HelpText = "Demo mode, you will never need to use this, fuck that fruit company...")] + public bool Demo { get; set; } + } } diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index d81227ff4..732089cf1 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -109,6 +109,7 @@ namespace Ombi services.Configure(configuration.GetSection("UserSettings")); services.Configure(configuration.GetSection("TokenAuthentication")); services.Configure(configuration.GetSection("LandingPageBackground")); + services.Configure(configuration.GetSection("Demo")); } public static void AddJwtAuthentication(this IServiceCollection services, IConfigurationRoot configuration) diff --git a/src/Ombi/appsettings.json b/src/Ombi/appsettings.json index 4ee01911a..7379d0a27 100644 --- a/src/Ombi/appsettings.json +++ b/src/Ombi/appsettings.json @@ -47,5 +47,67 @@ 296762, 280619 ] - } + }, + // Please ignore the below + "Demo": { + "Movies": [ + //https://en.wikipedia.org/wiki/List_of_films_in_the_public_domain_in_the_United_States + 130816, + 20278, + 22657, + 29998, + 22356, + 120862, + 23325, + 22718, + 10378, + 22733, + 144613, + 156397, + 43888, + 262743, + 92341, + 75888, + 53828, + 38346, + 33468, + 72012, + 22642, + 15401, + 16093, + 4808, + 111370, + 22948, + 165009, + 43386, + 105852, + 166316, + 18449, + 28503, + 20367, + 41021 //The Devil Bat + ], + "TvShows": [ + //https://infogalactic.com/info/List_of_TV_series_with_episodes_in_the_public_domain + 26741, + 9475, + 4379, + 17434, + 12751, + 17436, + 4378, + 7792, + 10643, + 23503, + 19339, + 10632, + 12740, + 23466, + 6910, + 3327, + 2122, + 22148, + 25941 // Front Row Center + ] + } } From 3bf07c63f904d173b3f4596a17688a38359f0974 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Jan 2019 22:34:36 +0000 Subject: [PATCH 249/325] Fixed #2756 --- src/Ombi/ClientApp/app/app.component.ts | 7 ++++--- src/Ombi/ClientApp/app/services/settings.service.ts | 8 -------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Ombi/ClientApp/app/app.component.ts b/src/Ombi/ClientApp/app/app.component.ts index d865e6604..7005f147c 100644 --- a/src/Ombi/ClientApp/app/app.component.ts +++ b/src/Ombi/ClientApp/app/app.component.ts @@ -4,7 +4,7 @@ import { NavigationStart, Router } from "@angular/router"; import { TranslateService } from "@ngx-translate/core"; import { AuthService } from "./auth/auth.service"; import { ILocalUser } from "./auth/IUserLogin"; -import { IdentityService, NotificationService } from "./services"; +import { CustomPageService, IdentityService, NotificationService } from "./services"; import { JobService, SettingsService } from "./services"; import { ICustomizationSettings, ICustomPage } from "./interfaces"; @@ -35,7 +35,8 @@ export class AppComponent implements OnInit { private readonly jobService: JobService, public readonly translate: TranslateService, private readonly identityService: IdentityService, - private readonly platformLocation: PlatformLocation) { + private readonly platformLocation: PlatformLocation, + private readonly customPageService: CustomPageService) { const base = this.platformLocation.getBaseHrefFromDOM(); if (base.length > 1) { @@ -57,7 +58,7 @@ export class AppComponent implements OnInit { this.settingsService.getCustomization().subscribe(x => { this.customizationSettings = x; if(this.customizationSettings.useCustomPage) { - this.settingsService.getCustomPage().subscribe(c => { + this.customPageService.getCustomPage().subscribe(c => { this.customPageSettings = c; if(!this.customPageSettings.title) { this.customPageSettings.title = "Custom Page"; diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 4e68d28df..776c47e96 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -113,14 +113,6 @@ export class SettingsService extends ServiceHelpers { return this.http.get(`${this.url}/Authentication`, {headers: this.headers}); } - public getCustomPage(): Observable { - return this.http.get(`${this.url}/CustomPage`, {headers: this.headers}); - } - - public saveCustomPage(model: ICustomPage): Observable { - return this.http.post(`${this.url}/CustomPage`, model, {headers: this.headers}); - } - public getClientId(): Observable { return this.http.get(`${this.url}/clientid`, {headers: this.headers}); } From 59b55f451b991f7f11ee397374689df6eac76cdd Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 24 Jan 2019 08:26:47 +0000 Subject: [PATCH 250/325] Fixed build !wip --- src/Ombi/ClientApp/app/services/settings.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 776c47e96..64a6edd14 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -10,7 +10,6 @@ import { ICronTestModel, ICronViewModelBody, ICustomizationSettings, - ICustomPage, IDiscordNotifcationSettings, IDogNzbSettings, IEmailNotificationSettings, From d9209642f21aed48c1643cda288c242c5b18ff29 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 28 Jan 2019 19:38:00 +0000 Subject: [PATCH 251/325] !wip demo --- src/Ombi.Helpers/DemoLists.cs | 1 + .../app/services/settings.service.ts | 1 - src/Ombi/StartupExtensions.cs | 4 +- src/Ombi/appsettings.json | 3 +- src/Ombi/package-lock.json | 11721 ++++++++++++++++ 5 files changed, 11727 insertions(+), 3 deletions(-) create mode 100644 src/Ombi/package-lock.json diff --git a/src/Ombi.Helpers/DemoLists.cs b/src/Ombi.Helpers/DemoLists.cs index 42deb3845..c0d0dd77f 100644 --- a/src/Ombi.Helpers/DemoLists.cs +++ b/src/Ombi.Helpers/DemoLists.cs @@ -2,6 +2,7 @@ { public class DemoLists { + public bool Enabled { get; set; } public int[] Movies { get; set; } public int[] TvShows { get; set; } } diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 776c47e96..64a6edd14 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -10,7 +10,6 @@ import { ICronTestModel, ICronViewModelBody, ICustomizationSettings, - ICustomPage, IDiscordNotifcationSettings, IDogNzbSettings, IEmailNotificationSettings, diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index 732089cf1..681148a07 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -86,7 +86,7 @@ namespace Ombi } - c.OperationFilter(); + c.OperationFilter();^ c.DescribeAllParametersInCamelCase(); }); } @@ -110,6 +110,8 @@ namespace Ombi services.Configure(configuration.GetSection("TokenAuthentication")); services.Configure(configuration.GetSection("LandingPageBackground")); services.Configure(configuration.GetSection("Demo")); + var enabledDemo = Convert.ToBoolean(configuration.GetSection("Demo:Enabled").Value); + DemoSingleton.Instance.Demo = enabledDemo; } public static void AddJwtAuthentication(this IServiceCollection services, IConfigurationRoot configuration) diff --git a/src/Ombi/appsettings.json b/src/Ombi/appsettings.json index 7379d0a27..7babcdbdd 100644 --- a/src/Ombi/appsettings.json +++ b/src/Ombi/appsettings.json @@ -50,6 +50,7 @@ }, // Please ignore the below "Demo": { + "Enabled": true, "Movies": [ //https://en.wikipedia.org/wiki/List_of_films_in_the_public_domain_in_the_United_States 130816, @@ -108,6 +109,6 @@ 2122, 22148, 25941 // Front Row Center - ] + ] } } diff --git a/src/Ombi/package-lock.json b/src/Ombi/package-lock.json new file mode 100644 index 000000000..fec5ad4b2 --- /dev/null +++ b/src/Ombi/package-lock.json @@ -0,0 +1,11721 @@ +{ + "name": "ombi", + "version": "2.6.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@angular-devkit/core": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.2.3.tgz", + "integrity": "sha512-NnN8O+97nJAxqD2zVTDlU8dSzrGCZmqYMDqDoRJJChYxAgmGwP4lhb+Jyi5D34tPxgKRTnjTOwC+G7D+WrXSDQ==", + "requires": { + "ajv": "6.6.2", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } + }, + "@angular/animations": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.2.tgz", + "integrity": "sha512-St03YR3N4Rv0vLr0+3V0kmf/QNi9q0tOenAlHP+jG/YySPkkv8P3xRcGVU38ID4JQzRiShUD+k2r+oZGCQMNjw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/cdk": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-7.2.2.tgz", + "integrity": "sha512-DG4Ip9COZuQngG31gNFrJRtVPYC8H938dCHuqVjHrLEKfdsKzvprI/y0W+tr/sUnIbIJWEPSvnzmS3XYOgmFyg==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^1.7.1" + } + }, + "@angular/common": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.2.tgz", + "integrity": "sha512-43EcR3mbM+dKH4VE1EYS1HxSuEToxxv5XPktKqdzY95g8PBOxe11ifcXoYHgImd7YOWzcKoy0k6yQbX3o0cZ8g==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.2.tgz", + "integrity": "sha512-vjPreOVPca6HSuDmj7N1w5u8hwXdm98gEPo2wqQMVuJd6qvGEyLYE9FsHc0XCchyQEKSybAYl1dwsjZq2nNSvQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler-cli": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.2.tgz", + "integrity": "sha512-ac62YlDescAaf0qPguyRkpzWCMNlwtsKObq80GKADP33Sxm0BxGt4+Wz6rolvUuWzCX8aZwJ0FA7ehKxdmdQoA==", + "requires": { + "canonical-path": "1.0.0", + "chokidar": "^1.4.2", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "shelljs": "^0.8.1", + "source-map": "^0.6.1", + "tslib": "^1.9.0", + "yargs": "9.0.1" + } + }, + "@angular/core": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.2.tgz", + "integrity": "sha512-kQ0HxUYAPvly8b3aibTGbiodFnBBgo3asXAQuPgFjYYEqcKR1zZII7PQdaEF9kb9sfm/IKLKj4nd9fZ0gcgqZg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/forms": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.2.tgz", + "integrity": "sha512-IsvVuUnzIA2ryRmh7l42AANPZFSyNcwqZNtxbmRq2wm3Lfed64U0rsRWWNqipjz7QTxZ2SRdAlP+XDgzg8hvMQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/http": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.2.tgz", + "integrity": "sha512-+9dZgiVQStGUO3iJGxEWBkjDCARuVLIPk7QPl4Qntbz8Sd/kR7IBqXMM+74W7T5rlG6bunDxq6LuisvsjWCppw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/material": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-7.2.2.tgz", + "integrity": "sha512-HTtDhK5XkDvP6GPg4WTTa0HbeeagTfVRooTfw0TA+IuTAMBhXt5h1yzuGpFyMap8/PUVZN1D04g2CLhBSzoDxg==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/platform-browser": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.2.tgz", + "integrity": "sha512-eiaqHq26PVASx1kTngBDkFkXhaJzEjoGtc5I+wQUef8CUjq6ZViWz8tUgiiDPOWdqUKUacRZG4q6VR/6uwQj0A==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.2.tgz", + "integrity": "sha512-bw5PuzMzjKMecB4slG/btmvxgn4qFWhNmJVpf2pbtZW7NtZz3HlrqipYzMk9XrCUDGjtwy7O2Z71C3ujI748iw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/platform-server": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-7.2.2.tgz", + "integrity": "sha512-lV4CvU06sEaU9q+F11eT9tgC/gFfyK21LkUrLw2nP3mLPBEOx4zhW1R452grN5a/8OFlxZOoSlYWdTQI2QN5CA==", + "requires": { + "domino": "^2.1.0", + "tslib": "^1.9.0", + "xhr2": "^0.1.4" + } + }, + "@angular/router": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.2.tgz", + "integrity": "sha512-+cBC+JxbPdjk+Nyqq27PKkjfIdnc+H+xjMGrkO6dlAKhVMGxyNaYt5NUNugb8XJPsQ1XNXyzwTfZK6jcAGLw6w==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@auth0/angular-jwt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-2.1.0.tgz", + "integrity": "sha512-1KFtqswmJeM8JiniagSenpwHKTf9l+W+TmfsWV+x9SoZIShc6YmBsZDxd+oruZJL7MbJlxIJ3SQs7Yl1wraQdg==", + "requires": { + "url": "^0.11.0" + } + }, + "@cypress/listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-cursor": "^1.0.2", + "date-fns": "^1.27.2", + "figures": "^1.7.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "@cypress/xvfb": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.3.tgz", + "integrity": "sha512-yYrK+/bgL3hwoRHMZG4r5fyLniCy1pXex5fimtewAY6vE/jsVs8Q37UsEO03tFlcmiLnQ3rBNMaZBYTi/+C1cw==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@ng-bootstrap/ng-bootstrap": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-3.3.1.tgz", + "integrity": "sha512-awty+5Kil0i/xIV7SSmKa5YozU83EdIx2EenF2AUDTczSKhHNhRByo82rjtwIhshN25/ZEss4aSDhgILLI88fw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@ngtools/webpack": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.2.3.tgz", + "integrity": "sha512-TbaCeE1mkruWzFGfAP1kSnwk4v5k0MQUxzy2reUvCfq80H8jYrqUuMZJa0VLPoEky5cYIy98Fe2Wz9xlEdx7sA==", + "requires": { + "@angular-devkit/core": "7.2.3", + "enhanced-resolve": "4.1.0", + "rxjs": "6.3.3", + "tree-kill": "1.2.0", + "webpack-sources": "1.2.0" + } + }, + "@ngu/carousel": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@ngu/carousel/-/carousel-1.5.5.tgz", + "integrity": "sha512-tPDThxM325ss4fBzUtu7OExuC0aR8QIZIHJwYHpfF955TR9Zs0argokopS8DX9mCTM3tYL+Qgy1ui0KjCJzHBg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@ngx-translate/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-11.0.1.tgz", + "integrity": "sha512-nBCa1ZD9fAUY/3eskP3Lql2fNg8OMrYIej1/5GRsfcutx9tG/5fZLCv9m6UCw1aS+u4uK/vXjv1ctG/FdMvaWg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@ngx-translate/http-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-4.0.0.tgz", + "integrity": "sha512-x8LumqydWD7eX9yQTAVeoCM9gFUIGVTUjZqbxdAUavAA3qVnk9wCQux7iHLPXpydl8vyQmLoPQR+fFU+DUDOMA==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@types/anymatch": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.0.tgz", + "integrity": "sha512-7WcbyctkE8GTzogDb0ulRAEw7v8oIS54ft9mQTU7PfM0hp5e+8kpa+HeQ7IQrFbKtJXBKcZ4bh+Em9dTw5L6AQ==" + }, + "@types/blob-util": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/blob-util/-/blob-util-1.3.3.tgz", + "integrity": "sha512-4ahcL/QDnpjWA2Qs16ZMQif7HjGP2cw3AGjHabybjw7Vm1EKu+cfQN1D78BaZbS1WJNa1opSMF5HNMztx7lR0w==", + "dev": true + }, + "@types/bluebird": { + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.18.tgz", + "integrity": "sha512-OTPWHmsyW18BhrnG5x8F7PzeZ2nFxmHGb42bZn79P9hl+GI5cMzyPgQTwNjbem0lJhoru/8vtjAFCUOu3+gE2w==", + "dev": true + }, + "@types/chai": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.8.tgz", + "integrity": "sha512-m812CONwdZn/dMzkIJEY0yAs4apyTkTORgfB2UsMOxgkUbC205AHnm4T8I0I5gPg9MHrFc1dJ35iS75c0CJkjg==", + "dev": true + }, + "@types/chai-jquery": { + "version": "1.1.35", + "resolved": "https://registry.npmjs.org/@types/chai-jquery/-/chai-jquery-1.1.35.tgz", + "integrity": "sha512-7aIt9QMRdxuagLLI48dPz96YJdhu64p6FCa6n4qkGN5DQLHnrIjZpD9bXCvV2G0NwgZ1FAmfP214dxc5zNCfgQ==", + "dev": true, + "requires": { + "@types/chai": "*", + "@types/jquery": "*" + } + }, + "@types/core-js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.0.tgz", + "integrity": "sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==" + }, + "@types/jquery": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.6.tgz", + "integrity": "sha512-403D4wN95Mtzt2EoQHARf5oe/jEPhzBOBNrunk+ydQGW8WmkQ/E8rViRAEB1qEt/vssfGfNVD6ujP4FVeegrLg==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.87", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.87.tgz", + "integrity": "sha512-AqRC+aEF4N0LuNHtcjKtvF9OTfqZI0iaBoe3dA6m/W+/YZJBZjBmW/QIZ8fBeXC6cnytSY9tBoFBqZ9uSCeVsw==", + "dev": true + }, + "@types/mini-css-extract-plugin": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.2.0.tgz", + "integrity": "sha512-oHec+Vasp+K3C1Hb9HpwbA9Iw8ywqDgo9edWQJdBqxu05JH2AQsR56Zo5THpYbu1ieh/xJCvMRIHRdvrUBDmcA==", + "requires": { + "@types/webpack": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/mocha": { + "version": "2.2.44", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz", + "integrity": "sha512-k2tWTQU8G4+iSMvqKi0Q9IIsWAp/n8xzdZS4Q4YVIltApoMA00wFBFdlJnmoaK1/z7B0Cy0yPe6GgXteSmdUNw==", + "dev": true + }, + "@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + }, + "@types/sinon": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.0.0.tgz", + "integrity": "sha512-kcYoPw0uKioFVC/oOqafk2yizSceIQXCYnkYts9vJIwQklFRsMubTObTDrjQamUyBRd47332s85074cd/hCwxg==", + "dev": true + }, + "@types/sinon-chai": { + "version": "2.7.29", + "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-2.7.29.tgz", + "integrity": "sha512-EkI/ZvJT4hglWo7Ipf9SX+J+R9htNOMjW8xiOhce7+0csqvgoF5IXqY5Ae1GqRgNtWCuaywR5HjVa1snkTqpOw==", + "dev": true, + "requires": { + "@types/chai": "*", + "@types/sinon": "*" + } + }, + "@types/tapable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.4.tgz", + "integrity": "sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ==" + }, + "@types/uglify-js": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.0.4.tgz", + "integrity": "sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==", + "requires": { + "source-map": "^0.6.1" + } + }, + "@types/webpack": { + "version": "4.4.24", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.4.24.tgz", + "integrity": "sha512-yg99CjvB7xZ/iuHrsZ7dkGKoq/FRDzqLzAxKh2EmTem6FWjzrty4FqCqBYuX5z+MFwSaaQGDAX4Q9HQkLjGLnQ==", + "requires": { + "@types/anymatch": "*", + "@types/node": "*", + "@types/tapable": "*", + "@types/uglify-js": "*", + "source-map": "^0.6.0" + } + }, + "@types/webpack-bundle-analyzer": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.0.tgz", + "integrity": "sha512-+qy5xatScNZW4NbIVaiV38XOeHbKRa4FIPeMf2VDpZEon9W/cxjaVR080vRrRGvfq4tRvOusTEypSMxTvjcSzw==", + "requires": { + "@types/webpack": "*" + } + }, + "@types/webpack-merge": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/webpack-merge/-/webpack-merge-4.1.3.tgz", + "integrity": "sha512-VdmNuYIvIouYlCI73NLKOE1pOVAxv5m5eupvTemojZz9dqghoQXmeEveI6CqeuWpCH6x6FLp6+tXM2sls20/MA==", + "requires": { + "@types/webpack": "*" + } + }, + "@webassemblyjs/ast": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", + "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "requires": { + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", + "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", + "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", + "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", + "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "requires": { + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", + "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", + "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==" + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", + "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", + "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", + "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", + "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "requires": { + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/utf8": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", + "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", + "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/helper-wasm-section": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-opt": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", + "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", + "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", + "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", + "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/floating-point-hex-parser": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-code-frame": "1.7.11", + "@webassemblyjs/helper-fsm": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", + "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==" + }, + "@yellowspot/ng-truncate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@yellowspot/ng-truncate/-/ng-truncate-1.4.0.tgz", + "integrity": "sha512-EgSP11lbkoegNgzkYvVVS4OSosgYiluuHFmWRE/Wb+HBdfdnaHI+3gQzpdriE/fhZmbfC+C9xtTyR15OL+AgMg==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz", + "integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==" + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" + }, + "ajv": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", + "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-keywords": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.3.0.tgz", + "integrity": "sha512-CMzN9S62ZOO4sA/mJZIO4S++ZM7KFWzH3PPWkveLhy4OZ9i1/VatgwWMD46w/XbGCBy7Ye0gCk+Za6mmyfKK7g==" + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "angular-router-loader": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/angular-router-loader/-/angular-router-loader-0.8.5.tgz", + "integrity": "sha512-8wggCTKGgzB1o8co3Wvj+p9pKN7T7q3C477lEz3NLjvPVzUti8rv9i45Di+4aO/k+HvzGh3s8QdNlXU2Bl4avQ==", + "requires": { + "loader-utils": "^1.0.2" + } + }, + "angular2-template-loader": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz", + "integrity": "sha1-wNROkP/w+sleiyPwQ6zaf9HFHXw=", + "requires": { + "loader-utils": "^0.2.15" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "aspnet-webpack": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-3.0.0.tgz", + "integrity": "sha512-umUYjAoWkszsH3GmN6BN9CR9QluhUBx/FH1bn72mC6/VcgeoC1uzlw/J2fi+HyiIuSQHfzNd1rx57GBc7hNqZg==", + "requires": { + "connect": "^3.4.1", + "es6-promise": "^3.1.2", + "memory-fs": "^0.3.0", + "require-from-string": "^1.1.0", + "webpack-node-externals": "^1.4.3" + }, + "dependencies": { + "memory-fs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=" + }, + "async": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.4.0.tgz", + "integrity": "sha1-SZAgDxjqW4N8LMT4wDGmmFw4VhE=", + "dev": true, + "requires": { + "lodash": "^4.14.0" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "requires": { + "browserslist": "^1.7.6", + "caniuse-db": "^1.0.30000634", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^5.2.16", + "postcss-value-parser": "^3.2.3" + } + }, + "awesome-typescript-loader": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz", + "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==", + "requires": { + "chalk": "^2.4.1", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.1.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.3", + "webpack-log": "^1.2.0" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "requires": { + "babel-runtime": "^6.22.0", + "core-js": "^2.4.0", + "regenerator-runtime": "^0.10.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" + }, + "bfj-node4": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/bfj-node4/-/bfj-node4-5.3.1.tgz", + "integrity": "sha512-SOmOsowQWfXc7ybFARsK3C4MCOWzERaOMV/Fl3Tgjs+5dJWyzo3oa127jL44eMbQiAN17J7SvAs2TRxEScTUmg==", + "requires": { + "bluebird": "^3.5.1", + "check-types": "^7.3.0", + "tryer": "^1.0.0" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==" + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "bootstrap": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.0.tgz", + "integrity": "sha512-F1yTDO9OHKH0xjl03DsOe8Nu1OWBIeAugGMhy3UTIYDdbbIPesQIhCEbj+HEr6wqlwweGAlP8F3OBC6kEuhFuw==" + }, + "bootswatch": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/bootswatch/-/bootswatch-3.4.0.tgz", + "integrity": "sha512-eCMWAa3/vYkT7bKDbffcgmbfy8keGSETMY0ECt+vAnKf2nKtgJUlr99x5OGFp3ZKW4hQrsSR9mPhNqFQRl4PXw==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "requires": { + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cachedir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-1.3.0.tgz", + "integrity": "sha512-O1ji32oyON9laVPJL1IZ5bmwd2cB46VfpxkDequezH+15FDzzVddEyrGEeX4WusDSqKxdyFdDQDEG1yo1GoWkg==", + "dev": true, + "requires": { + "os-homedir": "^1.0.1" + } + }, + "caller-id": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-id/-/caller-id-0.1.0.tgz", + "integrity": "sha1-Wb2sCJPRLDhxQIJ5Ix+XRYNk8Hs=", + "requires": { + "stack-trace": "~0.0.7" + } + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + } + } + }, + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", + "requires": { + "browserslist": "^1.3.6", + "caniuse-db": "^1.0.30000529", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-db": { + "version": "1.0.30000932", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000932.tgz", + "integrity": "sha512-nc4jIhwpajQCvADmBo3F1fj8ySvE2+dw0lXAmYmtYJi1l7CvfdZVTkrwD60SrQHDC1mddgYtLyAcwrtYVtiMSQ==" + }, + "canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, + "check-types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", + "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==" + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" + }, + "chrome-trace-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "requires": { + "chalk": "^1.1.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "requires": { + "source-map": "~0.6.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", + "dev": true + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "clone-deep": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", + "requires": { + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "requires": { + "q": "^1.1.2" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "requires": { + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "requires": { + "color-name": "^1.0.0" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "colormin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", + "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", + "requires": { + "color": "^0.11.0", + "css-color-names": "0.0.4", + "has": "^1.0.1" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" + }, + "common-tags": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.4.0.tgz", + "integrity": "sha1-EYe+Tz1M8MBCfUP3Tu8fc1AWFMA=", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0" + } + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "requires": { + "date-now": "^0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-webpack-plugin": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", + "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==", + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "^2.1.1" + } + } + } + }, + "core-js": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", + "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" + }, + "css-loader": { + "version": "0.28.11", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", + "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", + "requires": { + "babel-code-frame": "^6.26.0", + "css-selector-tokenizer": "^0.7.0", + "cssnano": "^3.10.0", + "icss-utils": "^2.1.0", + "loader-utils": "^1.0.2", + "lodash.camelcase": "^4.3.0", + "object-assign": "^4.1.1", + "postcss": "^5.0.6", + "postcss-modules-extract-imports": "^1.2.0", + "postcss-modules-local-by-default": "^1.2.0", + "postcss-modules-scope": "^1.1.0", + "postcss-modules-values": "^1.3.0", + "postcss-value-parser": "^3.3.0", + "source-list-map": "^2.0.0" + } + }, + "css-selector-tokenizer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + } + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "requires": { + "autoprefixer": "^6.3.1", + "decamelize": "^1.1.2", + "defined": "^1.0.0", + "has": "^1.0.1", + "object-assign": "^4.0.1", + "postcss": "^5.0.14", + "postcss-calc": "^5.2.0", + "postcss-colormin": "^2.1.8", + "postcss-convert-values": "^2.3.4", + "postcss-discard-comments": "^2.0.4", + "postcss-discard-duplicates": "^2.0.1", + "postcss-discard-empty": "^2.0.1", + "postcss-discard-overridden": "^0.1.1", + "postcss-discard-unused": "^2.2.1", + "postcss-filter-plugins": "^2.0.0", + "postcss-merge-idents": "^2.1.5", + "postcss-merge-longhand": "^2.0.1", + "postcss-merge-rules": "^2.0.3", + "postcss-minify-font-values": "^1.0.2", + "postcss-minify-gradients": "^1.0.1", + "postcss-minify-params": "^1.0.4", + "postcss-minify-selectors": "^2.0.4", + "postcss-normalize-charset": "^1.1.0", + "postcss-normalize-url": "^3.0.7", + "postcss-ordered-values": "^2.1.0", + "postcss-reduce-idents": "^2.2.2", + "postcss-reduce-initial": "^1.0.0", + "postcss-reduce-transforms": "^1.0.3", + "postcss-svgo": "^2.1.1", + "postcss-unique-selectors": "^2.0.2", + "postcss-value-parser": "^3.2.3", + "postcss-zindex": "^2.0.1" + } + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", + "requires": { + "clap": "^1.0.9", + "source-map": "^0.5.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + }, + "cypress": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-3.1.4.tgz", + "integrity": "sha512-8VJYtCAFqHXMnRDo4vdomR2CqfmhtReoplmbkXVspeKhKxU8WsZl0Nh5yeil8txxhq+YQwDrInItUqIm35Vw+g==", + "dev": true, + "requires": { + "@cypress/listr-verbose-renderer": "0.4.1", + "@cypress/xvfb": "1.2.3", + "@types/blob-util": "1.3.3", + "@types/bluebird": "3.5.18", + "@types/chai": "4.0.8", + "@types/chai-jquery": "1.1.35", + "@types/jquery": "3.3.6", + "@types/lodash": "4.14.87", + "@types/minimatch": "3.0.3", + "@types/mocha": "2.2.44", + "@types/sinon": "7.0.0", + "@types/sinon-chai": "2.7.29", + "bluebird": "3.5.0", + "cachedir": "1.3.0", + "chalk": "2.4.1", + "check-more-types": "2.24.0", + "commander": "2.11.0", + "common-tags": "1.4.0", + "debug": "3.1.0", + "execa": "0.10.0", + "executable": "4.1.1", + "extract-zip": "1.6.6", + "fs-extra": "4.0.1", + "getos": "3.1.0", + "glob": "7.1.2", + "is-ci": "1.0.10", + "is-installed-globally": "0.1.0", + "lazy-ass": "1.6.0", + "listr": "0.12.0", + "lodash": "4.17.11", + "log-symbols": "2.2.0", + "minimist": "1.2.0", + "moment": "2.22.2", + "ramda": "0.24.1", + "request": "2.87.0", + "request-progress": "0.3.1", + "supports-color": "5.1.0", + "tmp": "0.0.31", + "url": "0.11.0", + "yauzl": "2.8.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "bluebird": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "moment": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" + } + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + } + } + }, + "tmp": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", + "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "^1.4.1" + } + } + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "dependency-graph": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", + "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==" + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "requires": { + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "domino": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.1.tgz", + "integrity": "sha512-fqoTi6oQ881wYRENIEmz78hKVoc3X9HqVpklo419yxzebys6dtU5c83iVh3UYvvexPFdAuwlDYCsUM9//CrMMg==" + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "~1.1.9" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "duplexify": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" + }, + "electron-to-chromium": { + "version": "1.3.108", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.108.tgz", + "integrity": "sha512-/QI4hMpAh48a1Sea6PALGv+kuVne9A2EWGd8HrWHMdYhIzGtbhVVHh6heL5fAzGaDnZuPyrlWJRl8WPm4RyiQQ==" + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.47", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", + "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-templates": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", + "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", + "requires": { + "recast": "~0.11.12", + "through": "~2.3.6" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-source-polyfill": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-0.0.12.tgz", + "integrity": "sha1-5TnNZ/3vJ2ChaqUmL6mBNN9S468=" + }, + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "requires": { + "pify": "^2.2.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "^2.1.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expose-loader": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/expose-loader/-/expose-loader-0.7.5.tgz", + "integrity": "sha512-iPowgKUZkTPX5PznYsmifVj9Bob0w2wTHVkt/eYNPSzyebkUgIedmskf/kcfEIWpiWjg3JRjnW+a17XypySMuw==" + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extract-zip": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz", + "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "debug": "2.6.9", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "~1.0.1" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==" + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-loader": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^0.4.5" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=" + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "fined": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", + "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=" + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" + }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "font-awesome": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.1.tgz", + "integrity": "sha1-f8DGyJV/mD9X8waiTlud3Y0N2IA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.3", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.2.0", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.6.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true + } + } + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "requires": { + "globule": "~0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getos": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.1.0.tgz", + "integrity": "sha512-i9vrxtDu5DlLVFcrbqUqGWYlZN/zZ4pGMICCAcZoYsX3JA54nYp8r5EThw5K+m2q3wszkx4Th746JstspB0H4Q==", + "dev": true, + "requires": { + "async": "2.4.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "requires": { + "gaze": "^0.5.1" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "requires": { + "find-index": "^0.1.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-modules-path": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.1.tgz", + "integrity": "sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==" + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=" + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=" + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "gulp-run": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/gulp-run/-/gulp-run-1.7.1.tgz", + "integrity": "sha1-4XwKy3wwtuKu7iPAREKpbAys7/o=", + "requires": { + "gulp-util": "^3.0.0", + "lodash.defaults": "^4.0.1", + "lodash.template": "^4.0.2", + "vinyl": "^0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "requires": { + "glogg": "^1.0.0" + } + }, + "gzip-size": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-4.1.0.tgz", + "integrity": "sha1-iuCWJX6r59acRb4rZ8RIEk/7UXw=", + "requires": { + "duplexer": "^0.1.1", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "hammerjs": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", + "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" + }, + "html-loader": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", + "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", + "requires": { + "es6-templates": "^0.2.3", + "fastparse": "^1.1.1", + "html-minifier": "^3.5.8", + "loader-utils": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "dependencies": { + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + } + } + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "dependencies": { + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + } + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", + "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", + "requires": { + "ansi-escapes": "^1.1.0", + "chalk": "^1.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.1", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx": "^4.1.0", + "string-width": "^2.0.0", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-ci": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", + "dev": true, + "requires": { + "ci-info": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jquery": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" + }, + "js-base64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "requires": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "lightercollective": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lightercollective/-/lightercollective-0.1.0.tgz", + "integrity": "sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ==" + }, + "listr": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz", + "integrity": "sha1-a84sD1YD+klYDqF81qAMwOX6RRo=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "figures": "^1.7.0", + "indent-string": "^2.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.2.0", + "listr-verbose-renderer": "^0.4.0", + "log-symbols": "^1.0.2", + "log-update": "^1.0.2", + "ora": "^0.2.3", + "p-map": "^1.1.1", + "rxjs": "^5.0.0-beta.11", + "stream-to-observable": "^0.1.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz", + "integrity": "sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^1.0.2", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-cursor": "^1.0.2", + "date-fns": "^1.27.2", + "figures": "^1.7.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + }, + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=" + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "^2.0.1" + } + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "dev": true, + "requires": { + "ansi-escapes": "^1.0.0", + "cli-cursor": "^1.0.2" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + } + } + }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "magic-string": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", + "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", + "requires": { + "sourcemap-codec": "^1.4.1" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "math-expression-evaluator": { + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", + "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=" + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==" + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mini-css-extract-plugin": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.5.tgz", + "integrity": "sha512-dqBanNfktnp2hwL2YguV9Jh91PFX7gu7nRLs4TGsbAfAG6WOtlynFRYzwDwmmeSb5uIwHo9nx1ta0f7vAZVp2w==", + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=" + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mock-require": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-2.0.2.tgz", + "integrity": "sha1-HqpxqtIwE3c9En3H6Ro/u0g31g0=", + "requires": { + "caller-id": "^0.1.0" + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "requires": { + "duplexer2": "0.0.2" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "ng2-cookies": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/ng2-cookies/-/ng2-cookies-1.0.12.tgz", + "integrity": "sha1-Pz5hPgE3sGSbcFxngHS0vQgUnMw=" + }, + "ngx-bootstrap": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-3.2.0.tgz", + "integrity": "sha512-oLSLIWZgRiIfcuxyXLMZUOhX3wZtg6lpuMbdo/0UzMDg2bSOe1XPskcKZ/iuOa3FOlU9rjuYMzswHYYV5f/QCA==" + }, + "ngx-clipboard": { + "version": "11.1.9", + "resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-11.1.9.tgz", + "integrity": "sha512-xF54Ibt/04g2B5SnYylNz7ESP1/thuC7odo+0bKkgbCC873NaqP1VTVx/umh/cnezlXKu8zuWNzzg05tvfgaJg==", + "requires": { + "ngx-window-token": "^1.0.2", + "tslib": "^1.9.0" + } + }, + "ngx-editor": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ngx-editor/-/ngx-editor-4.1.0.tgz", + "integrity": "sha512-TdbFoHYJjWjyrYEw6fiYrP50s7mLcRErvSYfQ+Nz47Hse44klogi7FDl+hUjVZPBQVc5xXtTwcGSzId3ptxf8w==", + "requires": { + "tslib": "^1.9.0" + } + }, + "ngx-infinite-scroll": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-6.0.1.tgz", + "integrity": "sha512-20WcD+3Qh3O0IEFyIjt55JPTKw5W1hAxERXMUDgGDRveS3IBpBxv2DuX5vuHG/bNGC+WoTDlNR/XXScNNicRpw==", + "requires": { + "opencollective": "^1.0.3" + } + }, + "ngx-moment": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ngx-moment/-/ngx-moment-3.3.0.tgz", + "integrity": "sha512-6fpllpJqLfjRWboOhphgeEYt+rzIA9O29rG5QWCebRt2X0uNk4P93sLEb0S8lbDF0dEp2NOC3UOD+xoCVlJQhA==", + "requires": { + "tslib": "^1.9.0" + } + }, + "ngx-order-pipe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ngx-order-pipe/-/ngx-order-pipe-2.0.2.tgz", + "integrity": "sha512-uFDNHaY36bpF+aK9jhNdMS7BclztZYpAKHHIZg9VTL/kuhETSObX+lDIlssEpovy27lJY+Ymmey40FsEk1YMvw==" + }, + "ngx-window-token": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ngx-window-token/-/ngx-window-token-1.0.2.tgz", + "integrity": "sha512-bFgvi7MYSK1p4b3Mqvn9+biXaO8QDEbpP2sEMSwr0Zgrwh6zCO3F92a6SIIzusqpZBAhxyfVSqj3mO5qIxlM5Q==", + "requires": { + "tslib": "^1.9.0" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-fetch": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, + "node-libs-browser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "0.0.4" + } + }, + "node-sass": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz", + "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==", + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash.assign": "^4.2.0", + "lodash.clonedeep": "^4.3.2", + "lodash.mergewith": "^4.6.0", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.10.0", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "^2.2.4", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "requires": { + "globule": "^1.0.0" + } + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opencollective": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", + "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", + "requires": { + "babel-polyfill": "6.23.0", + "chalk": "1.1.3", + "inquirer": "3.0.6", + "minimist": "1.2.0", + "node-fetch": "1.6.3", + "opn": "4.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==" + }, + "opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "cli-cursor": "^1.0.2", + "cli-spinners": "^0.1.2", + "object-assign": "^4.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + }, + "dependencies": { + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "requires": { + "once": "~1.3.0" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "requires": { + "wrappy": "1" + } + } + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=" + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "pace-progress": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pace-progress/-/pace-progress-1.0.2.tgz", + "integrity": "sha1-/cVlxX3ZFyWjFns2C/JXjTw7VI0=" + }, + "pako": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", + "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==" + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "requires": { + "no-case": "^2.2.0" + } + }, + "parse-asn1": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz", + "integrity": "sha512-VrPoetlz7B/FqjBLD2f5wBVZvsZVLnRUrxVLfRYhGXCODa/NWE4p3Wp+6+aV3ZPL3KM7/OZmxDIwwijD7yuucg==", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-node-version": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", + "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==" + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "optional": true + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "^2.1.0" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=" + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=" + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=" + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "postcss-calc": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "requires": { + "postcss": "^5.0.2", + "postcss-message-helpers": "^2.0.0", + "reduce-css-calc": "^1.2.6" + } + }, + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "requires": { + "colormin": "^1.0.5", + "postcss": "^5.0.13", + "postcss-value-parser": "^3.2.3" + } + }, + "postcss-convert-values": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", + "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "requires": { + "postcss": "^5.0.11", + "postcss-value-parser": "^3.1.2" + } + }, + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", + "requires": { + "postcss": "^5.0.14" + } + }, + "postcss-discard-duplicates": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", + "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "requires": { + "postcss": "^5.0.14" + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "requires": { + "postcss": "^5.0.16" + } + }, + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "requires": { + "postcss": "^5.0.14", + "uniqs": "^2.0.0" + } + }, + "postcss-filter-plugins": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", + "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.10", + "postcss-value-parser": "^3.1.1" + } + }, + "postcss-merge-longhand": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", + "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-merge-rules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", + "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", + "requires": { + "browserslist": "^1.5.2", + "caniuse-api": "^1.5.2", + "postcss": "^5.0.4", + "postcss-selector-parser": "^2.2.2", + "vendors": "^1.0.0" + } + }, + "postcss-message-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=" + }, + "postcss-minify-font-values": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "requires": { + "object-assign": "^4.0.1", + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "requires": { + "postcss": "^5.0.12", + "postcss-value-parser": "^3.3.0" + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "requires": { + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.2", + "postcss-value-parser": "^3.0.2", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", + "requires": { + "alphanum-sort": "^1.0.2", + "has": "^1.0.1", + "postcss": "^5.0.14", + "postcss-selector-parser": "^2.0.0" + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", + "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", + "requires": { + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + } + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + } + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + } + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + } + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", + "requires": { + "postcss": "^5.0.5" + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^1.4.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3" + } + }, + "postcss-ordered-values": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", + "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", + "requires": { + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.1" + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", + "requires": { + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.8", + "postcss-value-parser": "^3.0.1" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-svgo": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "requires": { + "is-svg": "^2.0.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3", + "svgo": "^0.7.0" + } + }, + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "requires": { + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "postcss-zindex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" + }, + "primeng": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/primeng/-/primeng-7.0.5.tgz", + "integrity": "sha512-CVc6XxMZEsuCKXkyLUI/bRKX+spSBnEwqOFnAeXfSjIq0Uok51Dnrn8yNHyAWU2YRx93h7NWgxBtSXWVddEwqg==" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "ramda": { + "version": "0.24.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz", + "integrity": "sha1-w7d1UZfzW43DUCIoJixMkd22uFc=", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "raw-loader": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "requires": { + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + } + } + }, + "reduce-function-call": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", + "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", + "requires": { + "balanced-match": "^0.4.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + } + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "~0.5.0" + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-progress": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.1.tgz", + "integrity": "sha1-ByHBBdipasayzossia4tXs/Pazo=", + "dev": true, + "requires": { + "throttleit": "~0.0.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "run-sequence": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.1.tgz", + "integrity": "sha512-qkzZnQWMZjcKbh3CNly2srtrkaO/2H/SI5f2eliMCapdRD3UhMrwjfOAZJAnZ2H8Ju4aBzFZkBGXUqFs9V0yxw==", + "requires": { + "chalk": "^1.1.3", + "fancy-log": "^1.3.2", + "plugin-error": "^0.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" + }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "sass-loader": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", + "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "requires": { + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0", + "semver": "^5.5.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=" + }, + "serialize-javascript": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", + "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==" + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "sourcemap-codec": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz", + "integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==" + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "requires": { + "readable-stream": "^2.0.1" + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==" + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "stream-to-observable": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz", + "integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4=", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "style-loader": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz", + "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==", + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^0.4.5" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", + "requires": { + "coa": "~1.0.1", + "colors": "~1.1.2", + "csso": "~2.3.1", + "js-yaml": "~3.7.0", + "mkdirp": "~0.5.1", + "sax": "~1.2.1", + "whet.extend": "~0.9.9" + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + }, + "tapable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", + "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "terser": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.14.1.tgz", + "integrity": "sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw==", + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1", + "source-map-support": "~0.5.6" + } + }, + "terser-webpack-plugin": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz", + "integrity": "sha512-GGSt+gbT0oKcMDmPx4SRSfJPE1XaN3kQRWG4ghxKQw9cn5G9x6aCKSsgYdvyM0na9NJ4Drv0RG6jbBByZ5CMjw==", + "requires": { + "cacache": "^11.0.2", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "terser": "^3.8.1", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + }, + "dependencies": { + "cacache": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "requires": { + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + } + } + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "requires": { + "os-homedir": "^1.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "to-string-loader": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/to-string-loader/-/to-string-loader-1.1.5.tgz", + "integrity": "sha1-e3qheJG3u0lHp6Eb+wO1/enG5pU=", + "requires": { + "loader-utils": "^0.2.16" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "requires": { + "glob": "^7.1.2" + } + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tslint": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz", + "integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==", + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + } + }, + "tslint-language-service": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/tslint-language-service/-/tslint-language-service-0.9.9.tgz", + "integrity": "sha1-9UbcOEg5eeb7PPpZWErYUls61No=", + "requires": { + "mock-require": "^2.0.2" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typescript": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", + "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==" + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" + } + } + }, + "uglifyjs-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "schema-utils": "^0.4.5", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "uglify-es": "^3.3.4", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==" + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "requires": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "v8-compile-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", + "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "requires": { + "user-home": "^1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "vendors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", + "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "requires": { + "natives": "^1.1.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "requires": { + "indexof": "0.0.1" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "webpack": { + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.0.tgz", + "integrity": "sha512-pxdGG0keDBtamE1mNvT5zyBdx+7wkh6mh7uzMOo/uRQ/fhsdj5FXkh/j5mapzs060forql1oXqXN9HJGju+y7w==", + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/wasm-edit": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "acorn": "^6.0.5", + "acorn-dynamic-import": "^4.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^0.4.4", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "webpack-bundle-analyzer": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz", + "integrity": "sha512-rwxyfecTAxoarCC9VlHlIpfQCmmJ/qWD5bpbjkof+7HrNhTNZIwZITxN6CdlYL2axGmwNUQ+tFgcSOiNXMf/sQ==", + "requires": { + "acorn": "^5.3.0", + "bfj-node4": "^5.2.0", + "chalk": "^2.3.0", + "commander": "^2.13.0", + "ejs": "^2.5.7", + "express": "^4.16.2", + "filesize": "^3.5.11", + "gzip-size": "^4.1.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "opener": "^1.4.3", + "ws": "^4.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + } + } + }, + "webpack-cli": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.2.1.tgz", + "integrity": "sha512-jeJveHwz/vwpJ3B8bxEL5a/rVKIpRNJDsKggfKnxuYeohNDW4Y/wB9N/XHJA093qZyS0r6mYL+/crLsIol4WKA==", + "requires": { + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.0", + "findup-sync": "^2.0.0", + "global-modules": "^1.0.0", + "global-modules-path": "^2.3.0", + "import-local": "^2.0.0", + "interpret": "^1.1.0", + "lightercollective": "^0.1.0", + "loader-utils": "^1.1.0", + "supports-color": "^5.5.0", + "v8-compile-cache": "^2.0.2", + "yargs": "^12.0.4" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", + "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.5.1.tgz", + "integrity": "sha512-4dwCh/AyMOYAybggUr8fiCkRnjVDp+Cqlr9c+aaNB3GJYgRGYQWJ1YX/WAKUNA9dPNHZ6QSN2lYDKqjKSI8Vqw==", + "requires": { + "memory-fs": "~0.4.1", + "mime": "^2.3.1", + "range-parser": "^1.0.3", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-hot-middleware": { + "version": "2.24.3", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.24.3.tgz", + "integrity": "sha512-pPlmcdoR2Fn6UhYjAhp1g/IJy1Yc9hD+T6O9mjRcWV2pFbBjIFoJXhP0CoD0xPOhWJuWXuZXGBga9ybbOdzXpg==", + "requires": { + "ansi-html": "0.0.7", + "html-entities": "^1.2.0", + "querystring": "^0.2.0", + "strip-ansi": "^3.0.0" + } + }, + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } + }, + "webpack-merge": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", + "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", + "requires": { + "lodash": "^4.17.5" + } + }, + "webpack-node-externals": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz", + "integrity": "sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg==" + }, + "webpack-sources": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz", + "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", + "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0" + } + }, + "xhr2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", + "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "^4.1.0" + } + }, + "yauzl": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", + "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.0.1" + } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=" + }, + "zone.js": { + "version": "0.8.29", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.29.tgz", + "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" + } + } +} From 1ad799d6bf3142cb9823623ce7f1407f8865ca7a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 28 Jan 2019 19:57:39 +0000 Subject: [PATCH 252/325] removed invalid char !wip --- src/Ombi/StartupExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index 681148a07..a3b4f1dde 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -86,7 +86,7 @@ namespace Ombi } - c.OperationFilter();^ + c.OperationFilter(); c.DescribeAllParametersInCamelCase(); }); } From 9aee688d217b54add79f54c0fb71b1dca75ea40c Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 29 Jan 2019 20:09:01 +0000 Subject: [PATCH 253/325] turn off demo mode !wip --- src/Ombi/appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/appsettings.json b/src/Ombi/appsettings.json index 7babcdbdd..8a9e38008 100644 --- a/src/Ombi/appsettings.json +++ b/src/Ombi/appsettings.json @@ -50,7 +50,7 @@ }, // Please ignore the below "Demo": { - "Enabled": true, + "Enabled": false, "Movies": [ //https://en.wikipedia.org/wiki/List_of_films_in_the_public_domain_in_the_United_States 130816, From 5b46c7bd25aca84226a4b4a7e36033dcb32884f4 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 30 Jan 2019 19:21:58 +0000 Subject: [PATCH 254/325] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index d9791a032..aecd9903f 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -48,7 +48,7 @@ "Requests": "Solicitações", "UserManagement": "Gerenciador de Usuário", "Issues": "Problemas", - "Vote": "Vote", + "Vote": "Votar", "Donate": "Fazer uma doação!", "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", "DonateTooltip": "É assim que eu convenço a minha mulher a deixar-me passar o meu tempo livre desenvolvendo Ombi;)", @@ -74,7 +74,7 @@ "ViewOnEmby": "Assistir no Emby", "RequestAdded": "Pedido de {{title}} foi adicionado com sucesso", "Similar": "Semelhante", - "Refine": "Refine", + "Refine": "Filtro", "Movies": { "PopularMovies": "Filmes populares", "UpcomingMovies": "Próximos filmes", @@ -137,11 +137,11 @@ "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Quota": "{{remaining}}/{{total}} solicitações restantes", + "NextDays": "Outro pedido será adicionado em {{time}} dias", + "NextHours": "Outro pedido será adicionado em {{time}} horas", + "NextMinutes": "Outro pedido será adicionado em {{time}} minutos", + "NextMinute": "Outro pedido será adicionado em {{time}} minuto" } }, "Issues": { @@ -171,15 +171,15 @@ "PendingApproval": "Aprovação Pendente" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "Tv: {{remaining}}/{{total}} restantes", + "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes", + "MusicRemaining": "Música: {{remaining}}/{{total}} restantes", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Filme: {{date}}", + "MusicDue": "Música: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Votado", + "VotesTab": "Votos necessários" } } From a9511f2bb04283cff408e37fbaa4568949b8ba4e Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 3 Feb 2019 19:31:14 +0000 Subject: [PATCH 255/325] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 947041a93..a0a2b1b37 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -126,7 +126,7 @@ "GridTitle": "Título", "AirDate": "Fecha de estreno", "GridStatus": "Estado", - "ReportIssue": "Informar de un problema/error", + "ReportIssue": "Informar de un Problema", "Filter": "Filtrar", "Sort": "Ordenar", "SeasonNumberHeading": "Temporada: {seasonNumber}", From d2aedfa726856bf91db4ae7b47c44990226d41a0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 6 Feb 2019 16:23:17 +0000 Subject: [PATCH 256/325] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index ce82bc9c1..fdf70aad1 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -13,7 +13,7 @@ "ContinueButton": "Doorgaan", "Available": "Beschikbaar", "PartiallyAvailable": "Deels Beschikbaar", - "Monitored": "Gecontroleerd", + "Monitored": "Onder toezicht", "NotAvailable": "Niet Beschikbaar", "ProcessingRequest": "Verzoek wordt verwerkt", "PendingApproval": "Wacht op goedkeuring", From 42eae458d866d9c6b3483c052cc33112c6d759d5 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 8 Feb 2019 13:47:22 +0000 Subject: [PATCH 257/325] Fixed #2786 --- src/Ombi.Core/Engine/TvSearchEngine.cs | 4 +- .../Rule/Rules/Search/ExistingRule.cs | 7 ++-- .../Entities/Requests/SeasonRequests.cs | 4 +- .../ClientApp/app/interfaces/IRequestModel.ts | 1 + .../search/seriesinformation.component.html | 5 ++- .../app/search/seriesinformation.component.ts | 1 + src/Ombi/package-lock.json | 41 ++++++++++++++----- 7 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index b2e07f05e..3a1fead18 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -99,7 +99,7 @@ namespace Ombi.Core.Engine { Url = e.url, Title = e.name, - AirDate = DateTime.Parse(e.airstamp ?? DateTime.MinValue.ToString()), + AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, }); @@ -112,7 +112,7 @@ namespace Ombi.Core.Engine { Url = e.url, Title = e.name, - AirDate = DateTime.Parse(e.airstamp ?? DateTime.MinValue.ToString()), + AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, }); } diff --git a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs index 965fcdfaf..2d4482ba9 100644 --- a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Models.Search; @@ -87,11 +88,11 @@ namespace Ombi.Core.Rule.Rules.Search } } - if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.All(e => e.Available))) + if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.All(e => e.Available && e.AirDate > DateTime.MinValue))) { request.FullyAvailable = true; } - if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.Available))) + if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.Available && e.AirDate > DateTime.MinValue))) { request.PartlyAvailable = true; } diff --git a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs index 521cf5b94..6abaa4de3 100644 --- a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs +++ b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Globalization; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; @@ -27,9 +28,10 @@ namespace Ombi.Store.Repository.Requests public bool Approved { get; set; } public bool Requested { get; set; } - public int SeasonId { get; set; } [ForeignKey(nameof(SeasonId))] public SeasonRequests Season { get; set; } + + [NotMapped] public string AirDateDisplay => AirDate == DateTime.MinValue ? "Unknown" : AirDate.ToString(CultureInfo.InvariantCulture); } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index e9b7c53f7..f187db0b8 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -146,6 +146,7 @@ export interface IEpisodesRequests { episodeNumber: number; title: string; airDate: Date; + airDateDisplay: string; url: string; available: boolean; requested: boolean; diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.html b/src/Ombi/ClientApp/app/search/seriesinformation.component.html index 2ae6408c7..12059e417 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.html +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.html @@ -42,8 +42,11 @@
- + From be6d59f768b6f6b609efe905c4a3ceeb7663d41a Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 11 Feb 2019 20:42:47 +0000 Subject: [PATCH 262/325] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 387dcac9d..592d69f9c 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -1,6 +1,6 @@ { "Login": { - "SignInButton": "Einloggen", + "SignInButton": "Anmelden", "UsernamePlaceholder": "Benutzername", "PasswordPlaceholder": "Passwort", "RememberMe": "Eingeloggt bleiben", @@ -137,7 +137,7 @@ "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", + "Quota": "{{remaining}}/{{total}} Anfragen verbleiben", "NextDays": "Another request will be added in {{time}} days", "NextHours": "Another request will be added in {{time}} hours", "NextMinutes": "Another request will be added in {{time}} minutes", @@ -171,9 +171,9 @@ "PendingApproval": "Genehmigung ausstehend" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "TV: {{remaining}}/{{total}} verbleibend", + "MovieRemaining": "Filme: {{remaining}}/{{total}} verbleibend", + "MusicRemaining": "Musik: {{remaining}}/{{total}} verbleibend", "TvDue": "TV: {{date}}", "MovieDue": "Film: {{date}}", "MusicDue": "Musik: {{date}}" From 3b3cb52dab8b1586e2b3c55549467394b3cda425 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 12 Feb 2019 02:21:18 +0000 Subject: [PATCH 263/325] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index f7653c2bb..4f4910d8a 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -12,8 +12,8 @@ "Common": { "ContinueButton": "Dalej", "Available": "Dostępny", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", + "PartiallyAvailable": "Częściowo dostępne", + "Monitored": "Monitorowane", "NotAvailable": "Niedostępny", "ProcessingRequest": "Przetwarzanie zgłoszenia", "PendingApproval": "Oczekujące na zatwierdzenie", @@ -48,7 +48,7 @@ "Requests": "Zgłoszenia", "UserManagement": "Zarządzanie użytkownikami", "Issues": "Problemy", - "Vote": "Vote", + "Vote": "Głosowania", "Donate": "Wesprzyj!", "DonateLibraryMaintainer": "Wesprzyj właściciela biblioteki", "DonateTooltip": "W ten sposób przekonuję moją żonę by spędzać mój wolny czas rozwijając Ombi ;)", @@ -65,7 +65,7 @@ "Paragraph": "Chcesz obejrzeć coś, co nie jest obecnie dostępne? Żaden problem, po prostu wyszukaj poniżej i dodaj zgłoszenie!", "MoviesTab": "Filmy", "TvTab": "Seriale", - "MusicTab": "Music", + "MusicTab": "Muzyka", "Suggestions": "Sugestie", "NoResults": "Niestety nic nie znaleziono!", "DigitalDate": "Wydanie cyfrowe: {{date}}", @@ -74,7 +74,7 @@ "ViewOnEmby": "Obejrzyj na Emby", "RequestAdded": "Zgłoszenie dla {{title}} zostało dodane", "Similar": "Podobne", - "Refine": "Refine", + "Refine": "Zawęź", "Movies": { "PopularMovies": "Popularne filmy", "UpcomingMovies": "Wkrótce w kinach", @@ -104,13 +104,13 @@ "Paragraph": "Poniżej są twoje i wszystkie inne zgłoszenia, a także ich status akceptacji i pobierania.", "MoviesTab": "Filmy", "TvTab": "Seriale", - "MusicTab": "Music", + "MusicTab": "Muzyka", "RequestedBy": "Zgłoszone przez:", "Status": "Stan:", "RequestStatus": "Stan zgłoszenia:", "Denied": "Odrzucono:", "TheatricalRelease": "Premiera kinowa: {{date}}", - "ReleaseDate": "Released: {{date}}", + "ReleaseDate": "Wydany: {{date}}", "TheatricalReleaseSort": "Premiera kinowa", "DigitalRelease": "Wydanie cyfrowe: {{date}}", "RequestDate": "Data zgłoszenia:", @@ -137,8 +137,8 @@ "SortStatusAsc": "Stan ▲", "SortStatusDesc": "Stan ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", + "Quota": "{{remaining}}/{{total}} pozostałych żądań", + "NextDays": "Kolejne żądanie zostanie dodane za {{time}} dni", "NextHours": "Another request will be added in {{time}} hours", "NextMinutes": "Another request will be added in {{time}} minutes", "NextMinute": "Another request will be added in {{time}} minute" From 6f0b779bf8a200a303e6de2c94625548116e5d21 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 12 Feb 2019 02:31:13 +0000 Subject: [PATCH 264/325] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 4f4910d8a..b24508b54 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -11,10 +11,10 @@ }, "Common": { "ContinueButton": "Dalej", - "Available": "Dostępny", + "Available": "Dostępne", "PartiallyAvailable": "Częściowo dostępne", "Monitored": "Monitorowane", - "NotAvailable": "Niedostępny", + "NotAvailable": "Niedostępne", "ProcessingRequest": "Przetwarzanie zgłoszenia", "PendingApproval": "Oczekujące na zatwierdzenie", "RequestDenied": "Zgłoszenie odrzucone", @@ -139,9 +139,9 @@ "Remaining": { "Quota": "{{remaining}}/{{total}} pozostałych żądań", "NextDays": "Kolejne żądanie zostanie dodane za {{time}} dni", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "NextHours": "Kolejne żądanie zostanie dodane za {{time}} godzin(y)", + "NextMinutes": "Kolejne żądanie zostanie dodane za {{time}} minut(y)", + "NextMinute": "Kolejne żądanie zostanie dodane za {{time}} minut(y)" } }, "Issues": { @@ -171,15 +171,15 @@ "PendingApproval": "Oczekujące na zatwierdzenie" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "TV: pozostało {{remaining}}/{{total}}", + "MovieRemaining": "Filmy: pozostało {{remaining}}/{{total}}", + "MusicRemaining": "Muzyka: pozostało {{remaining}}/{{total}}", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film: {{date}}", + "MusicDue": "Muzyka: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Zagłosowano", + "VotesTab": "Potrzebne głosy" } } From d916c993fb17f6d1ed2fa341f229d108fdc96239 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 12 Feb 2019 02:41:19 +0000 Subject: [PATCH 265/325] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index b24508b54..58606bb09 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -23,7 +23,7 @@ "Request": "Zgłoszenie", "Denied": "Odrzucone", "Approve": "Zatwierdź", - "PartlyAvailable": "Dostępne częściowo", + "PartlyAvailable": "Częściowo dostępne", "Errors": { "Validation": "Sprawdź wprowadzone dane" } @@ -34,13 +34,13 @@ }, "LandingPage": { "OnlineHeading": "Dostępny", - "OnlineParagraph": "Serwer mediów jest dostępny", - "PartiallyOnlineHeading": "Dostępny częściowo", - "PartiallyOnlineParagraph": "Serwer mediów jest dostępny częściowo.", - "MultipleServersUnavailable": "{{serversUnavailable}} serwerów spośród {{totalServers}} jest niedostępnych.", - "SingleServerUnavailable": "Jeden serwer spośród {{totalServers}} jest niedostępny.", - "OfflineHeading": "Niedostępny", - "OfflineParagraph": "Serwer mediów jest niedostępny.", + "OnlineParagraph": "Serwer multimediów jest aktualnie online", + "PartiallyOnlineHeading": "Częściowo online", + "PartiallyOnlineParagraph": "Serwer multimediów jest częściowo online.", + "MultipleServersUnavailable": "{{serversUnavailable}} serwerów spośród {{totalServers}} jest offline.", + "SingleServerUnavailable": "{{serversUnavailable}} serwer z {{totalServers}} jest w offline.", + "OfflineHeading": "Aktualnie offline", + "OfflineParagraph": "Serwer multimediów jest aktualnie offline.", "CheckPageForUpdates": "Tutaj znajdziesz aktualizacje dotyczące tej strony." }, "NavigationBar": { @@ -137,7 +137,7 @@ "SortStatusAsc": "Stan ▲", "SortStatusDesc": "Stan ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} pozostałych żądań", + "Quota": "{{remaining}}/{{total}} pozostałych zgłoszeń", "NextDays": "Kolejne żądanie zostanie dodane za {{time}} dni", "NextHours": "Kolejne żądanie zostanie dodane za {{time}} godzin(y)", "NextMinutes": "Kolejne żądanie zostanie dodane za {{time}} minut(y)", From 9ec6d98f2863eea150d5f9e63b65aecf068530fb Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 12 Feb 2019 02:51:11 +0000 Subject: [PATCH 266/325] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 58606bb09..ddd3ed24d 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -103,11 +103,11 @@ "Title": "Zgłoszenia", "Paragraph": "Poniżej są twoje i wszystkie inne zgłoszenia, a także ich status akceptacji i pobierania.", "MoviesTab": "Filmy", - "TvTab": "Seriale", + "TvTab": "Programy TV", "MusicTab": "Muzyka", "RequestedBy": "Zgłoszone przez:", - "Status": "Stan:", - "RequestStatus": "Stan zgłoszenia:", + "Status": "Status:", + "RequestStatus": "Status zgłoszenia:", "Denied": "Odrzucono:", "TheatricalRelease": "Premiera kinowa: {{date}}", "ReleaseDate": "Wydany: {{date}}", @@ -125,7 +125,7 @@ "Season": "Sezon:", "GridTitle": "Tytuł", "AirDate": "Data emisji", - "GridStatus": "Stan", + "GridStatus": "Status", "ReportIssue": "Zgłoś problem", "Filter": "Filtr", "Sort": "Sortowanie", @@ -134,14 +134,14 @@ "SortTitleDesc": "Tytuł ▼", "SortRequestDateAsc": "Data zgłoszenia ▲", "SortRequestDateDesc": "Data zgłoszenia ▼", - "SortStatusAsc": "Stan ▲", - "SortStatusDesc": "Stan ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", "Remaining": { "Quota": "{{remaining}}/{{total}} pozostałych zgłoszeń", - "NextDays": "Kolejne żądanie zostanie dodane za {{time}} dni", - "NextHours": "Kolejne żądanie zostanie dodane za {{time}} godzin(y)", - "NextMinutes": "Kolejne żądanie zostanie dodane za {{time}} minut(y)", - "NextMinute": "Kolejne żądanie zostanie dodane za {{time}} minut(y)" + "NextDays": "Kolejne zgłoszenie zostanie dodane za {{time}} dni", + "NextHours": "Kolejne zgłoszenie zostanie dodane za {{time}} godzin(y)", + "NextMinutes": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)", + "NextMinute": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)" } }, "Issues": { @@ -166,7 +166,7 @@ "Filter": { "ClearFilter": "Wyczyść fltr", "FilterHeaderAvailability": "Dostępność", - "FilterHeaderRequestStatus": "Stan", + "FilterHeaderRequestStatus": "Status", "Approved": "Zatwierdzone", "PendingApproval": "Oczekujące na zatwierdzenie" }, From e83a8d045d8fefabd444444de2fdeb2421552f4a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Feb 2019 21:10:54 +0000 Subject: [PATCH 267/325] Fixed build !wip --- src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index d1dc01d8c..28155cf25 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -62,7 +62,7 @@ namespace Ombi.Schedule.Jobs.Ombi var embySettings = await _embySettings.GetSettingsAsync(); if (embySettings.Enable) { - await StartEmby(); + await StartEmby(embySettings); } } catch (Exception e) @@ -127,9 +127,9 @@ namespace Ombi.Schedule.Jobs.Ombi await StartPlexTv(allTv); } - private async Task StartEmby() + private async Task StartEmby(EmbySettings s) { - await StartEmbyMovies(); + await StartEmbyMovies(s); await StartEmbyTv(); } From 5b1f326854babde643013bcfcbc1b4556460c15d Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Feb 2019 21:41:39 +0000 Subject: [PATCH 268/325] Fixed #2802 the issue where "Issues" were not being deleted correctly. --- src/Ombi.Core/Senders/MovieSender.cs | 3 +-- src/Ombi.Core/Senders/TvSender.cs | 13 ++++--------- .../Jobs/Ombi/Interfaces/IssuesPurge.cs | 4 ++-- src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs | 10 +++++----- src/Ombi/Controllers/IssuesController.cs | 5 +++++ 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index 9124eb9c9..567df43b5 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -49,7 +49,6 @@ namespace Ombi.Core.Senders { try { - var cpSettings = await CouchPotatoSettings.GetSettingsAsync(); //var watcherSettings = await WatcherSettings.GetSettingsAsync(); var radarrSettings = await RadarrSettings.GetSettingsAsync(); @@ -76,7 +75,7 @@ namespace Ombi.Core.Senders } catch (Exception e) { - Log.LogError(e, "Error when seing movie to DVR app, added to the request queue"); + Log.LogError(e, "Error when sending movie to DVR app, added to the request queue"); // Check if already in request quee var existingQueue = await _requestQueuRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index f0784a4ca..3edc34e1b 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -57,7 +57,7 @@ namespace Ombi.Core.Senders var sonarr = await SonarrSettings.GetSettingsAsync(); if (sonarr.Enabled) { - var result = await SendToSonarr(model); + var result = await SendToSonarr(model, sonarr); if (result != null) { return new SenderResult @@ -109,7 +109,7 @@ namespace Ombi.Core.Senders catch (Exception e) { Logger.LogError(e, "Exception thrown when sending a movie to DVR app, added to the request queue"); - // Check if already in request quee + // Check if already in request queue var existingQueue = await _requestQueueRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); if (existingQueue != null) { @@ -134,7 +134,7 @@ namespace Ombi.Core.Senders return new SenderResult { Success = false, - Message = "Something wen't wrong!" + Message = "Something went wrong!" }; } @@ -150,13 +150,8 @@ namespace Ombi.Core.Senders /// /// /// - public async Task SendToSonarr(ChildRequests model) + public async Task SendToSonarr(ChildRequests model, SonarrSettings s) { - var s = await SonarrSettings.GetSettingsAsync(); - if (!s.Enabled) - { - return null; - } if (string.IsNullOrEmpty(s.ApiKey)) { return null; diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs index 92ca31071..077fcb7e2 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs @@ -28,9 +28,9 @@ namespace Ombi.Schedule.Jobs.Ombi return; } - var now = DateTime.Now.AddDays(-settings.DaysAfterResolvedToDelete).Date; + var now = DateTime.Now.AddDays(settings.DaysAfterResolvedToDelete).Date; var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved); - var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date <= now); + var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date >= now); foreach (var d in toDelete) { diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 28155cf25..c9ba5c6b3 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -58,7 +58,7 @@ namespace Ombi.Schedule.Jobs.Ombi { await StartPlex(); } - + var embySettings = await _embySettings.GetSettingsAsync(); if (embySettings.Enable) { @@ -162,7 +162,7 @@ namespace Ombi.Schedule.Jobs.Ombi _plexRepo.UpdateWithoutSave(show); } tvCount++; - if (tvCount >= 20) + if (tvCount >= 75) { await _plexRepo.SaveChangesAsync(); tvCount = 0; @@ -202,7 +202,7 @@ namespace Ombi.Schedule.Jobs.Ombi _embyRepo.UpdateWithoutSave(show); } tvCount++; - if (tvCount >= 20) + if (tvCount >= 75) { await _embyRepo.SaveChangesAsync(); tvCount = 0; @@ -233,7 +233,7 @@ namespace Ombi.Schedule.Jobs.Ombi _plexRepo.UpdateWithoutSave(movie); } movieCount++; - if (movieCount >= 20) + if (movieCount >= 75) { await _plexRepo.SaveChangesAsync(); movieCount = 0; @@ -292,7 +292,7 @@ namespace Ombi.Schedule.Jobs.Ombi _embyRepo.UpdateWithoutSave(movie); } movieCount++; - if (movieCount >= 20) + if (movieCount >= 75) { await _embyRepo.SaveChangesAsync(); movieCount = 0; diff --git a/src/Ombi/Controllers/IssuesController.cs b/src/Ombi/Controllers/IssuesController.cs index 1a5af5446..0ac4d77bb 100644 --- a/src/Ombi/Controllers/IssuesController.cs +++ b/src/Ombi/Controllers/IssuesController.cs @@ -267,6 +267,11 @@ namespace Ombi.Controllers } issue.Status = model.Status; + + if (model.Status == IssueStatus.Resolved) + { + issue.ResovledDate = DateTime.UtcNow; + } await _issues.SaveChangesAsync(); if (issue.Status == IssueStatus.Resolved) From 8ed0146e09bd490ae811a4c2d2eff7cc72b9a289 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Feb 2019 21:42:47 +0000 Subject: [PATCH 269/325] !wip --- src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs index 077fcb7e2..5af4b565d 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs @@ -28,9 +28,9 @@ namespace Ombi.Schedule.Jobs.Ombi return; } - var now = DateTime.Now.AddDays(settings.DaysAfterResolvedToDelete).Date; + var deletionDate = DateTime.Now.AddDays(settings.DaysAfterResolvedToDelete).Date; var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved); - var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date >= now); + var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date >= deletionDate); foreach (var d in toDelete) { From 4a405db1817f943647d2bac49363dcf56cd539e0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 15 Feb 2019 17:38:22 +0000 Subject: [PATCH 270/325] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 4f7635742..f11ed29c4 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -37,7 +37,7 @@ "OnlineParagraph": "El servidor de medios esta en línea", "PartiallyOnlineHeading": "Parcialmente en línea", "PartiallyOnlineParagraph": "El servidor de medios está parcialmente en línea.", - "MultipleServersUnavailable": "{{serversUnavailable}} de {{totalServers}} servidores están fuera de línea.", + "MultipleServersUnavailable": "Hay {{serversUnavailable}} de {{totalServers}} servidores fuera de línea.", "SingleServerUnavailable": "Hay {{serversUnavailable}} de {{totalServers}} servidores fuera de línea.", "OfflineHeading": "Fuera de línea", "OfflineParagraph": "El servidor de medios está fuera de línea.", @@ -55,7 +55,7 @@ "UpdateAvailableTooltip": "¡Actualización disponible!", "Settings": "Ajustes", "Welcome": "Bienvenido {{username}}", - "UpdateDetails": "Detalles de la actualización", + "UpdateDetails": "Editar cuenta usuario", "Logout": "Cerrar sesión", "OpenMobileApp": "Abrir aplicación móvil", "RecentlyAdded": "Agregado recientemente" From e16c1b6f8a49d37d3975a442aa08449d8953ba95 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 15 Feb 2019 17:41:57 +0000 Subject: [PATCH 271/325] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index f11ed29c4..b449e4aa6 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -51,7 +51,7 @@ "Vote": "Votar", "Donate": "¡Donar!", "DonateLibraryMaintainer": "Donar al mantenedor de la biblioteca", - "DonateTooltip": "Para que mi esposa me deje desarrollar Ombi ;)", + "DonateTooltip": "Así es como convenzo a mi esposa para que me deje pasar mi tiempo libre desarrollando ombi;)", "UpdateAvailableTooltip": "¡Actualización disponible!", "Settings": "Ajustes", "Welcome": "Bienvenido {{username}}", @@ -74,7 +74,7 @@ "ViewOnEmby": "Ver en Emby", "RequestAdded": "La solicitud de {{title}} se ha agregado con éxito", "Similar": "Similar", - "Refine": "Refinar", + "Refine": "Filtros", "Movies": { "PopularMovies": "Películas populares", "UpcomingMovies": "Próximas películas", From d03cf62983af3232652bc536b9105885d1b214c0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 15 Feb 2019 18:01:50 +0000 Subject: [PATCH 272/325] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index b449e4aa6..d510600ad 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -89,7 +89,7 @@ "MostWatched": "Más visto", "MostAnticipated": "Más Anticipado", "Results": "Resultados", - "AirDate": "Fecha del Aire:", + "AirDate": "Fecha de emisión:", "AllSeasons": "Todas las temporadas", "FirstSeason": "Primera temporada", "LatestSeason": "Última temporada", From bf94b3111ea4f214450b86a6a63741fad511415d Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 16 Feb 2019 22:10:22 +0000 Subject: [PATCH 273/325] Set the local domain if the Application URL is set for the HELO or EHLO commands. #2636 --- src/Ombi.Notifications/GenericEmailProvider.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi.Notifications/GenericEmailProvider.cs b/src/Ombi.Notifications/GenericEmailProvider.cs index d3f207234..916367e0a 100644 --- a/src/Ombi.Notifications/GenericEmailProvider.cs +++ b/src/Ombi.Notifications/GenericEmailProvider.cs @@ -5,6 +5,7 @@ using MailKit.Net.Smtp; using Microsoft.Extensions.Logging; using MimeKit; using Ombi.Core.Settings; +using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Notifications.Templates; using Ombi.Settings.Settings.Models; @@ -56,6 +57,11 @@ namespace Ombi.Notifications using (var client = new SmtpClient()) { + if (customization.ApplicationUrl.HasValue()) + { + client.LocalDomain = customization.ApplicationUrl; + } + if (settings.DisableCertificateChecking) { // Disable validation of the certificate associated with the SMTP service From b8b976cf2562918351aaeeac16997bdf32348df4 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 16 Feb 2019 22:20:46 +0000 Subject: [PATCH 274/325] Cannot create an issue comment with the API #2811 --- src/Ombi/Controllers/IssuesController.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/Controllers/IssuesController.cs b/src/Ombi/Controllers/IssuesController.cs index 0ac4d77bb..194ac971b 100644 --- a/src/Ombi/Controllers/IssuesController.cs +++ b/src/Ombi/Controllers/IssuesController.cs @@ -132,7 +132,7 @@ namespace Ombi.Controllers public async Task CreateIssue([FromBody]Issues i) { i.IssueCategory = null; - i.UserReportedId = (await _userManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name)).Id; + i.UserReportedId = (await _userManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase))).Id; await _issues.Add(i); var category = await _categories.GetAll().FirstOrDefaultAsync(x => i.IssueCategoryId == x.Id); if (category != null) @@ -199,7 +199,7 @@ namespace Ombi.Controllers [HttpPost("comments")] public async Task AddComment([FromBody] NewIssueCommentViewModel comment) { - var user = await _userManager.Users.Where(x => User.Identity.Name == x.UserName) + var user = await _userManager.Users.Where(x => User.Identity.Name.Equals(x.UserName, StringComparison.InvariantCultureIgnoreCase)) .FirstOrDefaultAsync(); var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == comment.IssueId); if (issue == null) @@ -258,7 +258,7 @@ namespace Ombi.Controllers [HttpPost("status")] public async Task UpdateStatus([FromBody] IssueStateViewModel model) { - var user = await _userManager.Users.Where(x => User.Identity.Name == x.UserName) + var user = await _userManager.Users.Where(x => User.Identity.Name.Equals(x.UserName, StringComparison.InvariantCultureIgnoreCase)) .FirstOrDefaultAsync(); var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == model.IssueId); if (issue == null) From 215663df1fcc880347292d79efcae9b7edb7272c Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 16 Feb 2019 22:25:03 +0000 Subject: [PATCH 275/325] Fixed #2810 --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 40 ++++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index ba4bd5c62..3374a7c7b 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -16,6 +16,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TvMaze; using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Notifications; using Ombi.Notifications.Models; @@ -36,7 +37,7 @@ namespace Ombi.Schedule.Jobs.Ombi ISettingsService emailSettings, INotificationTemplatesRepository templateRepo, UserManager um, ISettingsService newsletter, ILogger log, ILidarrApi lidarrApi, IRepository albumCache, ISettingsService lidarrSettings, - ISettingsService ombiSettings) + ISettingsService ombiSettings, ISettingsService plexSettings, ISettingsService embySettings) { _plex = plex; _emby = emby; @@ -57,6 +58,8 @@ namespace Ombi.Schedule.Jobs.Ombi _lidarrAlbumRepository = albumCache; _lidarrSettings = lidarrSettings; _ombiSettings = ombiSettings; + _plexSettings = plexSettings; + _embySettings = embySettings; _ombiSettings.ClearCache(); _lidarrSettings.ClearCache(); } @@ -77,6 +80,8 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly ILidarrApi _lidarrApi; private readonly IRepository _lidarrAlbumRepository; private readonly ISettingsService _lidarrSettings; + private readonly ISettingsService _plexSettings; + private readonly ISettingsService _embySettings; public async Task Start(NewsletterSettings settings, bool test) { @@ -132,6 +137,8 @@ namespace Ombi.Schedule.Jobs.Ombi _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); _log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count()); + var plexSettings = await _plexSettings.GetSettingsAsync(); + var embySettings = await _embySettings.GetSettingsAsync(); var body = string.Empty; if (test) { @@ -140,11 +147,11 @@ namespace Ombi.Schedule.Jobs.Ombi var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - body = await BuildHtml(plexm, embym, plext, embyt, lidarr, settings); + body = await BuildHtml(plexm, embym, plext, embyt, lidarr, settings, embySettings, plexSettings); } else { - body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings); + body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, plexSettings); if (body.IsNullOrEmpty()) { return; @@ -333,7 +340,8 @@ namespace Ombi.Schedule.Jobs.Ombi } private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, - HashSet plexEpisodes, HashSet embyEp, HashSet albums, NewsletterSettings settings) + HashSet plexEpisodes, HashSet embyEp, HashSet albums, NewsletterSettings settings, EmbySettings embySettings, + PlexSettings plexSettings) { var ombiSettings = await _ombiSettings.GetSettingsAsync(); var sb = new StringBuilder(); @@ -349,8 +357,16 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); @@ -367,8 +383,16 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); From da9c481bb40cd420b0758c4aec5e1a4abd1cda84 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 16 Feb 2019 22:39:00 +0000 Subject: [PATCH 276/325] Removed some areas where we clear out the cache. This should help with DB locking #2750 --- src/Ombi.Notifications/BaseNotification.cs | 4 ---- src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs | 1 - src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs | 1 - src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs | 2 -- src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs | 4 ---- src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs | 4 ---- src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs | 11 +++-------- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 5 ----- src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs | 6 ------ src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs | 2 -- src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs | 1 - src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs | 1 - src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs | 2 -- src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 1 - src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs | 1 - src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 1 - src/Ombi.Settings/Settings/SettingsService.cs | 2 +- src/Ombi/Controllers/External/RadarrController.cs | 1 - src/Ombi/Controllers/External/SonarrController.cs | 1 - 19 files changed, 4 insertions(+), 47 deletions(-) diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index 57eafedd9..001f68f45 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -26,8 +26,6 @@ namespace Ombi.Notifications MovieRepository = movie; TvRepository = tv; CustomizationSettings = customization; - Settings.ClearCache(); - CustomizationSettings.ClearCache(); RequestSubscription = sub; _log = log; AlbumRepository = album; @@ -55,14 +53,12 @@ namespace Ombi.Notifications public async Task NotifyAsync(NotificationOptions model) { - Settings.ClearCache(); var configuration = await GetConfiguration(); await NotifyAsync(model, configuration); } public async Task NotifyAsync(NotificationOptions model, Settings.Settings.Models.Settings settings) { - Settings.ClearCache(); if (settings == null) await NotifyAsync(model); var notificationSettings = (T)settings; diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 4972f940f..e22c0ca51 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -28,7 +28,6 @@ namespace Ombi.Schedule.Jobs.Emby _repo = repo; _episodeSync = epSync; _metadata = metadata; - _settings.ClearCache(); } private readonly ILogger _logger; diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index 2bb417d3d..962b08cda 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -49,7 +49,6 @@ namespace Ombi.Schedule.Jobs.Emby _settings = s; _repo = repo; _avaliabilityChecker = checker; - _settings.ClearCache(); } private readonly ISettingsService _settings; diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs index 2dadd4bd4..280a61ab4 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs @@ -50,8 +50,6 @@ namespace Ombi.Schedule.Jobs.Emby _log = log; _embySettings = embySettings; _userManagementSettings = ums; - _userManagementSettings.ClearCache(); - _embySettings.ClearCache(); } private readonly IEmbyApi _api; diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index d19fe561a..2a50b5b38 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -1,19 +1,16 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; using Ombi.Api.Lidarr; -using Ombi.Api.Radarr; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Context; using Ombi.Store.Entities; -using Serilog; using ILogger = Microsoft.Extensions.Logging.ILogger; namespace Ombi.Schedule.Jobs.Lidarr @@ -29,7 +26,6 @@ namespace Ombi.Schedule.Jobs.Lidarr _ctx = ctx; _job = job; _availability = availability; - _lidarrSettings.ClearCache(); } private readonly ISettingsService _lidarrSettings; diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs index 4117ee44a..e9a64f2a3 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs @@ -1,19 +1,16 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; using Ombi.Api.Lidarr; -using Ombi.Api.Radarr; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Context; using Ombi.Store.Entities; -using Serilog; using ILogger = Microsoft.Extensions.Logging.ILogger; namespace Ombi.Schedule.Jobs.Lidarr @@ -29,7 +26,6 @@ namespace Ombi.Schedule.Jobs.Lidarr _ctx = ctx; _job = background; _albumSync = album; - _lidarrSettings.ClearCache(); } private readonly ISettingsService _lidarrSettings; diff --git a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs index baa7fdcae..ed0bf227f 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs @@ -10,28 +10,23 @@ using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Store.Repository; -namespace Ombi.Schedule.Jobs.Plex +namespace Ombi.Schedule.Jobs.Ombi { public class MediaDatabaseRefresh : IMediaDatabaseRefresh { - public MediaDatabaseRefresh(ISettingsService s, ILogger log, IPlexApi plexApi, - IPlexContentRepository plexRepo, IPlexContentSync c, IEmbyContentRepository embyRepo, IEmbyContentSync embySync) + public MediaDatabaseRefresh(ISettingsService s, ILogger log, + IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo, IEmbyContentSync embySync) { _settings = s; _log = log; - _api = plexApi; _plexRepo = plexRepo; - _plexContentSync = c; _embyRepo = embyRepo; _embyContentSync = embySync; - _settings.ClearCache(); } private readonly ISettingsService _settings; private readonly ILogger _log; - private readonly IPlexApi _api; private readonly IPlexContentRepository _plexRepo; - private readonly IPlexContentSync _plexContentSync; private readonly IEmbyContentRepository _embyRepo; private readonly IEmbyContentSync _embyContentSync; diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 3374a7c7b..6c59f4c0f 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -50,9 +50,6 @@ namespace Ombi.Schedule.Jobs.Ombi _emailSettings = emailSettings; _newsletterSettings = newsletter; _userManager = um; - _emailSettings.ClearCache(); - _customizationSettings.ClearCache(); - _newsletterSettings.ClearCache(); _log = log; _lidarrApi = lidarrApi; _lidarrAlbumRepository = albumCache; @@ -60,8 +57,6 @@ namespace Ombi.Schedule.Jobs.Ombi _ombiSettings = ombiSettings; _plexSettings = plexSettings; _embySettings = embySettings; - _ombiSettings.ClearCache(); - _lidarrSettings.ClearCache(); } private readonly IPlexContentRepository _plex; diff --git a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs index 5ec8978b6..783fe5f9d 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs @@ -5,18 +5,13 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Net; -using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Hangfire; -using Hangfire.Console; using Hangfire.Server; using Microsoft.Extensions.Logging; - -using Ombi.Api.Service; -using Ombi.Api.Service.Models; using Ombi.Core.Processor; using Ombi.Core.Settings; using Ombi.Helpers; @@ -40,7 +35,6 @@ namespace Ombi.Schedule.Jobs.Ombi Settings = s; _processProvider = proc; _appConfig = appConfig; - Settings.ClearCache(); } private ILogger Logger { get; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs b/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs index e260ebed3..f98072e9e 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs @@ -20,8 +20,6 @@ namespace Ombi.Schedule.Jobs.Ombi _email = provider; _templates = template; _customizationSettings = c; - email.ClearCache(); - _customizationSettings.ClearCache(); } private readonly ISettingsService _emailSettings; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index c39b80c1f..964832b44 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -57,7 +57,6 @@ namespace Ombi.Schedule.Jobs.Plex EpisodeSync = epsiodeSync; Metadata = metadataRefresh; Checker = checker; - plex.ClearCache(); } private ISettingsService Plex { get; } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index 5652d126b..6ab5a5941 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -26,7 +26,6 @@ namespace Ombi.Schedule.Jobs.Plex _api = plexApi; _repo = repo; _availabilityChecker = a; - _settings.ClearCache(); } private readonly ISettingsService _settings; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs index 4f6bf2550..105e8876d 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs @@ -24,8 +24,6 @@ namespace Ombi.Schedule.Jobs.Plex _log = log; _plexSettings = plexSettings; _userManagementSettings = ums; - _userManagementSettings.ClearCache(); - _plexSettings.ClearCache(); } private readonly IPlexApi _api; diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 5c954def8..f61747ac6 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -22,7 +22,6 @@ namespace Ombi.Schedule.Jobs.Radarr RadarrApi = radarrApi; Logger = log; _ctx = ctx; - RadarrSettings.ClearCache(); } private ISettingsService RadarrSettings { get; } diff --git a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs index 92e0c2d55..2c8d03b1d 100644 --- a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs +++ b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs @@ -22,7 +22,6 @@ namespace Ombi.Schedule.Jobs.SickRage _api = api; _log = l; _ctx = ctx; - _settings.ClearCache(); } private readonly ISettingsService _settings; diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index e4c00c726..c77e23394 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -25,7 +25,6 @@ namespace Ombi.Schedule.Jobs.Sonarr _api = api; _log = l; _ctx = ctx; - _settings.ClearCache(); } private readonly ISettingsService _settings; diff --git a/src/Ombi.Settings/Settings/SettingsService.cs b/src/Ombi.Settings/Settings/SettingsService.cs index 3162c34c2..57ae482a2 100644 --- a/src/Ombi.Settings/Settings/SettingsService.cs +++ b/src/Ombi.Settings/Settings/SettingsService.cs @@ -61,7 +61,7 @@ namespace Ombi.Settings.Settings var model = obj; return model; - }, DateTime.Now.AddHours(2)); + }, DateTime.Now.AddHours(5)); } public bool SaveSettings(T model) diff --git a/src/Ombi/Controllers/External/RadarrController.cs b/src/Ombi/Controllers/External/RadarrController.cs index 623322704..b630244f6 100644 --- a/src/Ombi/Controllers/External/RadarrController.cs +++ b/src/Ombi/Controllers/External/RadarrController.cs @@ -23,7 +23,6 @@ namespace Ombi.Controllers.External RadarrApi = radarr; RadarrSettings = settings; Cache = mem; - RadarrSettings.ClearCache(); } private IRadarrApi RadarrApi { get; } diff --git a/src/Ombi/Controllers/External/SonarrController.cs b/src/Ombi/Controllers/External/SonarrController.cs index bc2534ab8..fd3e169bc 100644 --- a/src/Ombi/Controllers/External/SonarrController.cs +++ b/src/Ombi/Controllers/External/SonarrController.cs @@ -22,7 +22,6 @@ namespace Ombi.Controllers.External SonarrApi = sonarr; SonarrV3Api = sonarrv3; SonarrSettings = settings; - SonarrSettings.ClearCache(); } private ISonarrApi SonarrApi { get; } From d834b96b4b30e5042bd49da47f10c5fe3f0cdd2b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 16 Feb 2019 22:56:22 +0000 Subject: [PATCH 277/325] Small improvements to try and mitigate #2750 --- src/Ombi.Store/Context/OmbiContext.cs | 47 - .../20190216224539_Roles.Designer.cs | 1212 +++++++++++++++++ .../Migrations/20190216224539_Roles.cs | 32 + 3 files changed, 1244 insertions(+), 47 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20190216224539_Roles.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20190216224539_Roles.cs diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index a8e84c942..47b245603 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -87,53 +87,6 @@ namespace Ombi.Store.Context public void Seed() { - // VACUUM; - Database.ExecuteSqlCommand("VACUUM;"); - - // Make sure we have the roles - var newsletterRole = Roles.Where(x => x.Name == OmbiRoles.ReceivesNewsletter); - if (!newsletterRole.Any()) - { - Roles.Add(new IdentityRole(OmbiRoles.ReceivesNewsletter) - { - NormalizedName = OmbiRoles.ReceivesNewsletter.ToUpper() - }); - SaveChanges(); - } - var requestMusicRole = Roles.Where(x => x.Name == OmbiRoles.RequestMusic); - if (!requestMusicRole.Any()) - { - Roles.Add(new IdentityRole(OmbiRoles.RequestMusic) - { - NormalizedName = OmbiRoles.RequestMusic.ToUpper() - }); - Roles.Add(new IdentityRole(OmbiRoles.AutoApproveMusic) - { - NormalizedName = OmbiRoles.AutoApproveMusic.ToUpper() - }); - SaveChanges(); - } - - var manageOwnRequestsRole = Roles.Where(x => x.Name == OmbiRoles.ManageOwnRequests); - if (!manageOwnRequestsRole.Any()) - { - Roles.Add(new IdentityRole(OmbiRoles.ManageOwnRequests) - { - NormalizedName = OmbiRoles.ManageOwnRequests.ToUpper() - }); - SaveChanges(); - } - - var editCustomPage = Roles.Where(x => x.Name == OmbiRoles.EditCustomPage); - if (!editCustomPage.Any()) - { - Roles.Add(new IdentityRole(OmbiRoles.EditCustomPage) - { - NormalizedName = OmbiRoles.EditCustomPage.ToUpper() - }); - SaveChanges(); - } - // Make sure we have the API User var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); if (!apiUserExists) diff --git a/src/Ombi.Store/Migrations/20190216224539_Roles.Designer.cs b/src/Ombi.Store/Migrations/20190216224539_Roles.Designer.cs new file mode 100644 index 000000000..f0aeb88bc --- /dev/null +++ b/src/Ombi.Store/Migrations/20190216224539_Roles.Designer.cs @@ -0,0 +1,1212 @@ +// +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 +{ + [DbContext(typeof(OmbiContext))] + [Migration("20190216224539_Roles")] + partial class Roles + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/20190216224539_Roles.cs b/src/Ombi.Store/Migrations/20190216224539_Roles.cs new file mode 100644 index 000000000..9c2f91c12 --- /dev/null +++ b/src/Ombi.Store/Migrations/20190216224539_Roles.cs @@ -0,0 +1,32 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Ombi.Helpers; + +namespace Ombi.Store.Migrations +{ + public partial class Roles : Migration + { + protected override void Up(MigrationBuilder mb) + { + // Make sure we have the roles + InsertRole(mb, OmbiRoles.ReceivesNewsletter); + InsertRole(mb, OmbiRoles.RequestMusic); + InsertRole(mb, OmbiRoles.AutoApproveMusic); + InsertRole(mb, OmbiRoles.ManageOwnRequests); + InsertRole(mb, OmbiRoles.EditCustomPage); + } + + private void InsertRole(MigrationBuilder mb, string role) + { + mb.Sql($@" +INSERT INTO AspnetRoles(Id, ConcurrencyStamp, Name, NormalizedName) +SELECT '{Guid.NewGuid().ToString()}','{Guid.NewGuid().ToString()}','{role}', '{role.ToUpper()}' +WHERE NOT EXISTS(SELECT 1 FROM AspnetRoles WHERE Name = '{role}');"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} From ada38a0c3066f59c103676f3dc2a8e8add97fe1b Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 16 Feb 2019 23:40:32 +0000 Subject: [PATCH 278/325] Fixed #2801 this is when a season is not correctly monitored in sonarr when approved by an admin --- src/Ombi.Core/Engine/TvRequestEngine.cs | 1 + src/Ombi.Core/Senders/TvSender.cs | 16 +- .../Entities/Requests/TvRequests.cs | 4 - ...6231519_TvRequestsTotalSeasons.Designer.cs | 1214 +++++++++++++++++ .../20190216231519_TvRequestsTotalSeasons.cs | 23 + .../Migrations/OmbiContextModelSnapshot.cs | 2 + src/Ombi.Tests/TokenControllerTests.cs | 112 +- 7 files changed, 1309 insertions(+), 63 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.cs diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index ddcc22d7b..58144d3ce 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -385,6 +385,7 @@ namespace Ombi.Core.Engine foreach (var ep in s.Episodes) { ep.Approved = true; + ep.Requested = true; } } diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 3edc34e1b..9a25ca9c0 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -16,6 +16,7 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; +using Remotion.Linq.Parsing.Structure.IntermediateModel; namespace Ombi.Core.Senders { @@ -314,10 +315,19 @@ namespace Ombi.Core.Senders foreach (var season in model.SeasonRequests) { - var sonarrSeason = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber); - var sonarrEpCount = sonarrSeason.Count(); + var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList(); + var sonarrEpCount = sonarrEpisodeList.Count; var ourRequestCount = season.Episodes.Count; + var ourEpisodes = season.Episodes.Select(x => x.EpisodeNumber).ToList(); + var unairedEpisodes = sonarrEpisodeList.Where(x => x.airDateUtc > DateTime.UtcNow).Select(x => x.episodeNumber).ToList(); + + //// Check if we have requested all the latest episodes, if we have then monitor + //// NOTE, not sure if needed since ombi ui displays future episodes anyway... + //ourEpisodes.AddRange(unairedEpisodes); + //var distinctEpisodes = ourEpisodes.Distinct().ToList(); + //var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes); + var existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); if (existingSeason == null) @@ -327,7 +337,7 @@ namespace Ombi.Core.Senders } - if (sonarrEpCount == ourRequestCount) + if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/) { // We have the same amount of requests as all of the episodes in the season. diff --git a/src/Ombi.Store/Entities/Requests/TvRequests.cs b/src/Ombi.Store/Entities/Requests/TvRequests.cs index 432bc88ab..5e33c016f 100644 --- a/src/Ombi.Store/Entities/Requests/TvRequests.cs +++ b/src/Ombi.Store/Entities/Requests/TvRequests.cs @@ -17,10 +17,6 @@ namespace Ombi.Store.Entities.Requests public DateTime ReleaseDate { get; set; } public string Status { get; set; } - /// - /// This is so we can correctly send the right amount of seasons to Sonarr - /// - [NotMapped] public int TotalSeasons { get; set; } public List ChildRequests { get; set; } diff --git a/src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.Designer.cs b/src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.Designer.cs new file mode 100644 index 000000000..7341ff5fe --- /dev/null +++ b/src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.Designer.cs @@ -0,0 +1,1214 @@ +// +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 +{ + [DbContext(typeof(OmbiContext))] + [Migration("20190216231519_TvRequestsTotalSeasons")] + partial class TvRequestsTotalSeasons + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TotalSeasons"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.cs b/src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.cs new file mode 100644 index 000000000..0bae50c15 --- /dev/null +++ b/src/Ombi.Store/Migrations/20190216231519_TvRequestsTotalSeasons.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class TvRequestsTotalSeasons : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TotalSeasons", + table: "TvRequests", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "TotalSeasons", + table: "TvRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 50a34a931..466011d43 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -819,6 +819,8 @@ namespace Ombi.Store.Migrations b.Property("Title"); + b.Property("TotalSeasons"); + b.Property("TvDbId"); b.HasKey("Id"); diff --git a/src/Ombi.Tests/TokenControllerTests.cs b/src/Ombi.Tests/TokenControllerTests.cs index ec0e616ac..0fb1e9200 100644 --- a/src/Ombi.Tests/TokenControllerTests.cs +++ b/src/Ombi.Tests/TokenControllerTests.cs @@ -1,60 +1,60 @@ -using System.Net.Http; -using System.Threading.Tasks; -using AutoMapper; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features.Authentication; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Moq; -using NUnit.Framework; -using Ombi.Api.Emby; -using Ombi.Api.Plex; -using Ombi.Controllers; -using Ombi.Core.Authentication; -using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; -using Ombi.Models.Identity; -using Ombi.Notifications; -using Ombi.Schedule.Jobs.Ombi; -using Ombi.Settings.Settings.Models; -using Ombi.Settings.Settings.Models.Notifications; -using Ombi.Store.Context; -using Ombi.Store.Entities; -using Ombi.Store.Repository; -using Microsoft.AspNetCore.Hosting.Server; -using Microsoft.AspNetCore.TestHost; -using Newtonsoft.Json; -using Ombi.Models; +//using System.Net.Http; +//using System.Threading.Tasks; +//using AutoMapper; +//using Microsoft.AspNetCore.Hosting; +//using Microsoft.AspNetCore.Http; +//using Microsoft.AspNetCore.Http.Features.Authentication; +//using Microsoft.AspNetCore.Identity; +//using Microsoft.Extensions.DependencyInjection; +//using Microsoft.Extensions.Options; +//using Moq; +//using NUnit.Framework; +//using Ombi.Api.Emby; +//using Ombi.Api.Plex; +//using Ombi.Controllers; +//using Ombi.Core.Authentication; +//using Ombi.Core.Settings; +//using Ombi.Core.Settings.Models.External; +//using Ombi.Models.Identity; +//using Ombi.Notifications; +//using Ombi.Schedule.Jobs.Ombi; +//using Ombi.Settings.Settings.Models; +//using Ombi.Settings.Settings.Models.Notifications; +//using Ombi.Store.Context; +//using Ombi.Store.Entities; +//using Ombi.Store.Repository; +//using Microsoft.AspNetCore.Hosting.Server; +//using Microsoft.AspNetCore.TestHost; +//using Newtonsoft.Json; +//using Ombi.Models; -namespace Ombi.Tests -{ - [TestFixture] - [Ignore("TODO")] - public class TokenControllerTests - { - [SetUp] - public void Setup() - { - _testServer = new TestServer(new WebHostBuilder() - .UseStartup()); - _client = _testServer.CreateClient(); - } +//namespace Ombi.Tests +//{ +// [TestFixture] +// [Ignore("TODO")] +// public class TokenControllerTests +// { +// [SetUp] +// public void Setup() +// { +// _testServer = new TestServer(new WebHostBuilder() +// .UseStartup()); +// _client = _testServer.CreateClient(); +// } - private TestServer _testServer; - private HttpClient _client; +// private TestServer _testServer; +// private HttpClient _client; - [Test] - public async Task GetToken_FromValid_LocalUser() - { - var model = new UserAuthModel - { - Password = "a", - Username = "a" - }; - HttpResponseMessage response = await _client.PostAsync("/api/v1/token", new StringContent(JsonConvert.SerializeObject(model)) ); - } - } -} \ No newline at end of file +// [Test] +// public async Task GetToken_FromValid_LocalUser() +// { +// var model = new UserAuthModel +// { +// Password = "a", +// Username = "a" +// }; +// HttpResponseMessage response = await _client.PostAsync("/api/v1/token", new StringContent(JsonConvert.SerializeObject(model)) ); +// } +// } +//} \ No newline at end of file From 2fe175b165447fae1e09108bd82301660927b775 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Mon, 18 Feb 2019 02:55:16 +0000 Subject: [PATCH 279/325] fix: src/Ombi/package.json to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-BOOTSTRAP-173700 --- src/Ombi/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/package.json b/src/Ombi/package.json index 5713b1061..acd432418 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -42,7 +42,7 @@ "angular2-template-loader": "^0.6.2", "aspnet-webpack": "^3.0.0", "awesome-typescript-loader": "^5.2.0", - "bootstrap": "3.4.0", + "bootstrap": "3.4.1", "bootswatch": "3.4.0", "copy-webpack-plugin": "^4.5.2", "core-js": "^2.5.7", From cd15e7ded7c527de388abade2de8796f4a468d55 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 18 Feb 2019 11:29:27 +0000 Subject: [PATCH 280/325] gitchangelog !wip --- CHANGELOG.md | 182 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 170 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96f37c27b..0d7f0802d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,107 @@ # Changelog +## (unreleased) -## v3.0.4119 (2019-1-09) +### **New Features** +- Update discord link to follow the scheme of other links. [Tom McClellan] + +- Update issue templates. [Jamie] + +- Update README.md. [Jamie] + +- Update CHANGELOG.md. [Jamie] + +- Added the functionality to remove a user from getting notifications to their mobile device #2780. [tidusjar] + +- Added a demo mode, this will only show movies and shows that are in the public domain. Dam that stupid fruit company. [tidusjar] + +- Added Actor Searching for Movies! [TidusJar] + +- Added the ability to change where the View on Emby link goes to #2730. [TidusJar] + +- Added the request queue to the notifications UI so you can turn it off per notification agent #2747. [TidusJar] + +- Added new classes to the posters #2732. [TidusJar] + +### **Fixes** + +- Fix: src/Ombi/package.json to reduce vulnerabilities. [snyk-bot] + +- Fixed #2801 this is when a season is not correctly monitored in sonarr when approved by an admin. [tidusjar] + +- Small improvements to try and mitigate #2750. [tidusjar] + +- Removed some areas where we clear out the cache. This should help with DB locking #2750. [tidusjar] + +- Fixed #2810. [tidusjar] + +- Cannot create an issue comment with the API #2811. [tidusjar] + +- Set the local domain if the Application URL is set for the HELO or EHLO commands. #2636. [tidusjar] + +- New translations en.json (Spanish) [Jamie] + +- Delete ISSUE_TEMPLATE.md. [Jamie] + +- More minor grammatical edits. [Andrew Metzger] + +- Minor grammatical edits. [Andrew Metzger] + +- Fixed #2802 the issue where "Issues" were not being deleted correctly. [tidusjar] + +- Fixed #2797. [tidusjar] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- Fixed #2786. [tidusjar] + +- Fixed #2756. [tidusjar] + +- Ignore the UserName header as part of the Api is the value is an empty string. [tidusjar] + +- Fixed #2759. [tidusjar] + +- Did #2756. [TidusJar] + +- Fixed the exception that sometimes makes ombi fallover. [TidusJar] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- Log the error to the ui to figure out what's going on with #2755. [tidusjar] + +- Small fix when denying a request with a reason, we wasn't updating the ui. [TidusJar] + +- Make sure we can only set the ApiAlias when using the API Key. [tidusjar] + +- #2363 Added the ability to pass any username into the API using the ApiAlias header. [tidusjar] + +- Removed the Add user to Plex from Ombi. [tidusjar] + + +## v3.0.4119 (2019-01-09) ### **New Features** @@ -24,27 +123,33 @@ - Added the ability to specify a year when searching for movies. [tidusjar] -- Made the newsletter use the default lanuage code set in the Ombi settings for movie information. [TidusJar] +- Update NewsletterTemplate.html. [d1slact0r] -- Added a global language flag that now applies to the search by default. [tidusjar] +- Update NewsletterTemplate.html. [d1slact0r] -- Updated the frontend packages (Using Angular 7 now) [TidusJar] +- Update NewsletterTemplate.html. [d1slact0r] -- Added capture of anonymous analytical data. [tidusjar] +- Update HtmlTemplateGenerator.cs. [d1slact0r] -- Added {AvailableDate} as a Notification Variable, this is the date the request was marked as available. See here: https://github.com/tidusjar/Ombi/wiki/Notification-Template-Variables. [tidusjar] +- Update NewsletterTemplate.html. [d1slact0r] -- Updated the Newsletter template! Better mail client support [d1slact0r] +- Update HtmlTemplateGenerator.cs. [d1slact0r] -- Updated boostrap #2694. [TidusJar] +- Update NewsletterTemplate.html. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update NewsletterTemplate.html. [d1slact0r] + +- Update HtmlTemplateGenerator.cs. [d1slact0r] + +- Updated boostrap #2694. [Jamie] - Added the ability to deny a request with a reason. [TidusJar] -- Updated to .net core 2.2 and included a linux-arm64 build. [aptalca] -- Make the newsletter BCC the users rather than creating a million newsletters (Hopefully will stop SMTP providers from marking as spam). This does mean that the custom user customization in the newsletter will no longer work. [TidusJar] +- Update EmbyEpisodeSync.cs. [Jamie] - -- New translations [TidusJar] +- Updated to .net core 2.2 and included a linux-arm64 build. [TidusJar] ### **Fixes** @@ -66,12 +171,62 @@ - Fixed #2716. [tidusjar] +- Make the newsletter BCC the users rather than creating a million newsletters (Hopefully will stop SMTP providers from marking as spam). This does mean that the custom user customization in the newsletter will no longer work. [TidusJar] + - If we don't know the Plex agent, then see if it's a ImdbId, if it's not check the string for any episode and season hints #2695. [tidusjar] +- 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] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- Made the search results the language specified in the search refinement. [tidusjar] + - Fixed #2704. [tidusjar] +- Now it is fixed :) [d1slact0r] + +- Android please be nice now. [d1slact0r] + +- Fixed title bit better. [d1slact0r] + +- Fixed titles. [d1slact0r] + +- This should fix the build for sure (stupid quotes) [d1slact0r] + +- Fixes build. [d1slact0r] + +- Rewritten the whole newsletter template. [d1slact0r] + - Fixed #2697. [tidusjar] +- Add linux-arm runtime identifier. [aptalca] + +- Add back arm packages. [aptalca] + +- Add arm32 package. [aptalca] + - Fixed #2691. [tidusjar] - Fixed linting. [TidusJar] @@ -80,10 +235,13 @@ - Fixed #2678. [TidusJar] +- Deny reason for movie requests. [TidusJar] + - Set the landing and login pages background refresh to 15 seconds rather than 10 and 7. [TidusJar] - Fixed a bug with us thinking future dated emby episodes are not available, Consoldated the emby and plex search rules (since they have the same logic) [TidusJar] +- Fixed build. [TidusJar] ## v3.0.4036 (2018-12-11) From f67ea821874fe9f6577ba834b9d422cfa0845d20 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 18 Feb 2019 15:49:11 +0000 Subject: [PATCH 281/325] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index c2df9306b..d4e23e278 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -74,7 +74,7 @@ "ViewOnEmby": "Regarder sur Emby", "RequestAdded": "La demande pour {{title}} a été ajoutée avec succès", "Similar": "Similaires", - "Refine": "Refine", + "Refine": "Affiner", "Movies": { "PopularMovies": "Films populaires", "UpcomingMovies": "Films à venir", From 771ff2bd3bafb420de0adef8330f22dc92700c4c Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 18 Feb 2019 16:09:16 +0000 Subject: [PATCH 282/325] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d7f0802d..4e481b1b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## (unreleased) +## v3.0.4248 (2019-02-18) ### **New Features** From 7084839bc76f0ad3acfdd16f878c9d9e30558308 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 19 Feb 2019 16:26:10 +0000 Subject: [PATCH 283/325] Fixed #2826 --- src/Ombi.Notifications.Templates/EmailBasicTemplate.cs | 2 +- src/Ombi.Notifications/GenericEmailProvider.cs | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs index b29122be0..fc80de193 100644 --- a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs +++ b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs @@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates if (string.IsNullOrEmpty(_templateLocation)) { #if DEBUG - _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp2.0", "Templates", + _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp2.2", "Templates", "BasicTemplate.html"); #else _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html"); diff --git a/src/Ombi.Notifications/GenericEmailProvider.cs b/src/Ombi.Notifications/GenericEmailProvider.cs index 916367e0a..653670ef7 100644 --- a/src/Ombi.Notifications/GenericEmailProvider.cs +++ b/src/Ombi.Notifications/GenericEmailProvider.cs @@ -57,11 +57,6 @@ namespace Ombi.Notifications using (var client = new SmtpClient()) { - if (customization.ApplicationUrl.HasValue()) - { - client.LocalDomain = customization.ApplicationUrl; - } - if (settings.DisableCertificateChecking) { // Disable validation of the certificate associated with the SMTP service From 0517fdd9397392f9dc83c1e9b79f611228609d78 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 19 Feb 2019 17:22:46 +0000 Subject: [PATCH 284/325] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e481b1b3..5f2948060 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v3.0.4248 (2019-02-18) +## v3.0.4256 (2019-02-18) ### **New Features** From 09b2b6fe6f7eb94942feb6c889cc53aa06568817 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 19 Feb 2019 20:01:56 +0000 Subject: [PATCH 285/325] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index ddd3ed24d..af5f83efb 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -64,7 +64,7 @@ "Title": "Szukaj", "Paragraph": "Chcesz obejrzeć coś, co nie jest obecnie dostępne? Żaden problem, po prostu wyszukaj poniżej i dodaj zgłoszenie!", "MoviesTab": "Filmy", - "TvTab": "Seriale", + "TvTab": "Programy TV", "MusicTab": "Muzyka", "Suggestions": "Sugestie", "NoResults": "Niestety nic nie znaleziono!", From bd06af8ca0407ea38f1b8f5bcd362ebbeb0e8f99 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 20 Feb 2019 21:37:32 +0000 Subject: [PATCH 286/325] !wip just some small minor improvements --- .../Rule/Rules/Search/AvailabilityRuleHelper.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index 428de9ce5..58a0c300f 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -24,7 +24,7 @@ namespace Ombi.Core.Rule.Rules.Search if (!airedButNotAvailable) { var unairedEpisodes = search.SeasonRequests.Any(x => - x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date)); + x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date && c.AirDate != DateTime.MinValue)); if (unairedEpisodes) { search.FullyAvailable = true; @@ -41,21 +41,21 @@ namespace Ombi.Core.Rule.Rules.Search { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId.ToString()); + x.Series.ImdbId.Equals(item.ImdbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); } if (useTheMovieDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId.ToString()); + x.Series.TheMovieDbId.Equals(item.TheMovieDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); } if (useTvDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId.ToString()); + x.Series.TvDbId.Equals(item.TvDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); } if (epExists != null) @@ -71,21 +71,21 @@ namespace Ombi.Core.Rule.Rules.Search { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId.ToString()); + x.Series.ImdbId.Equals(item.ImdbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); } if (useTheMovieDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId.ToString()); + x.Series.TheMovieDbId.Equals(item.TheMovieDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); } if (useTvDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId.ToString()); + x.Series.TvDbId.Equals(item.TvDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); } if (epExists != null) From 099e7d3436840177dc095654219d4c23d3ba10c2 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 20 Feb 2019 20:10:03 -0500 Subject: [PATCH 287/325] fix typo --- src/Ombi/ClientApp/app/settings/emby/emby.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/emby/emby.component.html b/src/Ombi/ClientApp/app/settings/emby/emby.component.html index 62188aaf6..66cac8c8b 100644 --- a/src/Ombi/ClientApp/app/settings/emby/emby.component.html +++ b/src/Ombi/ClientApp/app/settings/emby/emby.component.html @@ -67,7 +67,7 @@
From 3a690e321ea8b72940a5087ffdd13f738fca0898 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 22 Feb 2019 08:08:58 +0000 Subject: [PATCH 288/325] Fixed an issue where the Subscribe button was appearing on available movies. --- src/Ombi.Core/Engine/MovieSearchEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index 84cb8afcf..520f052a9 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -227,7 +227,7 @@ namespace Ombi.Core.Engine } var request = await RequestService.MovieRequestService.GetAll() .AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id); - if (request) + if (request || viewModel.Available) { viewModel.ShowSubscribe = false; } From c84d5f9f5d5e06845eabc71274d331180b4daf1a Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 22 Feb 2019 09:05:47 +0000 Subject: [PATCH 289/325] Fixed a regression issue where TV Shows couldn't be requested --- .../Rule/Rules/Search/AvailabilityRuleHelper.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index 58a0c300f..503296400 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; using Ombi.Core.Models.Search; using Ombi.Store.Entities; using Ombi.Store.Repository.Requests; @@ -41,21 +40,21 @@ namespace Ombi.Core.Rule.Rules.Search { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId.Equals(item.ImdbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); + x.Series.ImdbId == item.ImdbId); } if (useTheMovieDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId.Equals(item.TheMovieDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); + x.Series.TheMovieDbId == item.TheMovieDbId); } if (useTvDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId.Equals(item.TvDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); + x.Series.TvDbId == item.TvDbId); } if (epExists != null) @@ -71,21 +70,21 @@ namespace Ombi.Core.Rule.Rules.Search { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId.Equals(item.ImdbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); + x.Series.ImdbId == item.ImdbId); } if (useTheMovieDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId.Equals(item.TheMovieDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); + x.Series.TheMovieDbId == item.TheMovieDbId); } if (useTvDb) { epExists = await allEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId.Equals(item.TvDbId.ToString(), StringComparison.InvariantCultureIgnoreCase)); + x.Series.TvDbId == item.TvDbId); } if (epExists != null) From 8be3ef205a6c955f11fbd3032adf78ff5685b08e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 22 Feb 2019 12:15:33 +0000 Subject: [PATCH 290/325] update dependancies --- src/Ombi.Core/Ombi.Core.csproj | 4 ++-- src/Ombi.Schedule/Ombi.Schedule.csproj | 4 ++-- src/Ombi.Store/Ombi.Store.csproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 35688a6fe..790aa8500 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -11,9 +11,9 @@ - + - + diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index ff3a17115..256a3df7a 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index f905c9ffe..31c69c8d8 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -12,8 +12,8 @@ - - + + From 6a36fa3974b51c9dd0cddd4fa64a4e7c540bea62 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 25 Feb 2019 08:42:06 +0000 Subject: [PATCH 291/325] Fixed #2847 --- src/Ombi.Notifications/Agents/MattermostNotification.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs index f64a0fe21..ed3084c19 100644 --- a/src/Ombi.Notifications/Agents/MattermostNotification.cs +++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs @@ -52,7 +52,7 @@ namespace Ombi.Notifications.Agents private void AddOtherInformation(NotificationOptions model, NotificationMessage notification, NotificationMessageContent parsed) { - notification.Other.Add("image", parsed.Image); + notification.Other.Add("image", parsed?.Image ?? string.Empty); notification.Other.Add("title", model.RequestType == RequestType.Movie ? MovieRequest.Title : TvRequest.Title); } From d1086e8ae08cf16335a1834d758e57137b8203e5 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 25 Feb 2019 08:47:16 +0000 Subject: [PATCH 292/325] Prevented #2848 from erroring out causing further issues. --- .../Rules/Search/AvailabilityRuleHelper.cs | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index 503296400..dd4f6c918 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Store.Entities; using Ombi.Store.Repository.Requests; @@ -33,28 +34,36 @@ namespace Ombi.Core.Rule.Rules.Search } public static async Task SingleEpisodeCheck(bool useImdb, IQueryable allEpisodes, EpisodeRequests episode, - SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb) + SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log) { PlexEpisode epExists = null; - if (useImdb) + try { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.ImdbId == item.ImdbId); - } - if (useTheMovieDb) - { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TheMovieDbId == item.TheMovieDbId); - } + if (useImdb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.ImdbId == item.ImdbId); + } - if (useTvDb) + if (useTheMovieDb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.TheMovieDbId == item.TheMovieDbId); + } + + if (useTvDb) + { + epExists = await allEpisodes.FirstOrDefaultAsync(x => + x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && + x.Series.TvDbId == item.TvDbId); + } + } + catch (Exception e) { - epExists = await allEpisodes.FirstOrDefaultAsync(x => - x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && - x.Series.TvDbId == item.TvDbId); + log.LogError(e, "Exception thrown when attempting to check if something is available"); } if (epExists != null) From d233d2faebe8699020c918bae542f73ce0cdc7e5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 25 Feb 2019 17:01:30 +0000 Subject: [PATCH 293/325] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 93ed1342e..b65c9b53c 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -13,7 +13,7 @@ "ContinueButton": "Gå videre", "Available": "Tilgjengelig", "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", + "Monitored": "Overvåket", "NotAvailable": "Ikke tilgjengelig", "ProcessingRequest": "Behandler forespørsel", "PendingApproval": "Venter på godkjenning", @@ -48,7 +48,7 @@ "Requests": "Forespørsler", "UserManagement": "Brukeradministrasjon", "Issues": "Mangler", - "Vote": "Vote", + "Vote": "Stem", "Donate": "Doner!", "DonateLibraryMaintainer": "Doner til vedlikeholderen av biblioteket", "DonateTooltip": "Dette er hvordan jeg overbevise min kone til å la meg bruke min fritid til å utvikle Ombi ;)", @@ -58,14 +58,14 @@ "UpdateDetails": "Oppdater detaljer", "Logout": "Logg av", "OpenMobileApp": "Åpne mobilapp", - "RecentlyAdded": "Recently Added" + "RecentlyAdded": "Nylig lagt til" }, "Search": { "Title": "Søk", "Paragraph": "Vil du se noe som foreløpig ikke er tilgjengelig? Ikke noe problem, bare søk etter det nedenfor og be om det!", "MoviesTab": "Filmer", "TvTab": "TV serier", - "MusicTab": "Music", + "MusicTab": "Musikk", "Suggestions": "Forslag", "NoResults": "Beklager, vi fant ingen resultater!", "DigitalDate": "Digital utgivelse: {{date}}", @@ -104,7 +104,7 @@ "Paragraph": "Nedenfor kan du se dine og alle andres forespørsler, du ser også status for nedlasting og godkjenning.", "MoviesTab": "Filmer", "TvTab": "TV serier", - "MusicTab": "Music", + "MusicTab": "Musikk", "RequestedBy": "Etterspurt av:", "Status": "Status:", "RequestStatus": "Status for forespørsel:", @@ -128,10 +128,10 @@ "GridStatus": "Status", "ReportIssue": "Rapportér en feil", "Filter": "Filter", - "Sort": "Sort", + "Sort": "Sorter", "SeasonNumberHeading": "Sesong: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", + "SortTitleAsc": "Tittel ▲", + "SortTitleDesc": "Tittel ▼", "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", @@ -168,18 +168,18 @@ "FilterHeaderAvailability": "Tilgjengelighet", "FilterHeaderRequestStatus": "Status", "Approved": "Godkjent", - "PendingApproval": "Pending Approval" + "PendingApproval": "Venter på godkjenning" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "TV: {{remaining}}/{{total}} gjenstående", + "MovieRemaining": "Filmer: {{remaining}}/{{total}} gjenstående", + "MusicRemaining": "Musikk: {{remaining}}/{{total}} gjenstående", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film:{{date}}", + "MusicDue": "Musikk:{{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", + "CompletedVotesTab": "Stemt", "VotesTab": "Votes Needed" } } From c8415f8da9ccd5adc19f1f84f217928ddebb7282 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 25 Feb 2019 21:36:19 +0000 Subject: [PATCH 294/325] Set the CommandTimeout longer to see if EF can get a handle on the SQLite file when it's locked #2750 --- src/Ombi.Store/Context/ExternalContext.cs | 1 + src/Ombi.Store/Context/OmbiContext.cs | 10 +++++++++- src/Ombi.Store/Context/SettingsContext.cs | 8 +------- src/Ombi/Program.cs | 18 +----------------- 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/Ombi.Store/Context/ExternalContext.cs b/src/Ombi.Store/Context/ExternalContext.cs index eb2be6450..ff0581091 100644 --- a/src/Ombi.Store/Context/ExternalContext.cs +++ b/src/Ombi.Store/Context/ExternalContext.cs @@ -13,6 +13,7 @@ namespace Ombi.Store.Context if (_created) return; _created = true; + Database.SetCommandTimeout(60); Database.Migrate(); } diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 47b245603..2f19bc681 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -18,6 +18,7 @@ namespace Ombi.Store.Context if (_created) return; _created = true; + Database.SetCommandTimeout(60); Database.Migrate(); } @@ -107,6 +108,7 @@ namespace Ombi.Store.Context var allAgents = Enum.GetValues(typeof(NotificationAgent)).Cast().ToList(); var allTypes = Enum.GetValues(typeof(NotificationType)).Cast().ToList(); + var needToSave = false; foreach (var agent in allAgents) { foreach (var notificationType in allTypes) @@ -116,6 +118,8 @@ namespace Ombi.Store.Context // We already have this continue; } + + needToSave = true; NotificationTemplates notificationToAdd; switch (notificationType) { @@ -230,7 +234,11 @@ namespace Ombi.Store.Context NotificationTemplates.Add(notificationToAdd); } } - SaveChanges(); + + if (needToSave) + { + SaveChanges(); + } } } } \ No newline at end of file diff --git a/src/Ombi.Store/Context/SettingsContext.cs b/src/Ombi.Store/Context/SettingsContext.cs index 6a53e598f..6c9fad335 100644 --- a/src/Ombi.Store/Context/SettingsContext.cs +++ b/src/Ombi.Store/Context/SettingsContext.cs @@ -14,6 +14,7 @@ namespace Ombi.Store.Context if (_created) return; _created = true; + Database.SetCommandTimeout(60); Database.Migrate(); } @@ -63,13 +64,6 @@ namespace Ombi.Store.Context }); SaveChanges(); } - - SaveChanges(); - } - - ~SettingsContext() - { - } } } \ No newline at end of file diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index acc904875..40fd37e73 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -91,9 +91,7 @@ namespace Ombi dbBaseUrl.Value = baseUrl; ctx.SaveChanges(); } - - DeleteSchedulesDb(); - + Console.WriteLine($"We are running on {urlValue}"); CreateWebHostBuilder(args).Build().Run(); @@ -226,20 +224,6 @@ namespace Ombi } } - private static void DeleteSchedulesDb() - { - try - { - if (File.Exists("Schedules.db")) - { - File.Delete("Schedules.db"); - } - } - catch (Exception) - { - } - } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() From ee89f6f16cddfafab1e8211588c3b3a7c8476227 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 25 Feb 2019 22:26:09 +0000 Subject: [PATCH 295/325] Fixed build !wip --- .../Rule/Search/PlexAvailabilityRuleTests.cs | 3 ++- .../Rule/Rules/Search/PlexAvailabilityRule.cs | 7 +++++-- src/Ombi.Store/Repository/BaseRepository.cs | 10 +++++----- src/Ombi/Ombi.csproj | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs index 55177a6ac..5bd35473c 100644 --- a/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Ombi.Core.Models.Search; @@ -14,7 +15,7 @@ namespace Ombi.Core.Tests.Rule.Search public void Setup() { ContextMock = new Mock(); - Rule = new PlexAvailabilityRule(ContextMock.Object); + Rule = new PlexAvailabilityRule(ContextMock.Object, new Mock>().Object); } private PlexAvailabilityRule Rule { get; set; } diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs index 7f79e4165..2a239d1d3 100644 --- a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; @@ -10,12 +11,14 @@ namespace Ombi.Core.Rule.Rules.Search { public class PlexAvailabilityRule : BaseSearchRule, IRules { - public PlexAvailabilityRule(IPlexContentRepository repo) + public PlexAvailabilityRule(IPlexContentRepository repo, ILogger log) { PlexContentRepository = repo; + Log = log; } private IPlexContentRepository PlexContentRepository { get; } + private ILogger Log { get; } public async Task Execute(SearchViewModel obj) { @@ -72,7 +75,7 @@ namespace Ombi.Core.Rule.Rules.Search { foreach (var episode in season.Episodes) { - await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb); + await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log); } } diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index 1679035dd..efd277f43 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -40,27 +40,27 @@ namespace Ombi.Store.Repository _db.AddRange(content); if (save) { - await _ctx.SaveChangesAsync(); + await SaveChangesAsync(); } } public async Task Add(T content) { await _db.AddAsync(content); - await _ctx.SaveChangesAsync(); + await SaveChangesAsync(); return content; } public async Task Delete(T request) { _db.Remove(request); - await _ctx.SaveChangesAsync(); + await SaveChangesAsync(); } public async Task DeleteRange(IEnumerable req) { _db.RemoveRange(req); - await _ctx.SaveChangesAsync(); + await SaveChangesAsync(); } public async Task SaveChangesAsync() @@ -79,7 +79,7 @@ namespace Ombi.Store.Repository { await _ctx.Database.ExecuteSqlCommandAsync(sql); } - + private bool _disposed; // Protected implementation of Dispose pattern. diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index dc447dd20..02e11c84b 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -65,7 +65,7 @@ - + From e1a82ed8ef11fcbe16430586e6365b1bbd674f44 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 26 Feb 2019 14:32:25 +0000 Subject: [PATCH 296/325] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 592d69f9c..b3e93f306 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -13,7 +13,7 @@ "ContinueButton": "Weiter", "Available": "Verfügbar", "PartiallyAvailable": "Teilweise verfügbar", - "Monitored": "Monitored", + "Monitored": "Überwacht", "NotAvailable": "Nicht verfügbar", "ProcessingRequest": "Anfrage wird bearbeitet", "PendingApproval": "Genehmigung ausstehend", @@ -68,13 +68,13 @@ "MusicTab": "Musik", "Suggestions": "Vorschläge", "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", - "DigitalDate": "Digital Release: {{date}}", + "DigitalDate": "Veröffentlichung der digitalen Version: {{date}}", "TheatricalRelease": "Kinostart: {{date}}", "ViewOnPlex": "In Plex anschauen", "ViewOnEmby": "In Emby anschauen", "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", "Similar": "Ähnliche", - "Refine": "Refine", + "Refine": "Auswahl verfeinern", "Movies": { "PopularMovies": "Beliebte Filme", "UpcomingMovies": "Kommende Filme", @@ -112,7 +112,7 @@ "TheatricalRelease": "Kinostart: {{date}}", "ReleaseDate": "Veröffentlicht: {{date}}", "TheatricalReleaseSort": "Kinostart", - "DigitalRelease": "Digital Release: {{date}}", + "DigitalRelease": "Veröffentlichung der digitalen Version: {{date}}", "RequestDate": "Datum der Anfrage:", "QualityOverride": "Qualitäts Überschreiben:", "RootFolderOverride": "Stammverzeichnis Überschreiben:", @@ -132,16 +132,16 @@ "SeasonNumberHeading": "Staffel: {seasonNumber}", "SortTitleAsc": "Titel ▲", "SortTitleDesc": "Titel ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", + "SortRequestDateAsc": "Datum der Anfrage ▲", + "SortRequestDateDesc": "Datum der Anfrage ▼", "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { "Quota": "{{remaining}}/{{total}} Anfragen verbleiben", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "NextDays": "Eine weitere Anfrage wird in {{time}} Tagen hinzugefügt", + "NextHours": "Eine weitere Anfrage wird in {{time}} Stunden hinzugefügt", + "NextMinutes": "Eine weitere Anfrage wird in {{time}} Minuten hinzugefügt", + "NextMinute": "Eine weitere Anfrage wird in {{time}} Minute hinzugefügt" } }, "Issues": { From 3592781e94bf85e881f1ae4c0ab2ccd65565fbf9 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Wed, 6 Mar 2019 10:13:11 +0000 Subject: [PATCH 297/325] Added a lock on the database commit level to see if I can improve locked db's --- src/Ombi.Store/Ombi.Store.csproj | 1 + src/Ombi.Store/Repository/BaseRepository.cs | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index 31c69c8d8..8dfcc1c28 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index efd277f43..21dd2dac5 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; +using Nito.AsyncEx; using Ombi.Store.Context; using Ombi.Store.Entities; @@ -19,6 +20,7 @@ namespace Ombi.Store.Repository } public DbSet _db { get; } private readonly U _ctx; + private readonly AsyncLock _mutex = new AsyncLock(); public async Task Find(object key) { @@ -40,32 +42,32 @@ namespace Ombi.Store.Repository _db.AddRange(content); if (save) { - await SaveChangesAsync(); + await InternalSaveChanges(); } } public async Task Add(T content) { await _db.AddAsync(content); - await SaveChangesAsync(); + await InternalSaveChanges(); return content; } public async Task Delete(T request) { _db.Remove(request); - await SaveChangesAsync(); + await InternalSaveChanges(); } public async Task DeleteRange(IEnumerable req) { _db.RemoveRange(req); - await SaveChangesAsync(); + await InternalSaveChanges(); } public async Task SaveChangesAsync() { - return await _ctx.SaveChangesAsync(); + return await InternalSaveChanges(); } public IIncludableQueryable Include( @@ -79,6 +81,14 @@ namespace Ombi.Store.Repository { await _ctx.Database.ExecuteSqlCommandAsync(sql); } + + private async Task InternalSaveChanges() + { + using (await _mutex.LockAsync()) + { + return await _ctx.SaveChangesAsync(); + } + } private bool _disposed; From b74a4d29c8b9b6c788149eabfe3346f2ca0caa84 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 7 Mar 2019 08:53:07 +0000 Subject: [PATCH 298/325] Fixed #2860 When a future series is unknown it should appear as available when we have the other seasons --- src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs index dd4f6c918..ab1a0af98 100644 --- a/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs +++ b/src/Ombi.Core/Rule/Rules/Search/AvailabilityRuleHelper.cs @@ -24,7 +24,7 @@ namespace Ombi.Core.Rule.Rules.Search if (!airedButNotAvailable) { var unairedEpisodes = search.SeasonRequests.Any(x => - x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date && c.AirDate != DateTime.MinValue)); + x.Episodes.Any(c => !c.Available && c.AirDate > DateTime.Now.Date || c.AirDate != DateTime.MinValue)); if (unairedEpisodes) { search.FullyAvailable = true; From 12997541f0def3b1722df27d1a55ba806e315759 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 7 Mar 2019 08:58:02 +0000 Subject: [PATCH 299/325] Fixed build --- build.cake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.cake b/build.cake index e8e4bb8c0..07a20587f 100644 --- a/build.cake +++ b/build.cake @@ -81,9 +81,9 @@ Task("SetVersionInfo") versionInfo = GitVersion(settings); - Information("GitResults -> {0}", versionInfo.Dump()); +// Information("GitResults -> {0}", versionInfo.Dump()); - Information(@"Build:{0}",AppVeyor.Environment.Build.Dump()); +//Information(@"Build:{0}",AppVeyor.Environment.Build.Dump()); var buildVersion = string.Empty; if(string.IsNullOrEmpty(AppVeyor.Environment.Build.Version)) From fa76a57f08bcf32f3d515fedf7eb3608042f3acc Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 13 Mar 2019 20:59:39 +0000 Subject: [PATCH 300/325] Fixed a migration issue --- src/Ombi/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 40fd37e73..f1809a2dc 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -115,7 +115,7 @@ namespace Ombi try { - if (ombi.Settings.Any()) + if (ombi.Settings.Any() && !settings.Settings.Any()) { // OK migrate it! var allSettings = ombi.Settings.ToList(); @@ -125,7 +125,7 @@ namespace Ombi // Check for any application settings - if (ombi.ApplicationConfigurations.Any()) + if (ombi.ApplicationConfigurations.Any() && !settings.ApplicationConfigurations.Any()) { // OK migrate it! var allSettings = ombi.ApplicationConfigurations.ToList(); From 1322076aa678207b424f2cc92a4394ba7f187e17 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 11 Mar 2019 08:33:16 +0000 Subject: [PATCH 301/325] Added a global mutex (not used yet) and moved around the code for loggin in since I suspect the Get Roles call is using deffered execution on the database causing the lock when attempting to access straight away #2750 --- src/Ombi.Helpers/GlobalMutex.cs | 38 +++++++++++++++++++++++++ src/Ombi/Controllers/TokenController.cs | 6 ++-- 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/Ombi.Helpers/GlobalMutex.cs diff --git a/src/Ombi.Helpers/GlobalMutex.cs b/src/Ombi.Helpers/GlobalMutex.cs new file mode 100644 index 000000000..ecf9cdf15 --- /dev/null +++ b/src/Ombi.Helpers/GlobalMutex.cs @@ -0,0 +1,38 @@ +using System; +using System.Threading; + +namespace Ombi.Helpers +{ + public static class GlobalMutex + { + public static T Lock(Func func) + { + const string mutexId = "Global\\OMBI"; + + using (var mutex = new Mutex(false, mutexId, out __)) + { + var hasHandle = false; + try + { + try + { + hasHandle = mutex.WaitOne(5000, false); + if (hasHandle == false) + throw new TimeoutException("Timeout waiting for exclusive access"); + } + catch (AbandonedMutexException) + { + hasHandle = true; + } + + return func(); + } + finally + { + if (hasHandle) + mutex.ReleaseMutex(); + } + } + } + } +} diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 44ec5686f..b27c04caa 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -123,9 +123,6 @@ namespace Ombi.Controllers return new UnauthorizedResult(); } - user.LastLoggedIn = DateTime.UtcNow; - await _userManager.UpdateAsync(user); - var claims = new List { new Claim(JwtRegisteredClaimNames.Sub, user.UserName), @@ -152,6 +149,9 @@ namespace Ombi.Controllers //await _token.CreateToken(new Tokens() {Token = accessToken, User = user}); } + user.LastLoggedIn = DateTime.UtcNow; + await _userManager.UpdateAsync(user); + return new JsonResult(new { access_token = accessToken, From 947c0e74cbe7bb2b471261d3d52a4e6dbdb8e079 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 14 Mar 2019 11:12:28 +0000 Subject: [PATCH 302/325] Made use of the global mutex, this should now hopefully work #2750 --- src/Ombi.Helpers/GlobalMutex.cs | 9 +++++---- src/Ombi.Store/Repository/BaseRepository.cs | 14 +++++--------- src/Ombi/Controllers/TokenController.cs | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Ombi.Helpers/GlobalMutex.cs b/src/Ombi.Helpers/GlobalMutex.cs index ecf9cdf15..0164e888c 100644 --- a/src/Ombi.Helpers/GlobalMutex.cs +++ b/src/Ombi.Helpers/GlobalMutex.cs @@ -1,15 +1,16 @@ using System; using System.Threading; +using System.Threading.Tasks; +using Nito.AsyncEx; namespace Ombi.Helpers { public static class GlobalMutex { - public static T Lock(Func func) + public static async Task Lock(Func> func) { const string mutexId = "Global\\OMBI"; - - using (var mutex = new Mutex(false, mutexId, out __)) + using (var mutex = new Mutex(false, mutexId, out _)) { var hasHandle = false; try @@ -25,7 +26,7 @@ namespace Ombi.Helpers hasHandle = true; } - return func(); + return await func(); } finally { diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index 21dd2dac5..ca2937291 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -5,7 +5,7 @@ using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; -using Nito.AsyncEx; +using Ombi.Helpers; using Ombi.Store.Context; using Ombi.Store.Entities; @@ -20,7 +20,6 @@ namespace Ombi.Store.Repository } public DbSet _db { get; } private readonly U _ctx; - private readonly AsyncLock _mutex = new AsyncLock(); public async Task Find(object key) { @@ -32,7 +31,7 @@ namespace Ombi.Store.Repository return _db.AsQueryable(); } - public async Task FirstOrDefaultAsync(Expression> predicate) + public async Task FirstOrDefaultAsync(Expression> predicate) { return await _db.FirstOrDefaultAsync(predicate); } @@ -84,12 +83,9 @@ namespace Ombi.Store.Repository private async Task InternalSaveChanges() { - using (await _mutex.LockAsync()) - { - return await _ctx.SaveChangesAsync(); - } + return await GlobalMutex.Lock(async () => await _ctx.SaveChangesAsync()); } - + private bool _disposed; // Protected implementation of Dispose pattern. @@ -102,7 +98,7 @@ namespace Ombi.Store.Repository { _ctx?.Dispose(); } - + _disposed = true; } diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index b27c04caa..9499dd493 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -150,7 +150,7 @@ namespace Ombi.Controllers } user.LastLoggedIn = DateTime.UtcNow; - await _userManager.UpdateAsync(user); + await GlobalMutex.Lock(async () => await _userManager.UpdateAsync(user)).ConfigureAwait(false); return new JsonResult(new { From 2b1eebafd106acb975f1ade74f5a52c6c95f7a83 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 14 Mar 2019 13:52:17 +0000 Subject: [PATCH 303/325] Set the View On Emby Url at runtime so the user can configure and change the URL and it will take effect straight away --- .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 3171c6ada..f80bded7a 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -3,6 +3,8 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -11,12 +13,14 @@ namespace Ombi.Core.Rule.Rules.Search { public class EmbyAvailabilityRule : BaseSearchRule, IRules { - public EmbyAvailabilityRule(IEmbyContentRepository repo) + public EmbyAvailabilityRule(IEmbyContentRepository repo, ISettingsService s) { EmbyContentRepository = repo; + EmbySettings = s; } private IEmbyContentRepository EmbyContentRepository { get; } + private ISettingsService EmbySettings { get; } public async Task Execute(SearchViewModel obj) { @@ -60,7 +64,16 @@ namespace Ombi.Core.Rule.Rules.Search if (item != null) { obj.Available = true; - obj.EmbyUrl = item.Url; + var s = await EmbySettings.GetSettingsAsync(); + var server = s.Servers.FirstOrDefault(x => x.ServerHostname != null); + if ((server?.ServerHostname ?? string.Empty).HasValue()) + { + obj.EmbyUrl = $"{server.ServerHostname}#!/itemdetails.html?id={item.EmbyId}"; + } + else + { + obj.EmbyUrl = $"https://app.emby.media/#!/itemdetails.html?id={item.EmbyId}"; + } if (obj.Type == RequestType.TvShow) { From f048505eed7d14fbd4f159ec593c5c125e276de9 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 14 Mar 2019 20:58:04 +0000 Subject: [PATCH 304/325] Fixed #2636 --- src/Ombi.Notifications/GenericEmailProvider.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Notifications/GenericEmailProvider.cs b/src/Ombi.Notifications/GenericEmailProvider.cs index 462f8918e..e255c4357 100644 --- a/src/Ombi.Notifications/GenericEmailProvider.cs +++ b/src/Ombi.Notifications/GenericEmailProvider.cs @@ -4,7 +4,9 @@ using EnsureThat; using MailKit.Net.Smtp; using Microsoft.Extensions.Logging; using MimeKit; +using MimeKit.Utils; using Ombi.Core.Settings; +using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Notifications.Templates; using Ombi.Settings.Settings.Models; @@ -36,6 +38,15 @@ namespace Ombi.Notifications var customization = await CustomizationSettings.GetSettingsAsync(); var html = email.LoadTemplate(model.Subject, model.Message, null, customization.Logo); + + var messageId = MimeUtils.GenerateMessageId(); + if (customization.ApplicationUrl.HasValue()) + { + if (Uri.TryCreate(customization.ApplicationUrl, UriKind.RelativeOrAbsolute, out var url)) + { + messageId = MimeUtils.GenerateMessageId(url.IdnHost); + } + } var textBody = string.Empty; @@ -49,7 +60,8 @@ namespace Ombi.Notifications var message = new MimeMessage { Body = body.ToMessageBody(), - Subject = model.Subject + Subject = model.Subject, + MessageId = messageId }; message.From.Add(new MailboxAddress(string.IsNullOrEmpty(settings.SenderName) ? settings.SenderAddress : settings.SenderName, settings.SenderAddress)); message.To.Add(new MailboxAddress(model.To, model.To)); From 52b75ee4de1ebab4d7d85236e0c75ba8a00756f9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 18 Mar 2019 12:46:47 +0000 Subject: [PATCH 305/325] Update JobSetup.cs --- src/Ombi.Schedule/JobSetup.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index 5cc818441..38686396f 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -81,7 +81,6 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); - RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s)); RecurringJob.AddOrUpdate(() => _mediaDatabaseRefresh.Start(), JobSettingsHelper.MediaDatabaseRefresh(s)); } From 94b70c2f2cff1675b07f158065f7203425023e55 Mon Sep 17 00:00:00 2001 From: Guillaume Taquet Gasperini Date: Wed, 20 Mar 2019 19:40:37 +0100 Subject: [PATCH 306/325] Add Gotify as notification provider --- README.md | 1 + src/Ombi.Api.Gotify/GotifyApi.cs | 36 ++++++ src/Ombi.Api.Gotify/IGotifyApi.cs | 9 ++ src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj | 15 +++ .../Models/UI/GotifyNotificationViewModel.cs | 23 ++++ src/Ombi.DependencyInjection/IocExtensions.cs | 3 + src/Ombi.Helpers/LoggingEvents.cs | 1 + src/Ombi.Helpers/NotificationAgent.cs | 1 + src/Ombi.Mapping/Profiles/SettingsProfile.cs | 1 + .../Agents/GotifyNotification.cs | 116 ++++++++++++++++++ .../Agents/Interfaces/IGotifyNotification.cs | 6 + .../Ombi.Notifications.csproj | 1 + .../Models/Notifications/GotifySettings.cs | 10 ++ src/Ombi.sln | 9 +- .../app/interfaces/INotificationSettings.ts | 8 ++ .../services/applications/tester.service.ts | 7 +- .../app/services/settings.service.ts | 9 ++ .../notifications/gotify.component.html | 67 ++++++++++ .../notifications/gotify.component.ts | 68 ++++++++++ .../ClientApp/app/settings/settings.module.ts | 3 + .../app/settings/settingsmenu.component.html | 1 + .../Controllers/External/TesterController.cs | 28 ++++- src/Ombi/Controllers/SettingsController.cs | 34 +++++ 23 files changed, 454 insertions(+), 3 deletions(-) create mode 100644 src/Ombi.Api.Gotify/GotifyApi.cs create mode 100644 src/Ombi.Api.Gotify/IGotifyApi.cs create mode 100644 src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj create mode 100644 src/Ombi.Core/Models/UI/GotifyNotificationViewModel.cs create mode 100644 src/Ombi.Notifications/Agents/GotifyNotification.cs create mode 100644 src/Ombi.Notifications/Agents/Interfaces/IGotifyNotification.cs create mode 100644 src/Ombi.Settings/Settings/Models/Notifications/GotifySettings.cs create mode 100644 src/Ombi/ClientApp/app/settings/notifications/gotify.component.html create mode 100644 src/Ombi/ClientApp/app/settings/notifications/gotify.component.ts diff --git a/README.md b/README.md index 61cda24f3..0af908f65 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ We integrate with the following applications: Supported notifications: * SMTP Notifications (Email) * Discord +* Gotify * Slack * Pushbullet * Pushover diff --git a/src/Ombi.Api.Gotify/GotifyApi.cs b/src/Ombi.Api.Gotify/GotifyApi.cs new file mode 100644 index 000000000..8cd79a689 --- /dev/null +++ b/src/Ombi.Api.Gotify/GotifyApi.cs @@ -0,0 +1,36 @@ +using System.Net.Http; +using System.Threading.Tasks; + +namespace Ombi.Api.Gotify +{ + public class GotifyApi : IGotifyApi + { + public GotifyApi(IApi api) + { + _api = api; + } + + private readonly IApi _api; + + public async Task PushAsync(string baseUrl, string accessToken, string subject, string body, sbyte priority) + { + var request = new Request("/message", baseUrl, HttpMethod.Post); + request.AddQueryString("token", accessToken); + + request.AddHeader("Access-Token", accessToken); + request.ApplicationJsonContentType(); + + + var jsonBody = new + { + message = body, + title = subject, + priority = priority + }; + + request.AddJsonBody(jsonBody); + + await _api.Request(request); + } + } +} diff --git a/src/Ombi.Api.Gotify/IGotifyApi.cs b/src/Ombi.Api.Gotify/IGotifyApi.cs new file mode 100644 index 000000000..e6a6b4060 --- /dev/null +++ b/src/Ombi.Api.Gotify/IGotifyApi.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Api.Gotify +{ + public interface IGotifyApi + { + Task PushAsync(string endpoint, string accessToken, string subject, string body, sbyte priority); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj new file mode 100644 index 000000000..ce5475fae --- /dev/null +++ b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + 3.0.0.0 + 3.0.0.0 + + + + + + + + + diff --git a/src/Ombi.Core/Models/UI/GotifyNotificationViewModel.cs b/src/Ombi.Core/Models/UI/GotifyNotificationViewModel.cs new file mode 100644 index 000000000..93ce66724 --- /dev/null +++ b/src/Ombi.Core/Models/UI/GotifyNotificationViewModel.cs @@ -0,0 +1,23 @@ + +using System.Collections.Generic; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.UI +{ + /// + /// The view model for the notification settings page + /// + /// + public class GotifyNotificationViewModel : GotifySettings + { + /// + /// Gets or sets the notification templates. + /// + /// + /// The notification templates. + /// + public List NotificationTemplates { get; set; } + + } +} diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 68a363706..69e6bd3ca 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -32,6 +32,7 @@ using Ombi.Api.CouchPotato; using Ombi.Api.DogNzb; using Ombi.Api.FanartTv; using Ombi.Api.Github; +using Ombi.Api.Gotify; using Ombi.Api.Lidarr; using Ombi.Api.Mattermost; using Ombi.Api.Notifications; @@ -120,6 +121,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -170,6 +172,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.Helpers/LoggingEvents.cs b/src/Ombi.Helpers/LoggingEvents.cs index 3893dc879..0723800ab 100644 --- a/src/Ombi.Helpers/LoggingEvents.cs +++ b/src/Ombi.Helpers/LoggingEvents.cs @@ -32,6 +32,7 @@ namespace Ombi.Helpers public static EventId MattermostNotification => new EventId(4004); public static EventId PushoverNotification => new EventId(4005); public static EventId TelegramNotifcation => new EventId(4006); + public static EventId GotifyNotification => new EventId(4007); public static EventId TvSender => new EventId(5000); public static EventId SonarrSender => new EventId(5001); diff --git a/src/Ombi.Helpers/NotificationAgent.cs b/src/Ombi.Helpers/NotificationAgent.cs index 8990eeba9..18f28105a 100644 --- a/src/Ombi.Helpers/NotificationAgent.cs +++ b/src/Ombi.Helpers/NotificationAgent.cs @@ -10,5 +10,6 @@ Slack = 5, Mattermost = 6, Mobile = 7, + Gotify = 8, } } \ No newline at end of file diff --git a/src/Ombi.Mapping/Profiles/SettingsProfile.cs b/src/Ombi.Mapping/Profiles/SettingsProfile.cs index 139290f2b..f460ce78b 100644 --- a/src/Ombi.Mapping/Profiles/SettingsProfile.cs +++ b/src/Ombi.Mapping/Profiles/SettingsProfile.cs @@ -19,6 +19,7 @@ namespace Ombi.Mapping.Profiles CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/GotifyNotification.cs b/src/Ombi.Notifications/Agents/GotifyNotification.cs new file mode 100644 index 000000000..e1c9fc1db --- /dev/null +++ b/src/Ombi.Notifications/Agents/GotifyNotification.cs @@ -0,0 +1,116 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Ombi.Api.Gotify; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Notifications.Models; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Notifications.Agents +{ + public class GotifyNotification : BaseNotification, IGotifyNotification + { + public GotifyNotification(IGotifyApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + { + Api = api; + Logger = log; + } + + public override string NotificationName => "GotifyNotification"; + + private IGotifyApi Api { get; } + private ILogger Logger { get; } + + protected override bool ValidateConfiguration(GotifySettings settings) + { + return settings.Enabled && !string.IsNullOrEmpty(settings.BaseUrl) && !string.IsNullOrEmpty(settings.ApplicationToken); + } + + protected override async Task NewRequest(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.NewRequest); + } + + + protected override async Task NewIssue(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.Issue); + } + + protected override async Task IssueComment(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.IssueComment); + } + + protected override async Task IssueResolved(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.IssueResolved); + } + + protected override async Task AddedToRequestQueue(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); + } + + protected override async Task RequestDeclined(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.RequestDeclined); + } + + protected override async Task RequestApproved(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.RequestApproved); + } + + protected override async Task AvailableRequest(NotificationOptions model, GotifySettings settings) + { + await Run(model, settings, NotificationType.RequestAvailable); + } + + protected override async Task Send(NotificationMessage model, GotifySettings settings) + { + try + { + await Api.PushAsync(settings.BaseUrl, settings.ApplicationToken, model.Subject, model.Message, settings.Priority); + } + catch (Exception e) + { + Logger.LogError(LoggingEvents.GotifyNotification, e, "Failed to send Gotify notification"); + } + } + + protected override async Task Test(NotificationOptions model, GotifySettings settings) + { + var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; + var notification = new NotificationMessage + { + Message = message, + }; + await Send(notification, settings); + } + + private async Task Run(NotificationOptions model, GotifySettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Gotify, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Gotify}"); + return; + } + + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + await Send(notification, settings); + } + } +} diff --git a/src/Ombi.Notifications/Agents/Interfaces/IGotifyNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/IGotifyNotification.cs new file mode 100644 index 000000000..a85421938 --- /dev/null +++ b/src/Ombi.Notifications/Agents/Interfaces/IGotifyNotification.cs @@ -0,0 +1,6 @@ +namespace Ombi.Notifications.Agents +{ + public interface IGotifyNotification : INotification + { + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 2b5c95154..3fa4b4830 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/Notifications/GotifySettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/GotifySettings.cs new file mode 100644 index 000000000..f0325b0f2 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/Notifications/GotifySettings.cs @@ -0,0 +1,10 @@ +namespace Ombi.Settings.Settings.Models.Notifications +{ + public class GotifySettings : Settings + { + public bool Enabled { get; set; } + public string BaseUrl { get; set; } + public string ApplicationToken { get; set; } + public sbyte Priority { get; set; } = 4; + } +} \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index 2b9be2c42..f4f683c11 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -96,7 +96,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Notifications", "O EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Lidarr", "Ombi.Api.Lidarr\Ombi.Api.Lidarr.csproj", "{4FA21A20-92F4-462C-B929-2C517A88CC56}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Helpers.Tests", "Ombi.Helpers.Tests\Ombi.Helpers.Tests.csproj", "{CC8CEFCD-0CB6-45BB-845F-508BCAB5BDC3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Helpers.Tests", "Ombi.Helpers.Tests\Ombi.Helpers.Tests.csproj", "{CC8CEFCD-0CB6-45BB-845F-508BCAB5BDC3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Gotify", "Ombi.Api.Gotify\Ombi.Api.Gotify.csproj", "{105EA346-766E-45B8-928B-DE6991DCB7EB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -256,6 +258,10 @@ Global {CC8CEFCD-0CB6-45BB-845F-508BCAB5BDC3}.Debug|Any CPU.Build.0 = Debug|Any CPU {CC8CEFCD-0CB6-45BB-845F-508BCAB5BDC3}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC8CEFCD-0CB6-45BB-845F-508BCAB5BDC3}.Release|Any CPU.Build.0 = Release|Any CPU + {105EA346-766E-45B8-928B-DE6991DCB7EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {105EA346-766E-45B8-928B-DE6991DCB7EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {105EA346-766E-45B8-928B-DE6991DCB7EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {105EA346-766E-45B8-928B-DE6991DCB7EB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -293,6 +299,7 @@ Global {10D1FE9D-9124-42B7-B1E1-CEB99B832618} = {9293CA11-360A-4C20-A674-B9E794431BF5} {4FA21A20-92F4-462C-B929-2C517A88CC56} = {9293CA11-360A-4C20-A674-B9E794431BF5} {CC8CEFCD-0CB6-45BB-845F-508BCAB5BDC3} = {6F42AB98-9196-44C4-B888-D5E409F415A1} + {105EA346-766E-45B8-928B-DE6991DCB7EB} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts index f368ee035..5472a6c7c 100644 --- a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts @@ -93,6 +93,14 @@ export interface IPushoverNotificationSettings extends INotificationSettings { sound: string; } +export interface IGotifyNotificationSettings extends INotificationSettings { + accessToken: string; + notificationTemplates: INotificationTemplates[]; + baseUrl: string; + applicationToken: string; + priority: number; +} + export interface IMattermostNotifcationSettings extends INotificationSettings { webhookUrl: string; username: string; diff --git a/src/Ombi/ClientApp/app/services/applications/tester.service.ts b/src/Ombi/ClientApp/app/services/applications/tester.service.ts index e692b9196..af619d583 100644 --- a/src/Ombi/ClientApp/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/tester.service.ts @@ -11,6 +11,7 @@ import { IDiscordNotifcationSettings, IEmailNotificationSettings, IEmbyServer, + IGotifyNotificationSettings, ILidarrSettings, IMattermostNotifcationSettings, IMobileNotificationTestSettings, @@ -40,7 +41,11 @@ export class TesterService extends ServiceHelpers { } public pushoverTest(settings: IPushoverNotificationSettings): Observable { - return this.http.post(`${this.url}pushover`, JSON.stringify(settings), {headers: this.headers}); + return this.http.post(`${this.url}pushover`, JSON.stringify(settings), { headers: this.headers }); + } + + public gotifyTest(settings: IGotifyNotificationSettings): Observable { + return this.http.post(`${this.url}gotify`, JSON.stringify(settings), { headers: this.headers }); } public mattermostTest(settings: IMattermostNotifcationSettings): Observable { diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 64a6edd14..a80cfd772 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -14,6 +14,7 @@ import { IDogNzbSettings, IEmailNotificationSettings, IEmbySettings, + IGotifyNotificationSettings, IIssueSettings, IJobSettings, IJobSettingsViewModel, @@ -182,6 +183,14 @@ export class SettingsService extends ServiceHelpers { .post(`${this.url}/notifications/pushover`, JSON.stringify(settings), {headers: this.headers}); } + public getGotifyNotificationSettings(): Observable { + return this.http.get(`${this.url}/notifications/gotify`, { headers: this.headers }); + } + public saveGotifyNotificationSettings(settings: IGotifyNotificationSettings): Observable { + return this.http + .post(`${this.url}/notifications/gotify`, JSON.stringify(settings), { headers: this.headers }); + } + public getSlackNotificationSettings(): Observable { return this.http.get(`${this.url}/notifications/slack`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/notifications/gotify.component.html b/src/Ombi/ClientApp/app/settings/notifications/gotify.component.html new file mode 100644 index 000000000..9148cb880 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/notifications/gotify.component.html @@ -0,0 +1,67 @@ + + +
+
+ Gotify Notifications +
+
+ +
+
+ + +
+
+ +
+ + + + The Base URL is required +
+ +
+ + + + The Application Token is required +
+ +
+ +
+ +
+
+ + +
+
+ +
+
+ + + +
+
+ +
+
+ +
+ + +
+ +
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/notifications/gotify.component.ts b/src/Ombi/ClientApp/app/settings/notifications/gotify.component.ts new file mode 100644 index 000000000..f6c08d41b --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/notifications/gotify.component.ts @@ -0,0 +1,68 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { IGotifyNotificationSettings, INotificationTemplates, NotificationType } from "../../interfaces"; +import { TesterService } from "../../services"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./gotify.component.html", +}) +export class GotifyComponent implements OnInit { + public NotificationType = NotificationType; + public templates: INotificationTemplates[]; + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private fb: FormBuilder, + private testerService: TesterService) { } + + public ngOnInit() { + this.settingsService.getGotifyNotificationSettings().subscribe(x => { + this.templates = x.notificationTemplates; + + this.form = this.fb.group({ + enabled: [x.enabled], + baseUrl: [x.baseUrl, [Validators.required]], + applicationToken: [x.applicationToken, [Validators.required]], + priority: [x.priority], + }); + }); + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + settings.notificationTemplates = this.templates; + + this.settingsService.saveGotifyNotificationSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Gotify settings"); + } else { + this.notificationService.success("There was an error when saving the Gotify settings"); + } + }); + + } + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + this.testerService.gotifyTest(form.value).subscribe(x => { + if (x) { + this.notificationService.success("Successfully sent a Gotify message"); + } else { + this.notificationService.error("There was an error when sending the Gotify message. Please check your settings"); + } + }); + } +} diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index fb1a10abe..6fb69dc27 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -27,6 +27,7 @@ import { LidarrComponent } from "./lidarr/lidarr.component"; import { MassEmailComponent } from "./massemail/massemail.component"; import { DiscordComponent } from "./notifications/discord.component"; import { EmailNotificationComponent } from "./notifications/emailnotification.component"; +import { GotifyComponent } from "./notifications/gotify.component"; import { MattermostComponent } from "./notifications/mattermost.component"; import { MobileComponent } from "./notifications/mobile.component"; import { NewsletterComponent } from "./notifications/newsletter.component"; @@ -63,6 +64,7 @@ const routes: Routes = [ { path: "Slack", component: SlackComponent, canActivate: [AuthGuard] }, { path: "Pushover", component: PushoverComponent, canActivate: [AuthGuard] }, { path: "Pushbullet", component: PushbulletComponent, canActivate: [AuthGuard] }, + { path: "Gotify", component: GotifyComponent, canActivate: [AuthGuard] }, { path: "Mattermost", component: MattermostComponent, canActivate: [AuthGuard] }, { path: "UserManagement", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "Update", component: UpdateComponent, canActivate: [AuthGuard] }, @@ -117,6 +119,7 @@ const routes: Routes = [ PushoverComponent, MattermostComponent, PushbulletComponent, + GotifyComponent, UserManagementComponent, UpdateComponent, AboutComponent, diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index 91405d1c5..81f901ecc 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -74,6 +74,7 @@
  • Pushover
  • Mattermost
  • Telegram
  • +
  • Gotify
  • diff --git a/src/Ombi/Controllers/External/TesterController.cs b/src/Ombi/Controllers/External/TesterController.cs index 5e3156bde..2894542f6 100644 --- a/src/Ombi/Controllers/External/TesterController.cs +++ b/src/Ombi/Controllers/External/TesterController.cs @@ -40,7 +40,7 @@ namespace Ombi.Controllers.External IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm, IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, IMobileNotification mobileNotification, - ILidarrApi lidarrApi) + ILidarrApi lidarrApi, IGotifyNotification gotifyNotification) { Service = service; DiscordNotification = notification; @@ -61,6 +61,7 @@ namespace Ombi.Controllers.External Newsletter = newsletter; MobileNotification = mobileNotification; LidarrApi = lidarrApi; + GotifyNotification = gotifyNotification; } private INotificationService Service { get; } @@ -69,6 +70,7 @@ namespace Ombi.Controllers.External private IPushbulletNotification PushbulletNotification { get; } private ISlackNotification SlackNotification { get; } private IPushoverNotification PushoverNotification { get; } + private IGotifyNotification GotifyNotification { get; } private IMattermostNotification MattermostNotification { get; } private IPlexApi PlexApi { get; } private IRadarrApi RadarrApi { get; } @@ -155,6 +157,30 @@ namespace Ombi.Controllers.External } + /// + /// Sends a test message to Gotify using the provided settings + /// + /// The settings. + /// + [HttpPost("gotify")] + public bool Gotify([FromBody] GotifySettings settings) + { + try + { + settings.Enabled = true; + GotifyNotification.NotifyAsync( + new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1 }, settings); + + return true; + } + catch (Exception e) + { + Log.LogError(LoggingEvents.Api, e, "Could not test Gotify"); + return false; + } + + } + /// /// Sends a test message to mattermost using the provided settings /// diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index b5ec57e29..823461e35 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -947,6 +947,40 @@ namespace Ombi.Controllers return model; } + /// + /// Saves the gotify notification settings. + /// + /// The model. + /// + [HttpPost("notifications/gotify")] + public async Task GotifyNotificationSettings([FromBody] GotifyNotificationViewModel model) + { + // Save the email settings + var settings = Mapper.Map(model); + var result = await Save(settings); + + // Save the templates + await TemplateRepository.UpdateRange(model.NotificationTemplates); + + return result; + } + + /// + /// Gets the gotify Notification Settings. + /// + /// + [HttpGet("notifications/gotify")] + public async Task GotifyNotificationSettings() + { + var settings = await Get(); + var model = Mapper.Map(settings); + + // Lookup to see if we have any templates saved + model.NotificationTemplates = BuildTemplates(NotificationAgent.Gotify); + + return model; + } + /// /// Saves the Newsletter notification settings. /// From 41d96238975b663a92664507ef62d09e153ece74 Mon Sep 17 00:00:00 2001 From: Guillaume Taquet Gasperini Date: Wed, 20 Mar 2019 19:57:21 +0100 Subject: [PATCH 307/325] Fix cake build by setting Incubator version --- build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cake b/build.cake index e8e4bb8c0..c25447906 100644 --- a/build.cake +++ b/build.cake @@ -3,7 +3,7 @@ #addin "Cake.Gulp" #addin "SharpZipLib" #addin nuget:?package=Cake.Compression&version=0.1.4 -#addin "Cake.Incubator" +#addin "Cake.Incubator&version=3.1.0" #addin "Cake.Yarn" ////////////////////////////////////////////////////////////////////// From 4920ac3da0ce947f522e8ec01b283e608f6f88ec Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 21 Mar 2019 15:33:10 +0000 Subject: [PATCH 308/325] Take out the lastlogindate update for now #2750 --- src/Ombi/Controllers/TokenController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 44ec5686f..6604c6dbb 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -124,7 +124,7 @@ namespace Ombi.Controllers } user.LastLoggedIn = DateTime.UtcNow; - await _userManager.UpdateAsync(user); + //await _userManager.UpdateAsync(user); var claims = new List { From 826517cbfff0db35ee51ab858cab5a8f198d9d10 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 21 Mar 2019 15:34:22 +0000 Subject: [PATCH 309/325] !wip --- src/Ombi/Controllers/TokenController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 9499dd493..9f9747f0e 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -150,7 +150,7 @@ namespace Ombi.Controllers } user.LastLoggedIn = DateTime.UtcNow; - await GlobalMutex.Lock(async () => await _userManager.UpdateAsync(user)).ConfigureAwait(false); + //await GlobalMutex.Lock(async () => await _userManager.UpdateAsync(user)).ConfigureAwait(false); return new JsonResult(new { From cf9bb889edaf4afa34c4504808432b07ca061672 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 22 Mar 2019 22:31:11 +0000 Subject: [PATCH 310/325] Fixed the issue where it was not picking up roles until the JWT was refreshed --- .../Rule/Request/CanRequestRuleTests.cs | 1 + .../Rule/Rules/Request/AutoApproveRule.cs | 21 +++++++----- .../Rule/Rules/Request/CanRequestRule.cs | 34 +++++++++++-------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs index c9db5875a..69b6a76df 100644 --- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Moq; using NUnit.Framework; using Ombi.Core.Rule.Rules; +using Ombi.Core.Rule.Rules.Request; using Ombi.Helpers; using Ombi.Store.Entities.Requests; diff --git a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs index a55868db8..685f02b54 100644 --- a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs @@ -1,5 +1,7 @@ using System.Security.Principal; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; @@ -10,28 +12,31 @@ namespace Ombi.Core.Rule.Rules.Request { public class AutoApproveRule : BaseRequestRule, IRules { - public AutoApproveRule(IPrincipal principal) + public AutoApproveRule(IPrincipal principal, OmbiUserManager um) { User = principal; + _manager = um; } private IPrincipal User { get; } + private readonly OmbiUserManager _manager; - public Task Execute(BaseRequest obj) + public async Task Execute(BaseRequest obj) { - if (User.IsInRole(OmbiRoles.Admin)) + var user = await _manager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin)) { obj.Approved = true; - return Task.FromResult(Success()); + return Success(); } - if (obj.RequestType == RequestType.Movie && User.IsInRole(OmbiRoles.AutoApproveMovie)) + if (obj.RequestType == RequestType.Movie && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie)) obj.Approved = true; - if (obj.RequestType == RequestType.TvShow && User.IsInRole(OmbiRoles.AutoApproveTv)) + if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv)) obj.Approved = true; - if (obj.RequestType == RequestType.Album && User.IsInRole(OmbiRoles.AutoApproveMusic)) + if (obj.RequestType == RequestType.Album && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMusic)) obj.Approved = true; - return Task.FromResult(Success()); // We don't really care, we just don't set the obj to approve + return Success(); // We don't really care, we just don't set the obj to approve } } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs index 1cdf03955..a2c70fcc5 100644 --- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs @@ -1,46 +1,52 @@ -using Ombi.Store.Entities; +using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; using Ombi.Core.Rule.Interfaces; using Ombi.Helpers; +using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; -namespace Ombi.Core.Rule.Rules +namespace Ombi.Core.Rule.Rules.Request { public class CanRequestRule : BaseRequestRule, IRules { - public CanRequestRule(IPrincipal principal) + public CanRequestRule(IPrincipal principal, OmbiUserManager manager) { User = principal; + _manager = manager; } private IPrincipal User { get; } + private readonly OmbiUserManager _manager; - public Task Execute(BaseRequest obj) + public async Task Execute(BaseRequest obj) { - if (User.IsInRole(OmbiRoles.Admin)) - return Task.FromResult(Success()); + var user = await _manager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin)) + return Success(); if (obj.RequestType == RequestType.Movie) { - if (User.IsInRole(OmbiRoles.RequestMovie) || User.IsInRole(OmbiRoles.AutoApproveMovie)) - return Task.FromResult(Success()); - return Task.FromResult(Fail("You do not have permissions to Request a Movie")); + if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMovie) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie)) + return Success(); + return Fail("You do not have permissions to Request a Movie"); } if (obj.RequestType == RequestType.TvShow) { - if (User.IsInRole(OmbiRoles.RequestTv) || User.IsInRole(OmbiRoles.AutoApproveTv)) - return Task.FromResult(Success()); + if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestTv) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv)) + return Success(); } if (obj.RequestType == RequestType.Album) { - if (User.IsInRole(OmbiRoles.RequestMusic) || User.IsInRole(OmbiRoles.AutoApproveMusic)) - return Task.FromResult(Success()); + if (await _manager.IsInRoleAsync(user, OmbiRoles.RequestMusic) || await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMusic)) + return Success(); } - return Task.FromResult(Fail("You do not have permissions to Request a TV Show")); + return Fail("You do not have permissions to Request a TV Show"); } } } \ No newline at end of file From 89e275df744ded175fec2492e1282c8045ccc563 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 23 Mar 2019 00:08:04 +0000 Subject: [PATCH 311/325] Update JobSetup.cs --- src/Ombi.Schedule/JobSetup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index 38686396f..811f5ca42 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -81,7 +81,7 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); - RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s)); + // RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s)); RecurringJob.AddOrUpdate(() => _mediaDatabaseRefresh.Start(), JobSettingsHelper.MediaDatabaseRefresh(s)); } From 775e18e2d3e6efc163ce65630aeb5e830df1d08d Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 25 Mar 2019 08:25:18 +0000 Subject: [PATCH 312/325] Fixed #2803 in regards to the Request Button showing up. Still need to investiagte the availability side of things --- src/Ombi/ClientApp/app/search/music/albumsearch.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html index 8f2fe73ce..2b31df040 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html @@ -80,7 +80,7 @@ {{ 'Common.Available' | translate }}
    -
    +
    From 42662924d94097fdd76fa83c09d1b2f30f69e7f2 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 25 Mar 2019 08:31:31 +0000 Subject: [PATCH 313/325] Removed the auditing, was not used anyway #2750 --- src/Ombi.Core/Engine/TvRequestEngine.cs | 16 +++------ src/Ombi/package-lock.json | 47 ++++++++----------------- 2 files changed, 18 insertions(+), 45 deletions(-) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 58144d3ce..1cb0ad65a 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -31,14 +31,13 @@ namespace Ombi.Core.Engine { public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user, INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, - ITvSender sender, IAuditRepository audit, IRepository rl, ISettingsService settings, ICacheService cache, + ITvSender sender, IRepository rl, ISettingsService settings, ICacheService cache, IRepository sub) : base(user, requestService, rule, manager, cache, settings, sub) { TvApi = tvApi; MovieDbApi = movApi; NotificationHelper = helper; TvSender = sender; - Audit = audit; _requestLog = rl; } @@ -46,7 +45,6 @@ namespace Ombi.Core.Engine private ITvMazeApi TvApi { get; } private IMovieDbApi MovieDbApi { get; } private ITvSender TvSender { get; } - private IAuditRepository Audit { get; } private readonly IRepository _requestLog; public async Task RequestTvShow(TvRequestViewModel tv) @@ -351,7 +349,6 @@ namespace Ombi.Core.Engine public async Task UpdateTvRequest(TvRequests request) { - await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username); var allRequests = TvRepository.Get(); var results = await allRequests.FirstOrDefaultAsync(x => x.Id == request.Id); @@ -394,7 +391,6 @@ namespace Ombi.Core.Engine if (request.Approved) { NotificationHelper.Notify(request, NotificationType.RequestApproved); - await Audit.Record(AuditType.Approved, AuditArea.TvRequest, $"Approved Request {request.Title}", Username); // Autosend await TvSender.Send(request); } @@ -426,9 +422,7 @@ namespace Ombi.Core.Engine public async Task UpdateChildRequest(ChildRequests request) { - await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username); - - await TvRepository.UpdateChild(request); + await TvRepository.UpdateChild(request); return request; } @@ -446,16 +440,14 @@ namespace Ombi.Core.Engine // Delete the parent TvRepository.Db.TvRequests.Remove(parent); } - await Audit.Record(AuditType.Deleted, AuditArea.TvRequest, $"Deleting Request {request.Title}", Username); - + await TvRepository.Db.SaveChangesAsync(); } public async Task RemoveTvRequest(int requestId) { var request = await TvRepository.Get().FirstOrDefaultAsync(x => x.Id == requestId); - await Audit.Record(AuditType.Deleted, AuditArea.TvRequest, $"Deleting Request {request.Title}", Username); - await TvRepository.Delete(request); + await TvRepository.Delete(request); } public async Task UserHasRequest(string userId) diff --git a/src/Ombi/package-lock.json b/src/Ombi/package-lock.json index 4ad391ab8..fff834922 100644 --- a/src/Ombi/package-lock.json +++ b/src/Ombi/package-lock.json @@ -1766,9 +1766,9 @@ } }, "bootstrap": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.0.tgz", - "integrity": "sha512-F1yTDO9OHKH0xjl03DsOe8Nu1OWBIeAugGMhy3UTIYDdbbIPesQIhCEbj+HEr6wqlwweGAlP8F3OBC6kEuhFuw==" + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", + "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==" }, "bootswatch": { "version": "3.4.0", @@ -4190,8 +4190,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -4209,13 +4208,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4228,18 +4225,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -4342,8 +4336,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -4353,7 +4346,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4366,20 +4358,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4396,7 +4385,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -4469,8 +4457,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -4480,7 +4467,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -4556,8 +4542,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -4587,7 +4572,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4605,7 +4589,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4644,13 +4627,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, From e6e24c6a97447ca2a8762eaee4c24539395183ff Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 25 Mar 2019 08:41:15 +0000 Subject: [PATCH 314/325] More for #2750 --- src/Ombi.Store/Repository/BaseRepository.cs | 2 +- .../Repository/EmbyContentRepository.cs | 7 +++--- .../NotificationTemplatesRepository.cs | 11 +++++++--- .../Repository/PlexContentRepository.cs | 10 ++++----- .../Requests/MovieRequestRepository.cs | 10 +++++++-- .../Requests/MusicRequestRepository.cs | 9 ++++++-- .../Requests/TvRequestRepository.cs | 22 ++++++++++++------- .../Repository/SettingsJsonRepository.cs | 9 ++++++-- src/Ombi.Store/Repository/TokenRepository.cs | 7 +++++- 9 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index ca2937291..1ca78ee50 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -81,7 +81,7 @@ namespace Ombi.Store.Repository await _ctx.Database.ExecuteSqlCommandAsync(sql); } - private async Task InternalSaveChanges() + protected async Task InternalSaveChanges() { return await GlobalMutex.Lock(async () => await _ctx.SaveChangesAsync()); } diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index 4d32e8da2..2ada709ab 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -72,7 +72,7 @@ namespace Ombi.Store.Repository public async Task Update(EmbyContent existingContent) { Db.EmbyContent.Update(existingContent); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public IQueryable GetAllEpisodes() @@ -83,7 +83,7 @@ namespace Ombi.Store.Repository public async Task Add(EmbyEpisode content) { await Db.EmbyEpisode.AddAsync(content); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); return content; } public async Task GetEpisodeByEmbyId(string key) @@ -94,12 +94,13 @@ namespace Ombi.Store.Repository public async Task AddRange(IEnumerable content) { Db.EmbyEpisode.AddRange(content); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public void UpdateWithoutSave(EmbyContent existingContent) { Db.EmbyContent.Update(existingContent); } + } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs b/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs index 175d0e6a9..eb4816d50 100644 --- a/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs +++ b/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs @@ -45,7 +45,7 @@ namespace Ombi.Store.Repository Db.Attach(template); Db.Entry(template).State = EntityState.Modified; } - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task UpdateRange(IEnumerable templates) @@ -56,16 +56,21 @@ namespace Ombi.Store.Repository Db.Attach(t); Db.Entry(t).State = EntityState.Modified; } - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task Insert(NotificationTemplates entity) { var settings = await Db.NotificationTemplates.AddAsync(entity).ConfigureAwait(false); - await Db.SaveChangesAsync().ConfigureAwait(false); + await InternalSaveChanges().ConfigureAwait(false); return settings.Entity; } + private async Task InternalSaveChanges() + { + return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); + } + private bool _disposed; // Protected implementation of Dispose pattern. protected virtual void Dispose(bool disposing) diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index 2c9c28d09..37275a47c 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -96,7 +96,7 @@ namespace Ombi.Store.Repository public async Task Update(PlexServerContent existingContent) { Db.PlexServerContent.Update(existingContent); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public void UpdateWithoutSave(PlexServerContent existingContent) { @@ -106,7 +106,7 @@ namespace Ombi.Store.Repository public async Task UpdateRange(IEnumerable existingContent) { Db.PlexServerContent.UpdateRange(existingContent); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public IQueryable GetAllEpisodes() @@ -127,14 +127,14 @@ namespace Ombi.Store.Repository public async Task Add(PlexEpisode content) { await Db.PlexEpisode.AddAsync(content); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); return content; } public async Task DeleteEpisode(PlexEpisode content) { Db.PlexEpisode.Remove(content); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task GetEpisodeByKey(int key) @@ -144,7 +144,7 @@ namespace Ombi.Store.Repository public async Task AddRange(IEnumerable content) { Db.PlexEpisode.AddRange(content); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs index d4a550528..d96363d29 100644 --- a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Ombi.Helpers; using Ombi.Store.Context; using Ombi.Store.Entities.Requests; @@ -70,12 +71,17 @@ namespace Ombi.Store.Repository.Requests Db.MovieRequests.Attach(request); Db.Update(request); } - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task Save() { - await Db.SaveChangesAsync(); + await InternalSaveChanges(); + } + + private async Task InternalSaveChanges() + { + return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs b/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs index 59edf265a..5179513d2 100644 --- a/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Ombi.Helpers; using Ombi.Store.Context; using Ombi.Store.Entities.Requests; @@ -61,12 +62,16 @@ namespace Ombi.Store.Repository.Requests Db.AlbumRequests.Attach(request); Db.Update(request); } - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task Save() { - await Db.SaveChangesAsync(); + await InternalSaveChanges(); + } + private async Task InternalSaveChanges() + { + return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs index daac7d4df..d3486358a 100644 --- a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Ombi.Helpers; using Ombi.Store.Context; using Ombi.Store.Entities.Requests; @@ -101,20 +102,20 @@ namespace Ombi.Store.Repository.Requests public async Task Save() { - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task Add(TvRequests request) { await Db.TvRequests.AddAsync(request); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); return request; } public async Task AddChild(ChildRequests request) { await Db.ChildRequests.AddAsync(request); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); return request; } @@ -122,33 +123,38 @@ namespace Ombi.Store.Repository.Requests public async Task Delete(TvRequests request) { Db.TvRequests.Remove(request); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task DeleteChild(ChildRequests request) { Db.ChildRequests.Remove(request); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task DeleteChildRange(IEnumerable request) { Db.ChildRequests.RemoveRange(request); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task Update(TvRequests request) { Db.Update(request); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task UpdateChild(ChildRequests request) { Db.Update(request); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); + } + + private async Task InternalSaveChanges() + { + return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/SettingsJsonRepository.cs b/src/Ombi.Store/Repository/SettingsJsonRepository.cs index 66cf57b18..6140fd7a1 100644 --- a/src/Ombi.Store/Repository/SettingsJsonRepository.cs +++ b/src/Ombi.Store/Repository/SettingsJsonRepository.cs @@ -62,14 +62,14 @@ namespace Ombi.Store.Repository { //_cache.Remove(GetName(entity.SettingsName)); Db.Settings.Remove(entity); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public async Task UpdateAsync(GlobalSettings entity) { //_cache.Remove(GetName(entity.SettingsName)); Db.Update(entity); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public void Delete(GlobalSettings entity) @@ -91,6 +91,11 @@ namespace Ombi.Store.Repository return $"{entity}Json"; } + private async Task InternalSaveChanges() + { + return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); + } + private bool _disposed; protected virtual void Dispose(bool disposing) { diff --git a/src/Ombi.Store/Repository/TokenRepository.cs b/src/Ombi.Store/Repository/TokenRepository.cs index d766c5690..3f82e3948 100644 --- a/src/Ombi.Store/Repository/TokenRepository.cs +++ b/src/Ombi.Store/Repository/TokenRepository.cs @@ -4,6 +4,7 @@ using Ombi.Store.Entities; using System; using System.Linq; using System.Threading.Tasks; +using Ombi.Helpers; namespace Ombi.Store.Repository { @@ -19,12 +20,16 @@ namespace Ombi.Store.Repository public async Task CreateToken(Tokens token) { await Db.Tokens.AddAsync(token); - await Db.SaveChangesAsync(); + await InternalSaveChanges(); } public IQueryable GetToken(string tokenId) { return Db.Tokens.Where(x => x.Token == tokenId); } + private async Task InternalSaveChanges() + { + return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); + } } } From 5d9e6bd1130d7cebe2f8679bd161c046e4340896 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 25 Mar 2019 09:24:32 +0000 Subject: [PATCH 315/325] Fixed build !wip --- src/Ombi.Core/Engine/TvRequestEngine.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 1cb0ad65a..796e2fe6a 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -82,8 +82,6 @@ namespace Ombi.Core.Engine } } - await Audit.Record(AuditType.Added, AuditArea.TvRequest, $"Added Request {tvBuilder.ChildRequest.Title}", Username); - var existingRequest = await TvRepository.Get().FirstOrDefaultAsync(x => x.TvDbId == tv.TvDbId); if (existingRequest != null) { From 117bd1cd8b14a5d93c495139918631a30ca1d3f4 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Tue, 26 Mar 2019 12:12:58 +0000 Subject: [PATCH 316/325] #2750 stuff --- .../Authentication/OmbiUserManager.cs | 2 +- src/Ombi.DependencyInjection/IocExtensions.cs | 36 +++++++++---------- src/Ombi.Store/Context/OmbiContext.cs | 1 + src/Ombi/Startup.cs | 3 -- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/Ombi.Core/Authentication/OmbiUserManager.cs b/src/Ombi.Core/Authentication/OmbiUserManager.cs index 2c78f39bf..6155672b3 100644 --- a/src/Ombi.Core/Authentication/OmbiUserManager.cs +++ b/src/Ombi.Core/Authentication/OmbiUserManager.cs @@ -158,7 +158,7 @@ namespace Ombi.Core.Authentication if (!email.Equals(result.User?.Email)) { user.Email = result.User?.Email; - await UpdateAsync(user); + await GlobalMutex.Lock(async () => await UpdateAsync(user)); } return true; diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 69e6bd3ca..466b74bb0 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -134,28 +134,28 @@ namespace Ombi.DependencyInjection } public static void RegisterStore(this IServiceCollection services) { - services.AddEntityFrameworkSqlite().AddDbContext(); - services.AddEntityFrameworkSqlite().AddDbContext(); - services.AddEntityFrameworkSqlite().AddDbContext(); + services.AddDbContext(); + services.AddDbContext(); + services.AddDbContext(); services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 services.AddScoped(); // https://docs.microsoft.com/en-us/aspnet/core/data/entity-framework-6 - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(typeof(ISettingsService<>), typeof(SettingsService<>)); - services.AddTransient(typeof(IRepository<>), typeof(Repository<>)); - services.AddTransient(typeof(IExternalRepository<>), typeof(ExternalRepository<>)); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(typeof(ISettingsService<>), typeof(SettingsService<>)); + services.AddScoped(typeof(IRepository<>), typeof(Repository<>)); + services.AddScoped(typeof(IExternalRepository<>), typeof(ExternalRepository<>)); } public static void RegisterServices(this IServiceCollection services) { @@ -163,7 +163,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddSingleton(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 2f19bc681..98f4cd9c3 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -17,6 +17,7 @@ namespace Ombi.Store.Context { if (_created) return; + _created = true; Database.SetCommandTimeout(60); Database.Migrate(); diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index bbf56c517..fa70df147 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -56,9 +56,6 @@ namespace Ombi // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) { - // Add framework services. - services.AddDbContext(); - services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders() From a499782ec0dc445abdfd14c7f999c876df901b04 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 26 Mar 2019 22:12:47 +0000 Subject: [PATCH 317/325] Delete the schedules db on startup, we don't want it trying to recover the jobs --- src/Ombi/Program.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index f1809a2dc..2365f6748 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -49,6 +49,7 @@ namespace Ombi demoInstance.Demo = demo; instance.StoragePath = storagePath ?? string.Empty; // Check if we need to migrate the settings + DeleteSchedules(); CheckAndMigrate(); var ctx = new SettingsContext(); var config = ctx.ApplicationConfigurations.ToList(); @@ -97,6 +98,20 @@ namespace Ombi CreateWebHostBuilder(args).Build().Run(); } + private static void DeleteSchedules() + { + try + { + if (File.Exists("Schedules.db")) + { + File.Delete("Schedules.db"); + } + } + catch (Exception) + { + } + } + /// /// This is to remove the Settings from the Ombi.db to the "new" /// OmbiSettings.db From 439dc395d05ba08ff0e06ba49bf0b4cfc69e160f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 27 Mar 2019 10:19:36 +0000 Subject: [PATCH 318/325] Reverted the global app lock for the db #2750 --- .../Rule/Request/AutoApproveRuleTests.cs | 3 +- .../Rule/Request/CanRequestRuleTests.cs | 2 +- .../Rule/Search/EmbyAvailabilityRuleTests.cs | 2 +- .../Authentication/OmbiUserManager.cs | 2 +- src/Ombi.Helpers/GlobalMutex.cs | 39 ------------------- src/Ombi.Store/Repository/BaseRepository.cs | 2 +- .../NotificationTemplatesRepository.cs | 2 +- .../Requests/MovieRequestRepository.cs | 5 --- .../Requests/MusicRequestRepository.cs | 4 -- .../Requests/TvRequestRepository.cs | 2 +- .../Repository/SettingsJsonRepository.cs | 2 +- src/Ombi.Store/Repository/TokenRepository.cs | 2 +- 12 files changed, 10 insertions(+), 57 deletions(-) delete mode 100644 src/Ombi.Helpers/GlobalMutex.cs diff --git a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs index 7ff8283da..34c21e008 100644 --- a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs @@ -4,6 +4,7 @@ using Moq; using Ombi.Core.Rule.Rules.Request; using Ombi.Store.Entities.Requests; using NUnit.Framework; +using Ombi.Core.Authentication; using Ombi.Helpers; namespace Ombi.Core.Tests.Rule.Request @@ -16,7 +17,7 @@ namespace Ombi.Core.Tests.Rule.Request { PrincipalMock = new Mock(); - Rule = new AutoApproveRule(PrincipalMock.Object); + Rule = new AutoApproveRule(PrincipalMock.Object, null); } diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs index 69b6a76df..f2781c8d2 100644 --- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs @@ -16,7 +16,7 @@ namespace Ombi.Core.Tests.Rule.Request { PrincipalMock = new Mock(); - Rule = new CanRequestRule(PrincipalMock.Object); + Rule = new CanRequestRule(PrincipalMock.Object, null); } diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index 99ff5b6bd..0171e37a1 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -16,7 +16,7 @@ namespace Ombi.Core.Tests.Rule.Search public void Setup() { ContextMock = new Mock(); - Rule = new EmbyAvailabilityRule(ContextMock.Object); + Rule = new EmbyAvailabilityRule(ContextMock.Object, null); } private EmbyAvailabilityRule Rule { get; set; } diff --git a/src/Ombi.Core/Authentication/OmbiUserManager.cs b/src/Ombi.Core/Authentication/OmbiUserManager.cs index 6155672b3..2c78f39bf 100644 --- a/src/Ombi.Core/Authentication/OmbiUserManager.cs +++ b/src/Ombi.Core/Authentication/OmbiUserManager.cs @@ -158,7 +158,7 @@ namespace Ombi.Core.Authentication if (!email.Equals(result.User?.Email)) { user.Email = result.User?.Email; - await GlobalMutex.Lock(async () => await UpdateAsync(user)); + await UpdateAsync(user); } return true; diff --git a/src/Ombi.Helpers/GlobalMutex.cs b/src/Ombi.Helpers/GlobalMutex.cs deleted file mode 100644 index 0164e888c..000000000 --- a/src/Ombi.Helpers/GlobalMutex.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Nito.AsyncEx; - -namespace Ombi.Helpers -{ - public static class GlobalMutex - { - public static async Task Lock(Func> func) - { - const string mutexId = "Global\\OMBI"; - using (var mutex = new Mutex(false, mutexId, out _)) - { - var hasHandle = false; - try - { - try - { - hasHandle = mutex.WaitOne(5000, false); - if (hasHandle == false) - throw new TimeoutException("Timeout waiting for exclusive access"); - } - catch (AbandonedMutexException) - { - hasHandle = true; - } - - return await func(); - } - finally - { - if (hasHandle) - mutex.ReleaseMutex(); - } - } - } - } -} diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index 1ca78ee50..0741a79b6 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -83,7 +83,7 @@ namespace Ombi.Store.Repository protected async Task InternalSaveChanges() { - return await GlobalMutex.Lock(async () => await _ctx.SaveChangesAsync()); + return await _ctx.SaveChangesAsync(); } diff --git a/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs b/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs index eb4816d50..8f3968dc0 100644 --- a/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs +++ b/src/Ombi.Store/Repository/NotificationTemplatesRepository.cs @@ -68,7 +68,7 @@ namespace Ombi.Store.Repository private async Task InternalSaveChanges() { - return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); + return await Db.SaveChangesAsync(); } private bool _disposed; diff --git a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs index d96363d29..2cea81200 100644 --- a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs @@ -78,10 +78,5 @@ namespace Ombi.Store.Repository.Requests { await InternalSaveChanges(); } - - private async Task InternalSaveChanges() - { - return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); - } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs b/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs index 5179513d2..971d53b39 100644 --- a/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/MusicRequestRepository.cs @@ -69,9 +69,5 @@ namespace Ombi.Store.Repository.Requests { await InternalSaveChanges(); } - private async Task InternalSaveChanges() - { - return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); - } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs index d3486358a..91e885b37 100644 --- a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs @@ -154,7 +154,7 @@ namespace Ombi.Store.Repository.Requests private async Task InternalSaveChanges() { - return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); + return await Db.SaveChangesAsync(); } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/SettingsJsonRepository.cs b/src/Ombi.Store/Repository/SettingsJsonRepository.cs index 6140fd7a1..909a68480 100644 --- a/src/Ombi.Store/Repository/SettingsJsonRepository.cs +++ b/src/Ombi.Store/Repository/SettingsJsonRepository.cs @@ -93,7 +93,7 @@ namespace Ombi.Store.Repository private async Task InternalSaveChanges() { - return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); + return await Db.SaveChangesAsync(); } private bool _disposed; diff --git a/src/Ombi.Store/Repository/TokenRepository.cs b/src/Ombi.Store/Repository/TokenRepository.cs index 3f82e3948..d0a501bd5 100644 --- a/src/Ombi.Store/Repository/TokenRepository.cs +++ b/src/Ombi.Store/Repository/TokenRepository.cs @@ -29,7 +29,7 @@ namespace Ombi.Store.Repository } private async Task InternalSaveChanges() { - return await GlobalMutex.Lock(async () => await Db.SaveChangesAsync()); + return await Db.SaveChangesAsync(); } } } From b0dff349957df35247c2ce989c122910ff28d66a Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 29 Mar 2019 12:07:10 +0000 Subject: [PATCH 319/325] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 61cda24f3..77f454e1d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,15 @@ ____ [![Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://patreon.com/tidusjar/Ombi) [![Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://paypal.me/PlexRequestsNet) +___ + +[![Twitter](https://img.shields.io/twitter/follow/tidusjar.svg?style=social)](https://img.shields.io/twitter/follow/tidusjar.svg?style=social) + +Follow me developing Ombi! + +[![Twitch](https://img.shields.io/badge/Twitch-Watch-blue.svg?style=flat-square&logo=twitch)](https://twitch.tv/tiusjar) + + ___ Get it on Google Play From 0e8859394b03f17c503e82308426966e28407279 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 29 Mar 2019 12:07:48 +0000 Subject: [PATCH 320/325] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 77f454e1d..79aba2c3a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ____ ___ -[![Twitter](https://img.shields.io/twitter/follow/tidusjar.svg?style=social)](https://img.shields.io/twitter/follow/tidusjar.svg?style=social) +[![Twitter](https://img.shields.io/twitter/follow/tidusjar.svg?style=social)](https://twitter.com/intent/follow?screen_name=tidusjar) Follow me developing Ombi! From 78395a38f7be433b6badf631245a33e0fa658280 Mon Sep 17 00:00:00 2001 From: PotatoQuality Date: Thu, 4 Apr 2019 20:21:05 +0200 Subject: [PATCH 321/325] Fix for broken twitch url in readme file Fixing the twitch url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79aba2c3a..e34e74aa8 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ ___ Follow me developing Ombi! -[![Twitch](https://img.shields.io/badge/Twitch-Watch-blue.svg?style=flat-square&logo=twitch)](https://twitch.tv/tiusjar) +[![Twitch](https://img.shields.io/badge/Twitch-Watch-blue.svg?style=flat-square&logo=twitch)](https://www.twitch.tv/tidusjar) ___ From c556334f79d2f83ac6f415c31a5093405565d069 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 6 Apr 2019 21:43:26 +0100 Subject: [PATCH 322/325] Fixed #2910 --- src/Ombi.Helpers/CacheService.cs | 57 +++++++++---------- .../Jobs/Ombi/MediaDatabaseRefresh.cs | 1 + src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 ++ .../Jobs/Plex/PlexContentSync.cs | 1 + .../Jobs/Plex/PlexEpisodeSync.cs | 1 + .../Jobs/Plex/PlexUserImporter.cs | 2 + src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 1 + .../Jobs/SickRage/SickRageSync.cs | 1 + src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 1 + 9 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/Ombi.Helpers/CacheService.cs b/src/Ombi.Helpers/CacheService.cs index 4eef62bda..ae57a9f61 100644 --- a/src/Ombi.Helpers/CacheService.cs +++ b/src/Ombi.Helpers/CacheService.cs @@ -28,18 +28,15 @@ namespace Ombi.Helpers return result; } - using (await _mutex.LockAsync()) + if (_memoryCache.TryGetValue(cacheKey, out result)) { - if (_memoryCache.TryGetValue(cacheKey, out result)) - { - return result; - } - - result = await factory(); - _memoryCache.Set(cacheKey, result, absoluteExpiration); - return result; } + + result = await factory(); + _memoryCache.Set(cacheKey, result, absoluteExpiration); + + return result; } public void Remove(string key) @@ -47,34 +44,34 @@ namespace Ombi.Helpers _memoryCache.Remove(key); } - - - public T GetOrAdd(string cacheKey, Func factory, DateTime absoluteExpiration) + + + public T GetOrAdd(string cacheKey, Func factory, DateTime absoluteExpiration) + { + // locks get and set internally + if (_memoryCache.TryGetValue(cacheKey, out var result)) { - // locks get and set internally - if (_memoryCache.TryGetValue(cacheKey, out var result)) + return result; + } + + lock (TypeLock.Lock) + { + if (_memoryCache.TryGetValue(cacheKey, out result)) { return result; } - lock (TypeLock.Lock) - { - if (_memoryCache.TryGetValue(cacheKey, out result)) - { - return result; - } + result = factory(); + _memoryCache.Set(cacheKey, result, absoluteExpiration); - result = factory(); - _memoryCache.Set(cacheKey, result, absoluteExpiration); - - return result; - } + return result; } + } + + private static class TypeLock + { + public static object Lock { get; } = new object(); + } - private static class TypeLock - { - public static object Lock { get; } = new object(); - } - } } diff --git a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs index ed0bf227f..fcf8529ce 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs @@ -22,6 +22,7 @@ namespace Ombi.Schedule.Jobs.Ombi _plexRepo = plexRepo; _embyRepo = embyRepo; _embyContentSync = embySync; + _settings.ClearCache(); } private readonly ISettingsService _settings; diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 6c59f4c0f..12415f6e4 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -57,6 +57,10 @@ namespace Ombi.Schedule.Jobs.Ombi _ombiSettings = ombiSettings; _plexSettings = plexSettings; _embySettings = embySettings; + _ombiSettings.ClearCache(); + _plexSettings.ClearCache(); + _emailSettings.ClearCache(); + _customizationSettings.ClearCache(); } private readonly IPlexContentRepository _plex; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 964832b44..9df1edf97 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -57,6 +57,7 @@ namespace Ombi.Schedule.Jobs.Plex EpisodeSync = epsiodeSync; Metadata = metadataRefresh; Checker = checker; + Plex.ClearCache(); } private ISettingsService Plex { get; } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index 6ab5a5941..5652d126b 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -26,6 +26,7 @@ namespace Ombi.Schedule.Jobs.Plex _api = plexApi; _repo = repo; _availabilityChecker = a; + _settings.ClearCache(); } private readonly ISettingsService _settings; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs index 105e8876d..53c82465c 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs @@ -24,6 +24,8 @@ namespace Ombi.Schedule.Jobs.Plex _log = log; _plexSettings = plexSettings; _userManagementSettings = ums; + _plexSettings.ClearCache(); + _userManagementSettings.ClearCache(); } private readonly IPlexApi _api; diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index f61747ac6..5c954def8 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -22,6 +22,7 @@ namespace Ombi.Schedule.Jobs.Radarr RadarrApi = radarrApi; Logger = log; _ctx = ctx; + RadarrSettings.ClearCache(); } private ISettingsService RadarrSettings { get; } diff --git a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs index 2c8d03b1d..92e0c2d55 100644 --- a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs +++ b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs @@ -22,6 +22,7 @@ namespace Ombi.Schedule.Jobs.SickRage _api = api; _log = l; _ctx = ctx; + _settings.ClearCache(); } private readonly ISettingsService _settings; diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index c77e23394..e4c00c726 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -25,6 +25,7 @@ namespace Ombi.Schedule.Jobs.Sonarr _api = api; _log = l; _ctx = ctx; + _settings.ClearCache(); } private readonly ISettingsService _settings; From 6dccea77c2bcad5719dda4d18f7370c8b310a990 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 6 Apr 2019 23:56:55 +0100 Subject: [PATCH 323/325] Fixed the mixed content warnings and the error when removing a album request #2884 --- src/Ombi.Core/Engine/MusicSearchEngine.cs | 5 +++-- src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs | 1 + .../app/requests/music/musicrequests.component.ts | 11 +++++------ src/Ombi/ClientApp/app/services/request.service.ts | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index d0e577801..16f727da7 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -152,7 +152,8 @@ namespace Ombi.Core.Engine Rating = a.ratings?.value ?? 0m, ReleaseDate = a.releaseDate, Title = a.title, - Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url + Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url?.Replace("http","https"), + Genres = a.genres }; if (a.artistId > 0) { @@ -169,7 +170,7 @@ namespace Ombi.Core.Engine vm.ArtistName = a.artist?.artistName; } - vm.Cover = a.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url; + vm.Cover = a.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url?.Replace("http", "https"); if (vm.Cover.IsNullOrEmpty()) { vm.Cover = a.remoteCover; diff --git a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs index a494a3cb5..3823d7789 100644 --- a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs @@ -16,6 +16,7 @@ namespace Ombi.Core.Models.Search public string Cover { get; set; } public string Disk { get; set; } public decimal PercentOfTracks { get; set; } + public object[] Genres { get; set; } public override RequestType Type => RequestType.Album; public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0; public bool FullyAvailable => PercentOfTracks == 100; diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts index b10173042..2bc7b6282 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts @@ -90,11 +90,10 @@ export class MusicRequestsComponent implements OnInit { this.searchChanged.next(text.target.value); } - public removeRequest(request: IAlbumRequest) { - this.requestService.removeAlbumRequest(request).subscribe(x => { - this.removeRequestFromUi(request); - this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); - }); + public async removeRequest(request: IAlbumRequest) { + await this.requestService.removeAlbumRequest(request).toPromise(); + this.removeRequestFromUi(request); + this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); } public changeAvailability(request: IAlbumRequest, available: boolean) { @@ -335,7 +334,7 @@ export class MusicRequestsComponent implements OnInit { } private setAlbumBackground(req: IAlbumRequest) { if (req.disk === null) { - if(req.cover === null) { + if (req.cover === null) { req.disk = this.defaultPoster; } else { req.disk = req.cover; diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index f7e2b3875..5353ea580 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -182,7 +182,7 @@ export class RequestService extends ServiceHelpers { } public removeAlbumRequest(request: IAlbumRequest): any { - this.http.delete(`${this.url}music/${request.id}`, {headers: this.headers}).subscribe(); + return this.http.delete(`${this.url}music/${request.id}`, {headers: this.headers}); } } From ca010a02824229f8e81052be1133a2c2547f3531 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sun, 7 Apr 2019 00:09:19 +0100 Subject: [PATCH 324/325] Added some defensive coding around when we create an artist for #2915 --- src/Ombi.Core/Senders/MusicSender.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 76a9fc14c..0e9db9192 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using EnsureThat; using Microsoft.Extensions.Logging; using Ombi.Api.Lidarr; using Ombi.Api.Lidarr.Models; @@ -87,6 +88,11 @@ namespace Ombi.Core.Senders if (artist == null || artist.id <= 0) { + EnsureArg.IsNotNullOrEmpty(model.ForeignArtistId, nameof(model.ForeignArtistId)); + EnsureArg.IsNotNullOrEmpty(model.ForeignAlbumId, nameof(model.ForeignAlbumId)); + EnsureArg.IsNotNullOrEmpty(model.ArtistName, nameof(model.ArtistName)); + EnsureArg.IsNotNullOrEmpty(rootFolderPath, nameof(rootFolderPath)); + // Create artist var newArtist = new ArtistAdd { From c2764fe780deae7a274c568489207b8beea6b548 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 9 Apr 2019 21:56:55 +0100 Subject: [PATCH 325/325] !wip on Music API --- src/Ombi.Api.Lidarr/ILidarrApi.cs | 1 + src/Ombi.Api.Lidarr/LidarrApi.cs | 26 +++++++++ src/Ombi.Api.Lidarr/Models/AlbumLookup.cs | 5 ++ src/Ombi.Api.Lidarr/Models/LidarrLinks.cs | 12 ++++ src/Ombi.Api.Lidarr/Models/LidarrRatings.cs | 8 +++ src/Ombi.Api.Lidarr/Models/LidarrTrack.cs | 22 ++++++++ .../Engine/Interfaces/IMusicSearchEngine.cs | 1 + src/Ombi.Core/Engine/MusicSearchEngine.cs | 56 ++++++++++++++++++- .../Models/Search/SearchAlbumViewModel.cs | 4 ++ src/Ombi/Controllers/SearchController.cs | 13 +++++ 10 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/Ombi.Api.Lidarr/Models/LidarrLinks.cs create mode 100644 src/Ombi.Api.Lidarr/Models/LidarrRatings.cs create mode 100644 src/Ombi.Api.Lidarr/Models/LidarrTrack.cs diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs index 4a23c6200..0eac960d0 100644 --- a/src/Ombi.Api.Lidarr/ILidarrApi.cs +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -23,5 +23,6 @@ namespace Ombi.Api.Lidarr Task> GetLanguageProfile(string apiKey, string baseUrl); Task Status(string apiKey, string baseUrl); Task AlbumSearch(int[] albumIds, string apiKey, string baseUrl); + Task AlbumInformation(string albumId, string apiKey, string baseUrl); } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index a6a283703..cb8db759e 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -105,6 +105,32 @@ namespace Ombi.Api.Lidarr return Api.Request>(request); } + public async Task AlbumInformation(string albumId, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); + request.AddQueryString("foreignAlbumId", albumId); + AddHeaders(request, apiKey); + var albums = await Api.Request>(request); + return albums.Where(x => x.foreignAlbumId.Equals(albumId, StringComparison.InvariantCultureIgnoreCase)) + .FirstOrDefault(); + } + + + /// + /// THIS ONLY SUPPORTS ALBUMS THAT THE ARTIST IS IN LIDARR + /// + /// + /// + /// + /// + public Task> GetTracksForAlbum(int albumId, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); + request.AddQueryString("albumId", albumId.ToString()); + AddHeaders(request, apiKey); + return Api.Request>(request); + } + public Task AddArtist(ArtistAdd artist, string apiKey, string baseUrl) { var request = new Request($"{ApiVersion}/artist", baseUrl, HttpMethod.Post); diff --git a/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs b/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs index b2394eb5f..1e909cf4c 100644 --- a/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs +++ b/src/Ombi.Api.Lidarr/Models/AlbumLookup.cs @@ -1,10 +1,15 @@ using System; +using System.Collections.Generic; namespace Ombi.Api.Lidarr.Models { public class AlbumLookup { public string title { get; set; } + public string status { get; set; } + public string artistType { get; set; } + public string disambiguation { get; set; } + public List links { get; set; } public int artistId { get; set; } public string foreignAlbumId { get; set; } public bool monitored { get; set; } diff --git a/src/Ombi.Api.Lidarr/Models/LidarrLinks.cs b/src/Ombi.Api.Lidarr/Models/LidarrLinks.cs new file mode 100644 index 000000000..e8bdb8975 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/LidarrLinks.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ombi.Api.Lidarr.Models +{ + public class LidarrLinks + { + public string url { get; set; } + public string name { get; set; } + } +} diff --git a/src/Ombi.Api.Lidarr/Models/LidarrRatings.cs b/src/Ombi.Api.Lidarr/Models/LidarrRatings.cs new file mode 100644 index 000000000..7728d58bf --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/LidarrRatings.cs @@ -0,0 +1,8 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class LidarrRatings + { + public int votes { get; set; } + public decimal value { get; set; } + } +} diff --git a/src/Ombi.Api.Lidarr/Models/LidarrTrack.cs b/src/Ombi.Api.Lidarr/Models/LidarrTrack.cs new file mode 100644 index 000000000..367e8cc7c --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/LidarrTrack.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ombi.Api.Lidarr.Models +{ + public class LidarrTrack + { + public int artistId { get; set; } + public int trackFileId { get; set; } + public int albumId { get; set; } + public bool _explicit { get; set; } + public int absoluteTrackNumber { get; set; } + public string trackNumber { get; set; } + public string title { get; set; } + public int duration { get; set; } + public int mediumNumber { get; set; } + public bool hasFile { get; set; } + public bool monitored { get; set; } + public int id { get; set; } + } +} diff --git a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs index 03294982a..71c02af9d 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs @@ -12,5 +12,6 @@ namespace Ombi.Core.Engine Task> GetArtistAlbums(string foreignArtistId); Task> SearchAlbum(string search); Task> SearchArtist(string search); + Task GetAlbumInformation(string foreignAlbumId); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index 16f727da7..c8d285766 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -60,6 +60,18 @@ namespace Ombi.Core.Engine return vm; } + public async Task GetAlbumInformation(string foreignAlbumId) + { + var settings = await GetSettings(); + var result = await _lidarrApi.AlbumInformation(foreignAlbumId, settings.ApiKey, settings.FullUri); + + + var vm = await MapIntoAlbumVm(result, settings); + + + return vm; + } + /// /// Searches the specified artist /// @@ -143,6 +155,48 @@ namespace Ombi.Core.Engine return vm; } + + // TODO + private async Task MapIntoAlbumVm(AlbumResponse a, LidarrSettings settings) + { + var vm = new SearchAlbumViewModel + { + ForeignAlbumId = a.foreignAlbumId, + Monitored = a.monitored, + Rating = a.ratings?.value ?? 0m, + ReleaseDate = a.releaseDate, + Title = a.title, + Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url?.Replace("http", "https"), + Genres = a.genres + }; + if (a.artistId > 0) + { + //TODO THEY HAVE FIXED THIS IN DEV + // The JSON is different for some stupid reason + // Need to lookup the artist now and all the images -.-" + var artist = await _lidarrApi.GetArtist(a.artistId, settings.ApiKey, settings.FullUri); + vm.ArtistName = artist.artistName; + vm.ForeignArtistId = artist.foreignArtistId; + } + else + { + //vm.ForeignArtistId = a.artistId?.foreignArtistId; + //vm.ArtistName = a.artist?.artistName; + } + + vm.Cover = a.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url?.Replace("http", "https"); + if (vm.Cover.IsNullOrEmpty()) + { + //vm.Cover = a.remoteCover; + } + + await Rules.StartSpecificRules(vm, SpecificRules.LidarrAlbum); + + await RunSearchRules(vm); + + return vm; + } + private async Task MapIntoAlbumVm(AlbumLookup a, LidarrSettings settings) { var vm = new SearchAlbumViewModel @@ -152,7 +206,7 @@ namespace Ombi.Core.Engine Rating = a.ratings?.value ?? 0m, ReleaseDate = a.releaseDate, Title = a.title, - Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url?.Replace("http","https"), + Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url?.Replace("http", "https"), Genres = a.genres }; if (a.artistId > 0) diff --git a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs index 3823d7789..e9f9c5f9e 100644 --- a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs @@ -20,5 +20,9 @@ namespace Ombi.Core.Models.Search public override RequestType Type => RequestType.Album; public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0; public bool FullyAvailable => PercentOfTracks == 100; + + + // Below is from the INFO call NEED A SEPERATE VM FOR THIS IN V4 TODO + // TODO ADD TRACK COUNT } } \ No newline at end of file diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index bdeacee2a..d5b5e3098 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -369,6 +369,19 @@ namespace Ombi.Controllers return await MusicEngine.SearchAlbum(searchTerm); } + /// + /// Returns the album information specified by the foreignAlbumId passed in + /// + /// We use Lidarr as the Provider + /// + [HttpGet("music/album/info/{foreignAlbumId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task GetAlbumInformation(string foreignAlbumId) + { + return await MusicEngine.GetAlbumInformation(foreignAlbumId); + } + /// /// Returns all albums for the artist using the ForeignArtistId ///
    - - + + - - + +
    -
    +
    - +
    {{ep.title}} + {{ep.airDate | amLocal | amDateFormat: 'L' }} + + {{ep.airDateDisplay }} Available diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts index 6a918a69a..c0d86f9a7 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts @@ -29,6 +29,7 @@ export class SeriesInformationComponent implements OnInit { this.searchService.getShowInformation(this.seriesId) .subscribe(x => { this.series = x; + debugger; }); } diff --git a/src/Ombi/package-lock.json b/src/Ombi/package-lock.json index fec5ad4b2..4ad391ab8 100644 --- a/src/Ombi/package-lock.json +++ b/src/Ombi/package-lock.json @@ -4190,7 +4190,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4208,11 +4209,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4225,15 +4228,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4336,7 +4342,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4346,6 +4353,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4358,17 +4366,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4385,6 +4396,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4457,7 +4469,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4467,6 +4480,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4542,7 +4556,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4572,6 +4587,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4589,6 +4605,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4627,11 +4644,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.0.3", - "bundled": true + "bundled": true, + "optional": true } } }, From 14d8d98979e3f57816f5120b66f3e68181a6917e Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 8 Feb 2019 14:02:42 +0000 Subject: [PATCH 258/325] Added the functionality to remove a user from getting notifications to their mobile device #2780 --- .../app/search/seriesinformation.component.ts | 1 - .../ClientApp/app/services/mobile.service.ts | 4 ++++ .../notifications/mobile.component.html | 9 +++++-- .../notifications/mobile.component.ts | 20 ++++++++++++++++ src/Ombi/Controllers/MobileController.cs | 24 ++++++++++++++++++- 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts index c0d86f9a7..6a918a69a 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts @@ -29,7 +29,6 @@ export class SeriesInformationComponent implements OnInit { this.searchService.getShowInformation(this.seriesId) .subscribe(x => { this.series = x; - debugger; }); } diff --git a/src/Ombi/ClientApp/app/services/mobile.service.ts b/src/Ombi/ClientApp/app/services/mobile.service.ts index 1f9e3fb24..9ff9b947d 100644 --- a/src/Ombi/ClientApp/app/services/mobile.service.ts +++ b/src/Ombi/ClientApp/app/services/mobile.service.ts @@ -15,4 +15,8 @@ export class MobileService extends ServiceHelpers { public getUserDeviceList(): Observable { return this.http.get(`${this.url}notification/`, {headers: this.headers}); } + + public deleteUser(userId: string): Observable { + return this.http.post(`${this.url}remove/`, userId, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/app/settings/notifications/mobile.component.html b/src/Ombi/ClientApp/app/settings/notifications/mobile.component.html index 5c82e03d5..2b7ea9b2c 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/mobile.component.html +++ b/src/Ombi/ClientApp/app/settings/notifications/mobile.component.html @@ -35,7 +35,7 @@
    - +
    - https://discord.gg/ + https://discord.gg/Sa7wNWb
    "); sb.Append(""); sb.Append(""); - await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode); - await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode); + if (plexSettings.Enable) + { + await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode); + } + + if (embySettings.Enable) + { + await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode); + } + sb.Append(""); sb.Append("
    "); sb.Append("
    "); sb.Append(""); sb.Append(""); - await ProcessPlexTv(plexEpisodes, sb); - await ProcessEmbyTv(embyEp, sb); + if (plexSettings.Enable) + { + await ProcessPlexTv(plexEpisodes, sb); + } + + if (embySettings.Enable) + { + await ProcessEmbyTv(embyEp, sb); + } + sb.Append(""); sb.Append("
    "); sb.Append("