mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-21 05:43:19 -07:00
Merge remote-tracking branch 'upstream/dev'
This commit is contained in:
commit
cd2c9a40e5
283 changed files with 10998 additions and 1985 deletions
|
@ -42,6 +42,7 @@ using Nancy.Validation;
|
|||
using NLog;
|
||||
using Ombi.Api;
|
||||
using Ombi.Api.Interfaces;
|
||||
using Ombi.Api.Models.Movie;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.Models;
|
||||
using Ombi.Core.SettingModels;
|
||||
|
@ -94,11 +95,14 @@ namespace Ombi.UI.Modules.Admin
|
|||
private IJobRecord JobRecorder { get; }
|
||||
private IAnalytics Analytics { get; }
|
||||
private IRecentlyAdded RecentlyAdded { get; }
|
||||
private IMassEmail MassEmail { get; }
|
||||
private ISettingsService<NotificationSettingsV2> NotifySettings { get; }
|
||||
private ISettingsService<DiscordNotificationSettings> DiscordSettings { get; }
|
||||
private IDiscordApi DiscordApi { get; }
|
||||
private ISettingsService<RadarrSettings> RadarrSettings { get; }
|
||||
private IRadarrApi RadarrApi { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
private IEmbyApi EmbyApi { get; }
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
public AdminModule(ISettingsService<PlexRequestSettings> prService,
|
||||
|
@ -124,10 +128,11 @@ namespace Ombi.UI.Modules.Admin
|
|||
ISlackApi slackApi, ISettingsService<MattermostNotificationSettings> mattermostSettings,
|
||||
IMattermostApi mattermostApi, ISettingsService<LandingPageSettings> lp,
|
||||
ISettingsService<ScheduledJobsSettings> scheduler, IJobRecord rec, IAnalytics analytics,
|
||||
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded,
|
||||
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded, IMassEmail massEmail,
|
||||
ISettingsService<WatcherSettings> watcherSettings ,
|
||||
ISettingsService<DiscordNotificationSettings> discord,
|
||||
IDiscordApi discordapi, ISettingsService<RadarrSettings> settings, IRadarrApi radarrApi
|
||||
IDiscordApi discordapi, ISettingsService<RadarrSettings> settings, IRadarrApi radarrApi,
|
||||
ISettingsService<EmbySettings> embySettings, IEmbyApi emby
|
||||
, ISecurityExtensions security) : base("admin", prService, security)
|
||||
{
|
||||
PrService = prService;
|
||||
|
@ -160,12 +165,15 @@ namespace Ombi.UI.Modules.Admin
|
|||
Analytics = analytics;
|
||||
NotifySettings = notifyService;
|
||||
RecentlyAdded = recentlyAdded;
|
||||
MassEmail = massEmail;
|
||||
WatcherSettings = watcherSettings;
|
||||
DiscordSettings = discord;
|
||||
DiscordApi = discordapi;
|
||||
RadarrSettings = settings;
|
||||
RadarrApi = radarrApi;
|
||||
|
||||
EmbyApi = emby;
|
||||
EmbySettings = embySettings;
|
||||
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
Get["/"] = _ => Admin();
|
||||
|
@ -175,7 +183,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
|
||||
Post["/", true] = async (x, ct) => await SaveAdmin();
|
||||
|
||||
Post["/requestauth"] = _ => RequestAuthToken();
|
||||
Post["/requestauth", true] = async (x, ct) => await RequestAuthToken();
|
||||
|
||||
Get["/getusers"] = _ => GetUsers();
|
||||
|
||||
|
@ -185,6 +193,10 @@ namespace Ombi.UI.Modules.Admin
|
|||
Get["/plex"] = _ => Plex();
|
||||
Post["/plex", true] = async (x, ct) => await SavePlex();
|
||||
|
||||
Get["/emby", true] = async (x, ct) => await Emby();
|
||||
Post["/emby", true] = async (x, ct) => await SaveEmby();
|
||||
|
||||
|
||||
Get["/sonarr"] = _ => Sonarr();
|
||||
Post["/sonarr"] = _ => SaveSonarr();
|
||||
Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles();
|
||||
|
@ -218,6 +230,11 @@ namespace Ombi.UI.Modules.Admin
|
|||
|
||||
Get["/newsletter", true] = async (x, ct) => await Newsletter();
|
||||
Post["/newsletter", true] = async (x, ct) => await SaveNewsletter();
|
||||
Post["/testnewsletteradminemail"] = x => TestNewsletterAdminEmail();
|
||||
|
||||
Get["/massemail"] = _ => MassEmailView();
|
||||
Post["/testmassadminemail"] = x => TestMassAdminEmail();
|
||||
Post["/sendmassemail"] = x => SendMassEmail();
|
||||
|
||||
Post["/createapikey"] = x => CreateApiKey();
|
||||
|
||||
|
@ -246,7 +263,6 @@ namespace Ombi.UI.Modules.Admin
|
|||
Get["/notificationsettings", true] = async (x, ct) => await NotificationSettings();
|
||||
Post["/notificationsettings"] = x => SaveNotificationSettings();
|
||||
|
||||
Post["/recentlyAddedTest"] = x => RecentlyAddedTest();
|
||||
}
|
||||
|
||||
private async Task<Negotiator> Authentication()
|
||||
|
@ -312,7 +328,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
: new JsonResponseModel { Result = false, Message = "We could not save to the database, please try again" });
|
||||
}
|
||||
|
||||
private Response RequestAuthToken()
|
||||
private async Task<Response> RequestAuthToken()
|
||||
{
|
||||
var user = this.Bind<PlexAuth>();
|
||||
|
||||
|
@ -328,11 +344,11 @@ namespace Ombi.UI.Modules.Admin
|
|||
return Response.AsJson(new { Result = false, Message = "Incorrect username or password!" });
|
||||
}
|
||||
|
||||
var oldSettings = PlexService.GetSettings();
|
||||
var oldSettings = await PlexService.GetSettingsAsync();
|
||||
if (oldSettings != null)
|
||||
{
|
||||
oldSettings.PlexAuthToken = model.user.authentication_token;
|
||||
PlexService.SaveSettings(oldSettings);
|
||||
await PlexService.SaveSettingsAsync(oldSettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -340,10 +356,14 @@ namespace Ombi.UI.Modules.Admin
|
|||
{
|
||||
PlexAuthToken = model.user.authentication_token
|
||||
};
|
||||
PlexService.SaveSettings(newModel);
|
||||
await PlexService.SaveSettingsAsync(newModel);
|
||||
}
|
||||
|
||||
return Response.AsJson(new { Result = true, AuthToken = model.user.authentication_token });
|
||||
var server = PlexApi.GetServer(model.user.authentication_token);
|
||||
var machine =
|
||||
server.Server.FirstOrDefault(x => x.AccessToken == model.user.authentication_token)?.MachineIdentifier;
|
||||
|
||||
return Response.AsJson(new { Result = true, AuthToken = model.user.authentication_token, Identifier = machine });
|
||||
}
|
||||
|
||||
|
||||
|
@ -441,13 +461,32 @@ namespace Ombi.UI.Modules.Admin
|
|||
private async Task<Response> SavePlex()
|
||||
{
|
||||
var plexSettings = this.Bind<PlexSettings>();
|
||||
var valid = this.Validate(plexSettings);
|
||||
if (!valid.IsValid)
|
||||
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
var valid = this.Validate(plexSettings);
|
||||
if (!valid.IsValid)
|
||||
{
|
||||
return Response.AsJson(valid.SendJsonError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
return Response.AsJson(valid.SendJsonError());
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "Emby is enabled, we cannot enable Plex and Emby"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(plexSettings.MachineIdentifier))
|
||||
if (string.IsNullOrEmpty(plexSettings.MachineIdentifier) && plexSettings.Enable)
|
||||
{
|
||||
//Lookup identifier
|
||||
var server = PlexApi.GetServer(plexSettings.PlexAuthToken);
|
||||
|
@ -462,6 +501,49 @@ namespace Ombi.UI.Modules.Admin
|
|||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||
}
|
||||
|
||||
private async Task<Negotiator> Emby()
|
||||
{
|
||||
var settings = await EmbySettings.GetSettingsAsync();
|
||||
|
||||
return View["Emby", settings];
|
||||
}
|
||||
|
||||
private async Task<Response> SaveEmby()
|
||||
{
|
||||
var emby = this.Bind<EmbySettings>();
|
||||
var valid = this.Validate(emby);
|
||||
if (!valid.IsValid)
|
||||
{
|
||||
return Response.AsJson(valid.SendJsonError());
|
||||
}
|
||||
|
||||
if (emby.Enable)
|
||||
{
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "Plex is enabled, we cannot enable Plex and Emby"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get the users
|
||||
var users = EmbyApi.GetUsers(emby.FullUri, emby.ApiKey);
|
||||
// Find admin
|
||||
var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator);
|
||||
emby.AdministratorId = admin?.Id;
|
||||
|
||||
var result = await EmbySettings.SaveSettingsAsync(emby);
|
||||
|
||||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Emby!" }
|
||||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||
}
|
||||
|
||||
private Negotiator Sonarr()
|
||||
{
|
||||
var settings = SonarrService.GetSettings();
|
||||
|
@ -757,6 +839,10 @@ namespace Ombi.UI.Modules.Admin
|
|||
{
|
||||
return Response.AsJson(valid.SendJsonError());
|
||||
}
|
||||
if (!settings.Enabled)
|
||||
{
|
||||
return Response.AsJson(new CouchPotatoProfiles{list = new List<ProfileList>()});
|
||||
}
|
||||
var profiles = CpApi.GetProfiles(settings.FullUri, settings.ApiKey);
|
||||
|
||||
// set the cache
|
||||
|
@ -859,6 +945,10 @@ namespace Ombi.UI.Modules.Admin
|
|||
var settings = await NewsLetterService.GetSettingsAsync();
|
||||
return View["NewsletterSettings", settings];
|
||||
}
|
||||
private Negotiator MassEmailView()
|
||||
{
|
||||
return View["MassEmail"];
|
||||
}
|
||||
|
||||
private async Task<Response> SaveNewsletter()
|
||||
{
|
||||
|
@ -1116,9 +1206,10 @@ namespace Ombi.UI.Modules.Admin
|
|||
|
||||
Analytics.TrackEventAsync(Category.Admin, Action.Update, "Update Landing Page", Username, CookieHelper.GetAnalyticClientId(Cookies));
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
if (string.IsNullOrEmpty(plexSettings.Ip))
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (string.IsNullOrEmpty(plexSettings.Ip) && string.IsNullOrEmpty(embySettings.Ip))
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "We cannot enable the landing page if Plex is not setup!" });
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "We cannot enable the landing page if Plex/Emby is not setup!" });
|
||||
}
|
||||
|
||||
if (settings.Enabled && settings.EnabledNoticeTime && string.IsNullOrEmpty(settings.NoticeMessage))
|
||||
|
@ -1137,6 +1228,10 @@ namespace Ombi.UI.Modules.Admin
|
|||
{
|
||||
var s = await ScheduledJobSettings.GetSettingsAsync();
|
||||
var allJobs = await JobRecorder.GetJobsAsync();
|
||||
var emby = await EmbySettings.GetSettingsAsync();
|
||||
var plex = await PlexService.GetSettingsAsync();
|
||||
|
||||
|
||||
|
||||
var dict = new Dictionary<string, DateTime>();
|
||||
|
||||
|
@ -1150,13 +1245,32 @@ namespace Ombi.UI.Modules.Admin
|
|||
}
|
||||
else
|
||||
{
|
||||
dict.Add(j.Name,j.LastRun);
|
||||
if (j.Name.Contains("Plex"))
|
||||
{
|
||||
if (plex.Enable)
|
||||
{
|
||||
dict.Add(j.Name, j.LastRun);
|
||||
}
|
||||
}
|
||||
else if (j.Name.Contains("Emby"))
|
||||
{
|
||||
if (emby.Enable)
|
||||
{
|
||||
dict.Add(j.Name, j.LastRun);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dict.Add(j.Name, j.LastRun);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var model = new ScheduledJobsViewModel
|
||||
{
|
||||
Emby = emby.Enable,
|
||||
Plex = plex.Enable,
|
||||
CouchPotatoCacher = s.CouchPotatoCacher,
|
||||
PlexAvailabilityChecker = s.PlexAvailabilityChecker,
|
||||
SickRageCacher = s.SickRageCacher,
|
||||
|
@ -1169,7 +1283,13 @@ namespace Ombi.UI.Modules.Admin
|
|||
FaultQueueHandler = s.FaultQueueHandler,
|
||||
PlexEpisodeCacher = s.PlexEpisodeCacher,
|
||||
PlexUserChecker = s.PlexUserChecker,
|
||||
UserRequestLimitResetter = s.UserRequestLimitResetter
|
||||
UserRequestLimitResetter = s.UserRequestLimitResetter,
|
||||
EmbyAvailabilityChecker = s.EmbyAvailabilityChecker,
|
||||
EmbyContentCacher = s.EmbyContentCacher,
|
||||
EmbyEpisodeCacher = s.EmbyEpisodeCacher,
|
||||
EmbyUserChecker = s.EmbyUserChecker,
|
||||
RadarrCacher = s.RadarrCacher,
|
||||
WatcherCacher = s.WatcherCacher
|
||||
};
|
||||
return View["SchedulerSettings", model];
|
||||
}
|
||||
|
@ -1232,13 +1352,13 @@ namespace Ombi.UI.Modules.Admin
|
|||
var model = this.Bind<NotificationSettingsV2>();
|
||||
return View["NotificationSettings", model];
|
||||
}
|
||||
|
||||
private Response RecentlyAddedTest()
|
||||
|
||||
private Response TestNewsletterAdminEmail()
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Debug("Clicked TEST");
|
||||
RecentlyAdded.Test();
|
||||
Log.Debug("Clicked Admin Newsletter Email Test");
|
||||
RecentlyAdded.RecentlyAddedAdminTest();
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Sent email to administrator" });
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -1247,5 +1367,50 @@ namespace Ombi.UI.Modules.Admin
|
|||
return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message });
|
||||
}
|
||||
}
|
||||
private Response TestMassAdminEmail()
|
||||
{
|
||||
try
|
||||
{
|
||||
var settings = this.Bind<MassEmailSettings>();
|
||||
Log.Debug("Clicked Admin Mass Email Test");
|
||||
if (settings.Subject == null) {
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Subject" });
|
||||
}
|
||||
if (settings.Body == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Body" });
|
||||
}
|
||||
MassEmail.MassEmailAdminTest(settings.Body.Replace("\n", "<br/>"), settings.Subject);
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Sent email to administrator" });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message });
|
||||
}
|
||||
}
|
||||
private Response SendMassEmail()
|
||||
{
|
||||
try
|
||||
{
|
||||
var settings = this.Bind<MassEmailSettings>();
|
||||
Log.Debug("Clicked Admin Mass Email Test");
|
||||
if (settings.Subject == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Subject" });
|
||||
}
|
||||
if (settings.Body == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Body" });
|
||||
}
|
||||
MassEmail.SendMassEmail(settings.Body.Replace("\n", "<br/>"), settings.Subject);
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Sent email to All users" });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,7 +25,10 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Nancy;
|
||||
using Nancy.Responses.Negotiation;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.SettingModels;
|
||||
|
@ -48,6 +51,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
Get["Index", "/faultqueue"] = x => Index();
|
||||
Get["DeleteFault", "/deleteFault", true] = async (x,ct) => await DeleteFault(Convert.ToInt32(Request.Form.id));
|
||||
}
|
||||
|
||||
private IRepository<RequestQueue> RequestQueue { get; }
|
||||
|
@ -69,5 +73,35 @@ namespace Ombi.UI.Modules.Admin
|
|||
|
||||
return View["RequestFaultQueue", model];
|
||||
}
|
||||
|
||||
public async Task<Response> DeleteFault(int faultId)
|
||||
{
|
||||
|
||||
if (faultId == 0)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = true,
|
||||
Message = "Fault does not exist"
|
||||
});
|
||||
}
|
||||
|
||||
var fault = await RequestQueue.GetAsync(faultId);
|
||||
if (fault == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = true,
|
||||
Message = "Fault does not exist"
|
||||
});
|
||||
}
|
||||
|
||||
await RequestQueue.DeleteAsync(fault);
|
||||
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,6 +69,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
|
||||
|
||||
Post["/sonarrrootfolders"] = _ => GetSonarrRootFolders();
|
||||
Post["/radarrrootfolders"] = _ => GetSonarrRootFolders();
|
||||
|
||||
Get["/watcher", true] = async (x, ct) => await Watcher();
|
||||
Post["/watcher", true] = async (x, ct) => await SaveWatcher();
|
||||
|
@ -156,7 +157,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
var cp = await CpSettings.GetSettingsAsync();
|
||||
if (cp.Enabled)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "CouchPotato is enabled, we cannot enable Watcher and CouchPotato" });
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "CouchPotato is enabled, we cannot enable Radarr and CouchPotato" });
|
||||
}
|
||||
|
||||
var valid = this.Validate(radarrSettings);
|
||||
|
@ -191,7 +192,22 @@ namespace Ombi.UI.Modules.Admin
|
|||
{
|
||||
var settings = this.Bind<SonarrSettings>();
|
||||
|
||||
var rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
|
||||
var rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
|
||||
|
||||
// set the cache
|
||||
if (rootFolders != null)
|
||||
{
|
||||
Cache.Set(CacheKeys.SonarrRootFolders, rootFolders);
|
||||
}
|
||||
|
||||
return Response.AsJson(rootFolders);
|
||||
}
|
||||
|
||||
private Response GetRadarrRootFolders()
|
||||
{
|
||||
var settings = this.Bind<RadarrSettings>();
|
||||
|
||||
var rootFolders = RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
|
||||
|
||||
// set the cache
|
||||
if (rootFolders != null)
|
||||
|
|
|
@ -33,6 +33,7 @@ using Ombi.Core.SettingModels;
|
|||
using Ombi.Helpers.Permissions;
|
||||
using Ombi.Services.Interfaces;
|
||||
using Ombi.Services.Jobs;
|
||||
using Ombi.Services.Jobs.Interfaces;
|
||||
using Ombi.UI.Models;
|
||||
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
|
||||
|
||||
|
@ -44,7 +45,8 @@ namespace Ombi.UI.Modules.Admin
|
|||
ISecurityExtensions security, IPlexContentCacher contentCacher, ISonarrCacher sonarrCacher, IWatcherCacher watcherCacher,
|
||||
IRadarrCacher radarrCacher, ICouchPotatoCacher cpCacher, IStoreBackup store, ISickRageCacher srCacher, IAvailabilityChecker plexChceker,
|
||||
IStoreCleanup cleanup, IUserRequestLimitResetter requestLimit, IPlexEpisodeCacher episodeCacher, IRecentlyAdded recentlyAdded,
|
||||
IFaultQueueHandler faultQueueHandler, IPlexUserChecker plexUserChecker) : base("admin", settingsService, security)
|
||||
IFaultQueueHandler faultQueueHandler, IPlexUserChecker plexUserChecker, IEmbyAvailabilityChecker embyAvailabilityChecker, IEmbyEpisodeCacher embyEpisode,
|
||||
IEmbyContentCacher embyContentCacher, IEmbyUserChecker embyUser) : base("admin", settingsService, security)
|
||||
{
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
|
@ -62,6 +64,10 @@ namespace Ombi.UI.Modules.Admin
|
|||
RecentlyAdded = recentlyAdded;
|
||||
FaultQueueHandler = faultQueueHandler;
|
||||
PlexUserChecker = plexUserChecker;
|
||||
EmbyAvailabilityChecker = embyAvailabilityChecker;
|
||||
EmbyContentCacher = embyContentCacher;
|
||||
EmbyEpisodeCacher = embyEpisode;
|
||||
EmbyUserChecker = embyUser;
|
||||
|
||||
Post["/schedulerun", true] = async (x, ct) => await ScheduleRun((string)Request.Form.key);
|
||||
}
|
||||
|
@ -80,10 +86,16 @@ namespace Ombi.UI.Modules.Admin
|
|||
private IRecentlyAdded RecentlyAdded { get; }
|
||||
private IFaultQueueHandler FaultQueueHandler { get; }
|
||||
private IPlexUserChecker PlexUserChecker { get; }
|
||||
private IEmbyAvailabilityChecker EmbyAvailabilityChecker { get; }
|
||||
private IEmbyContentCacher EmbyContentCacher { get; }
|
||||
private IEmbyEpisodeCacher EmbyEpisodeCacher { get; }
|
||||
private IEmbyUserChecker EmbyUserChecker { get; }
|
||||
|
||||
|
||||
private async Task<Response> ScheduleRun(string key)
|
||||
{
|
||||
await Task.Yield();
|
||||
|
||||
if (key.Equals(JobNames.PlexCacher, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
PlexContentCacher.CacheContent();
|
||||
|
@ -132,7 +144,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
}
|
||||
if (key.Equals(JobNames.RecentlyAddedEmail, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
RecentlyAdded.Start();
|
||||
RecentlyAdded.StartNewsLetter();
|
||||
}
|
||||
if (key.Equals(JobNames.FaultQueueHandler, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
|
@ -142,6 +154,22 @@ namespace Ombi.UI.Modules.Admin
|
|||
{
|
||||
RequestLimit.Start();
|
||||
}
|
||||
if (key.Equals(JobNames.EmbyEpisodeCacher, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
EmbyEpisodeCacher.Start();
|
||||
}
|
||||
if (key.Equals(JobNames.EmbyCacher, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
EmbyContentCacher.CacheContent();
|
||||
}
|
||||
if (key.Equals(JobNames.EmbyChecker, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
EmbyAvailabilityChecker.CheckAndUpdateAll();
|
||||
}
|
||||
if (key.Equals(JobNames.EmbyUserChecker, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
EmbyUserChecker.Start();
|
||||
}
|
||||
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
|
|
|
@ -35,7 +35,10 @@ using MarkdownSharp;
|
|||
using Nancy;
|
||||
using Nancy.ModelBinding;
|
||||
using Nancy.Responses.Negotiation;
|
||||
using Ombi.Api.Interfaces;
|
||||
using Ombi.Common.Processes;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.Models;
|
||||
using Ombi.Core.SettingModels;
|
||||
using Ombi.Core.StatusChecker;
|
||||
using Ombi.Helpers;
|
||||
|
@ -49,11 +52,13 @@ namespace Ombi.UI.Modules.Admin
|
|||
{
|
||||
public class SystemStatusModule : BaseModule
|
||||
{
|
||||
public SystemStatusModule(ISettingsService<PlexRequestSettings> settingsService, ICacheProvider cache, ISettingsService<SystemSettings> ss, ISecurityExtensions security, IAnalytics a) : base("admin", settingsService, security)
|
||||
public SystemStatusModule(ISettingsService<PlexRequestSettings> settingsService, ICacheProvider cache, ISettingsService<SystemSettings> ss,
|
||||
ISecurityExtensions security, IAnalytics a, IAppveyorApi appveyor) : base("admin", settingsService, security)
|
||||
{
|
||||
Cache = cache;
|
||||
SystemSettings = ss;
|
||||
Analytics = a;
|
||||
AppveyorApi = appveyor;
|
||||
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
|
@ -61,11 +66,13 @@ namespace Ombi.UI.Modules.Admin
|
|||
Post["/save", true] = async (x, ct) => await Save();
|
||||
|
||||
Post["/autoupdate"] = x => AutoUpdate();
|
||||
Get["/changes", true] = async (x, ct) => await GetLatestChanges();
|
||||
}
|
||||
|
||||
private ICacheProvider Cache { get; }
|
||||
private ISettingsService<SystemSettings> SystemSettings { get; }
|
||||
private IAnalytics Analytics { get; }
|
||||
private IAppveyorApi AppveyorApi { get; }
|
||||
|
||||
private async Task<Negotiator> Status()
|
||||
{
|
||||
|
@ -81,19 +88,19 @@ namespace Ombi.UI.Modules.Admin
|
|||
{
|
||||
new BranchDropdown
|
||||
{
|
||||
Name = EnumHelper<Branches>.GetDisplayValue(Branches.Stable),
|
||||
Name =EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.Stable).DisplayName,
|
||||
Value = Branches.Stable,
|
||||
Selected = settings.Branch == Branches.Stable
|
||||
},
|
||||
new BranchDropdown
|
||||
{
|
||||
Name = EnumHelper<Branches>.GetDisplayValue(Branches.EarlyAccessPreview),
|
||||
Name = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.EarlyAccessPreview).DisplayName,
|
||||
Value = Branches.EarlyAccessPreview,
|
||||
Selected = settings.Branch == Branches.EarlyAccessPreview
|
||||
},
|
||||
new BranchDropdown
|
||||
{
|
||||
Name = EnumHelper<Branches>.GetDisplayValue(Branches.Dev),
|
||||
Name = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.Dev).DisplayName,
|
||||
Value = Branches.Dev,
|
||||
Selected = settings.Branch == Branches.Dev
|
||||
},
|
||||
|
@ -102,6 +109,34 @@ namespace Ombi.UI.Modules.Admin
|
|||
return View["Status", settings];
|
||||
}
|
||||
|
||||
public async Task<Response> GetLatestChanges()
|
||||
{
|
||||
var settings = await SystemSettings.GetSettingsAsync();
|
||||
var branchName = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(settings.Branch).BranchName;
|
||||
var changes = AppveyorApi.GetProjectHistory(branchName);
|
||||
var currentVersion = AssemblyHelper.GetProductVersion();
|
||||
var model = new List<RecentUpdatesModel>();
|
||||
|
||||
foreach (var build in changes.builds)
|
||||
{
|
||||
model.Add(new RecentUpdatesModel
|
||||
{
|
||||
Date = build.finished,
|
||||
Message = BuildAppveyorMessage(build.message, build.messageExtended),
|
||||
Version = build.version,
|
||||
Installed = currentVersion.Equals(build.version, StringComparison.CurrentCultureIgnoreCase) ,
|
||||
Branch = branchName
|
||||
});
|
||||
}
|
||||
|
||||
return Response.AsJson(model);
|
||||
}
|
||||
|
||||
private string BuildAppveyorMessage(string message, string extended)
|
||||
{
|
||||
return extended == null ? message : $"{message} {extended}";
|
||||
}
|
||||
|
||||
private async Task<Response> Save()
|
||||
{
|
||||
|
||||
|
@ -123,7 +158,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
var url = Request.Form["url"];
|
||||
var args = (string)Request.Form["args"].ToString();
|
||||
var lowered = args.ToLower();
|
||||
var appPath = Path.Combine(Path.GetDirectoryName(Assembly.GetAssembly(typeof(SystemStatusModule)).Location ?? string.Empty) ?? string.Empty, "Ombi.Updater.exe");
|
||||
var appPath = Path.Combine(Path.GetDirectoryName(Assembly.GetAssembly(typeof(SystemStatusModule)).Location ?? string.Empty) ?? string.Empty, Path.Combine("UpdateService", "Ombi.Updater.exe"));
|
||||
|
||||
if (!string.IsNullOrEmpty(lowered))
|
||||
{
|
||||
|
@ -133,7 +168,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
}
|
||||
}
|
||||
|
||||
var startArgs = string.IsNullOrEmpty(lowered) ? appPath : $"{lowered} Ombi.Updater.exe";
|
||||
var startArgs = string.IsNullOrEmpty(lowered) || lowered == "Nancy.DynamicDictionaryValue".ToLower() ? appPath : $"{lowered} Ombi.Updater.exe";
|
||||
|
||||
var startInfo = Type.GetType("Mono.Runtime") != null
|
||||
? new ProcessStartInfo(startArgs) { Arguments = $"{url} {lowered}", }
|
||||
|
@ -141,7 +176,7 @@ namespace Ombi.UI.Modules.Admin
|
|||
|
||||
Process.Start(startInfo);
|
||||
|
||||
Environment.Exit(0);
|
||||
//Environment.Exit(0);
|
||||
return Nancy.Response.NoBody;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace Ombi.UI.Modules
|
|||
|
||||
public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi,
|
||||
ISickRageApi srApi, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr, ISecurityExtensions security,
|
||||
IWatcherApi watcherApi, IRadarrApi radarrApi) : base("test", pr, security)
|
||||
IWatcherApi watcherApi, IRadarrApi radarrApi, IEmbyApi emby) : base("test", pr, security)
|
||||
{
|
||||
this.RequiresAuthentication();
|
||||
|
||||
|
@ -57,6 +57,7 @@ namespace Ombi.UI.Modules
|
|||
HeadphonesApi = hpApi;
|
||||
WatcherApi = watcherApi;
|
||||
RadarrApi = radarrApi;
|
||||
Emby = emby;
|
||||
|
||||
Post["/cp"] = _ => CouchPotatoTest();
|
||||
Post["/sonarr"] = _ => SonarrTest();
|
||||
|
@ -66,6 +67,7 @@ namespace Ombi.UI.Modules
|
|||
Post["/headphones"] = _ => HeadphonesTest();
|
||||
Post["/plexdb"] = _ => TestPlexDb();
|
||||
Post["/watcher"] = _ => WatcherTest();
|
||||
Post["/emby"] = _ => EmbyTest();
|
||||
}
|
||||
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
@ -76,6 +78,7 @@ namespace Ombi.UI.Modules
|
|||
private IHeadphonesApi HeadphonesApi { get; }
|
||||
private IWatcherApi WatcherApi { get; }
|
||||
private IRadarrApi RadarrApi { get; }
|
||||
private IEmbyApi Emby { get; set; }
|
||||
|
||||
private Response CouchPotatoTest()
|
||||
{
|
||||
|
@ -213,7 +216,7 @@ namespace Ombi.UI.Modules
|
|||
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Plex, please check your settings." });
|
||||
|
||||
}
|
||||
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
|
||||
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
|
||||
{
|
||||
Log.Warn("Exception thrown when attempting to get Plex's status: ");
|
||||
Log.Warn(e);
|
||||
|
@ -225,6 +228,35 @@ namespace Ombi.UI.Modules
|
|||
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
|
||||
}
|
||||
}
|
||||
private Response EmbyTest()
|
||||
{
|
||||
var emby = this.Bind<EmbySettings>();
|
||||
var valid = this.Validate(emby);
|
||||
if (!valid.IsValid)
|
||||
{
|
||||
return Response.AsJson(valid.SendJsonError());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var status = Emby.GetUsers(emby?.FullUri, emby?.ApiKey);
|
||||
return status != null
|
||||
? Response.AsJson(new JsonResponseModel { Result = true, Message = "Connected to Emby successfully!" })
|
||||
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Emby, please check your settings." });
|
||||
|
||||
}
|
||||
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
|
||||
{
|
||||
Log.Warn("Exception thrown when attempting to get Emby's users: ");
|
||||
Log.Warn(e);
|
||||
var message = $"Could not connect to Emby, please check your settings. <strong>Exception Message:</strong> {e.Message}";
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
message = $"Could not connect to Emby, please check your settings. <strong>Exception Message:</strong> {e.InnerException.Message}";
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
|
||||
}
|
||||
}
|
||||
|
||||
private Response SickRageTest()
|
||||
{
|
||||
|
|
|
@ -193,7 +193,7 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
// Approve it
|
||||
request.Approved = true;
|
||||
Log.Warn("We approved movie: {0} but could not add it to CouchPotato/Watcher because it has not been setup", request.Title);
|
||||
Log.Warn("We approved movie: {0} but could not add it to CouchPotato/Watcher/Radarr because it has not been setup", request.Title);
|
||||
|
||||
// Update the record
|
||||
var inserted = await Service.UpdateRequestAsync(request);
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace Ombi.UI.Modules
|
|||
Deleted = issue.Deleted,
|
||||
Type = issue.Type,
|
||||
ProviderId = issue.ProviderId,
|
||||
PosterUrl = issue.PosterUrl,
|
||||
PosterUrl = issue.PosterUrl.Contains("https://image.tmdb.org/t/p/w150/") ? issue.PosterUrl : $"https://image.tmdb.org/t/p/w150/{issue.PosterUrl}",
|
||||
Id = issue.Id
|
||||
};
|
||||
return View["Details", m];
|
||||
|
|
|
@ -40,12 +40,15 @@ namespace Ombi.UI.Modules
|
|||
public class LandingPageModule : BaseModule
|
||||
{
|
||||
public LandingPageModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<LandingPageSettings> landing,
|
||||
ISettingsService<PlexSettings> ps, IPlexApi pApi, IResourceLinker linker, ISecurityExtensions security) : base("landing", settingsService, security)
|
||||
ISettingsService<PlexSettings> ps, IPlexApi pApi, IResourceLinker linker, ISecurityExtensions security, ISettingsService<EmbySettings> emby,
|
||||
IEmbyApi embyApi) : base("landing", settingsService, security)
|
||||
{
|
||||
LandingSettings = landing;
|
||||
PlexSettings = ps;
|
||||
PlexApi = pApi;
|
||||
Linker = linker;
|
||||
EmbySettings = emby;
|
||||
EmbyApi = embyApi;
|
||||
|
||||
Get["LandingPageIndex","/", true] = async (x, ct) =>
|
||||
{
|
||||
|
@ -75,26 +78,49 @@ namespace Ombi.UI.Modules
|
|||
|
||||
private ISettingsService<LandingPageSettings> LandingSettings { get; }
|
||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
private IPlexApi PlexApi { get; }
|
||||
private IEmbyApi EmbyApi { get; }
|
||||
private IResourceLinker Linker { get; }
|
||||
|
||||
private async Task<Response> CheckStatus()
|
||||
{
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip))
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
return Response.AsJson(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
var status = PlexApi.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri);
|
||||
return Response.AsJson(status != null);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return Response.AsJson(false);
|
||||
if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip))
|
||||
{
|
||||
return Response.AsJson(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
var status = PlexApi.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri);
|
||||
return Response.AsJson(status != null);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return Response.AsJson(false);
|
||||
}
|
||||
}
|
||||
|
||||
var emby = await EmbySettings.GetSettingsAsync();
|
||||
if (emby.Enable)
|
||||
{
|
||||
if (string.IsNullOrEmpty(emby.AdministratorId) || string.IsNullOrEmpty(emby.Ip))
|
||||
{
|
||||
return Response.AsJson(false);
|
||||
}
|
||||
try
|
||||
{
|
||||
var status = EmbyApi.GetSystemInformation(emby.ApiKey, emby.FullUri);
|
||||
return Response.AsJson(status?.Version != null);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return Response.AsJson(false);
|
||||
}
|
||||
}
|
||||
return Response.AsJson(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,10 +29,12 @@ using System;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Nancy;
|
||||
using Nancy.Responses;
|
||||
using NLog;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.SettingModels;
|
||||
using Ombi.Core.StatusChecker;
|
||||
using Ombi.Core.Users;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Services.Interfaces;
|
||||
using Ombi.Services.Jobs;
|
||||
|
@ -43,14 +45,16 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
public class LayoutModule : BaseAuthModule
|
||||
{
|
||||
public LayoutModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings, IJobRecord rec, ISecurityExtensions security) : base("layout", pr, security)
|
||||
public LayoutModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings, IJobRecord rec, ISecurityExtensions security, IUserHelper helper) : base("layout", pr, security)
|
||||
{
|
||||
Cache = provider;
|
||||
SystemSettings = settings;
|
||||
Job = rec;
|
||||
UserHelper = helper;
|
||||
|
||||
Get["/", true] = async (x,ct) => await CheckLatestVersion();
|
||||
Get["/cacher", true] = async (x,ct) => await CacherRunning();
|
||||
Get["/gravatar"] = x => GetGravatarImage();
|
||||
}
|
||||
|
||||
private ICacheProvider Cache { get; }
|
||||
|
@ -58,6 +62,7 @@ namespace Ombi.UI.Modules
|
|||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private ISettingsService<SystemSettings> SystemSettings { get; }
|
||||
private IJobRecord Job { get; }
|
||||
private IUserHelper UserHelper { get; }
|
||||
|
||||
private async Task<Response> CheckLatestVersion()
|
||||
{
|
||||
|
@ -116,5 +121,31 @@ namespace Ombi.UI.Modules
|
|||
return Response.AsJson(new { CurrentlyRunning = false, IsAdmin });
|
||||
}
|
||||
}
|
||||
|
||||
private Response GetGravatarImage()
|
||||
{
|
||||
if (LoggedIn)
|
||||
{
|
||||
var user = UserHelper.GetUser(Username);
|
||||
var hashed = StringHasher.CalcuateMd5Hash(user.EmailAddress);
|
||||
if (string.IsNullOrEmpty(hashed))
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false
|
||||
});
|
||||
}
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = true,
|
||||
Message = $"https://www.gravatar.com/avatar/{hashed}"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel {Result = false});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ using Nancy;
|
|||
using Nancy.Responses.Negotiation;
|
||||
using NLog;
|
||||
using Ombi.Api.Interfaces;
|
||||
using Ombi.Api.Models.Sonarr;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.Models;
|
||||
using Ombi.Core.SettingModels;
|
||||
|
@ -65,9 +66,13 @@ namespace Ombi.UI.Modules
|
|||
ISickRageApi sickRageApi,
|
||||
ICacheProvider cache,
|
||||
IAnalytics an,
|
||||
INotificationEngine engine,
|
||||
IPlexNotificationEngine engine,
|
||||
IEmbyNotificationEngine embyEngine,
|
||||
ISecurityExtensions security,
|
||||
ISettingsService<CustomizationSettings> customSettings) : base("requests", prSettings, security)
|
||||
ISettingsService<CustomizationSettings> customSettings,
|
||||
ISettingsService<EmbySettings> embyS,
|
||||
ISettingsService<RadarrSettings> radarr,
|
||||
IRadarrApi radarrApi) : base("requests", prSettings, security)
|
||||
{
|
||||
Service = service;
|
||||
PrSettings = prSettings;
|
||||
|
@ -81,8 +86,12 @@ namespace Ombi.UI.Modules
|
|||
CpApi = cpApi;
|
||||
Cache = cache;
|
||||
Analytics = an;
|
||||
NotificationEngine = engine;
|
||||
PlexNotificationEngine = engine;
|
||||
EmbyNotificationEngine = embyEngine;
|
||||
CustomizationSettings = customSettings;
|
||||
EmbySettings = embyS;
|
||||
Radarr = radarr;
|
||||
RadarrApi = radarrApi;
|
||||
|
||||
Get["/", true] = async (x, ct) => await LoadRequests();
|
||||
Get["/movies", true] = async (x, ct) => await GetMovies();
|
||||
|
@ -96,7 +105,8 @@ namespace Ombi.UI.Modules
|
|||
|
||||
Post["/changeavailability", true] = async (x, ct) => await ChangeRequestAvailability((int)Request.Form.Id, (bool)Request.Form.Available);
|
||||
|
||||
Post["/changeRootFolder", true] = async (x, ct) => await ChangeRootFolder((int) Request.Form.requestId, (int) Request.Form.rootFolderId);
|
||||
Post["/changeRootFoldertv", true] = async (x, ct) => await ChangeRootFolder(RequestType.TvShow, (int)Request.Form.requestId, (int)Request.Form.rootFolderId);
|
||||
Post["/changeRootFoldermovie", true] = async (x, ct) => await ChangeRootFolder(RequestType.Movie, (int)Request.Form.requestId, (int)Request.Form.rootFolderId);
|
||||
|
||||
Get["/UpdateFilters", true] = async (x, ct) => await GetFilterAndSortSettings();
|
||||
}
|
||||
|
@ -111,11 +121,15 @@ namespace Ombi.UI.Modules
|
|||
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
||||
private ISettingsService<CouchPotatoSettings> CpSettings { get; }
|
||||
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
|
||||
private ISettingsService<RadarrSettings> Radarr { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
private ISonarrApi SonarrApi { get; }
|
||||
private IRadarrApi RadarrApi { get; }
|
||||
private ISickRageApi SickRageApi { get; }
|
||||
private ICouchPotatoApi CpApi { get; }
|
||||
private ICacheProvider Cache { get; }
|
||||
private INotificationEngine NotificationEngine { get; }
|
||||
private INotificationEngine PlexNotificationEngine { get; }
|
||||
private INotificationEngine EmbyNotificationEngine { get; }
|
||||
|
||||
private async Task<Negotiator> LoadRequests()
|
||||
{
|
||||
|
@ -138,32 +152,64 @@ namespace Ombi.UI.Modules
|
|||
}
|
||||
|
||||
List<QualityModel> qualities = new List<QualityModel>();
|
||||
var rootFolders = new List<RootFolderModel>();
|
||||
|
||||
var radarr = await Radarr.GetSettingsAsync();
|
||||
if (IsAdmin)
|
||||
{
|
||||
var cpSettings = CpSettings.GetSettings();
|
||||
if (cpSettings.Enabled)
|
||||
try
|
||||
{
|
||||
try
|
||||
var cpSettings = await CpSettings.GetSettingsAsync();
|
||||
if (cpSettings.Enabled)
|
||||
{
|
||||
var result = await Cache.GetOrSetAsync(CacheKeys.CouchPotatoQualityProfiles, async () =>
|
||||
try
|
||||
{
|
||||
return await Task.Run(() => CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey)).ConfigureAwait(false);
|
||||
});
|
||||
if (result != null)
|
||||
var result = await Cache.GetOrSetAsync(CacheKeys.CouchPotatoQualityProfiles, async () =>
|
||||
{
|
||||
return
|
||||
await Task.Run(() => CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey))
|
||||
.ConfigureAwait(false);
|
||||
});
|
||||
if (result != null)
|
||||
{
|
||||
qualities =
|
||||
result.list.Select(x => new QualityModel { Id = x._id, Name = x.label }).ToList();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
qualities = result.list.Select(x => new QualityModel { Id = x._id, Name = x.label }).ToList();
|
||||
Log.Info(e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
if (radarr.Enabled)
|
||||
{
|
||||
Log.Info(e);
|
||||
var rootFoldersResult = await Cache.GetOrSetAsync(CacheKeys.RadarrRootFolders, async () =>
|
||||
{
|
||||
return await Task.Run(() => RadarrApi.GetRootFolders(radarr.ApiKey, radarr.FullUri));
|
||||
});
|
||||
|
||||
rootFolders =
|
||||
rootFoldersResult.Select(
|
||||
x => new RootFolderModel { Id = x.id.ToString(), Path = x.path, FreeSpace = x.freespace })
|
||||
.ToList();
|
||||
|
||||
var result = await Cache.GetOrSetAsync(CacheKeys.RadarrQualityProfiles, async () =>
|
||||
{
|
||||
return await Task.Run(() => RadarrApi.GetProfiles(radarr.ApiKey, radarr.FullUri));
|
||||
});
|
||||
qualities = result.Select(x => new QualityModel { Id = x.id.ToString(), Name = x.name }).ToList();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var canManageRequest = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests);
|
||||
var allowViewUsers = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ViewUsers);
|
||||
|
||||
var viewModel = dbMovies.Select(movie => new RequestViewModel
|
||||
{
|
||||
ProviderId = movie.ProviderId,
|
||||
|
@ -180,7 +226,7 @@ namespace Ombi.UI.Modules
|
|||
Approved = movie.Available || movie.Approved,
|
||||
Title = movie.Title,
|
||||
Overview = movie.Overview,
|
||||
RequestedUsers = canManageRequest ? movie.AllUsers.ToArray() : new string[] { },
|
||||
RequestedUsers = canManageRequest || allowViewUsers ? movie.AllUsers.ToArray() : new string[] { },
|
||||
ReleaseYear = movie.ReleaseDate.Year.ToString(),
|
||||
Available = movie.Available,
|
||||
Admin = canManageRequest,
|
||||
|
@ -188,6 +234,9 @@ namespace Ombi.UI.Modules
|
|||
Denied = movie.Denied,
|
||||
DeniedReason = movie.DeniedReason,
|
||||
Qualities = qualities.ToArray(),
|
||||
HasRootFolders = rootFolders.Any(),
|
||||
RootFolders = rootFolders.ToArray(),
|
||||
CurrentRootPath = radarr.Enabled ? GetRootPath(movie.RootFolderSelected, radarr).Result : null
|
||||
}).ToList();
|
||||
|
||||
return Response.AsJson(viewModel);
|
||||
|
@ -220,14 +269,14 @@ namespace Ombi.UI.Modules
|
|||
});
|
||||
qualities = result.Select(x => new QualityModel { Id = x.id.ToString(), Name = x.name }).ToList();
|
||||
|
||||
|
||||
var rootFoldersResult =await Cache.GetOrSetAsync(CacheKeys.SonarrRootFolders, async () =>
|
||||
{
|
||||
return await Task.Run(() => SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri));
|
||||
});
|
||||
|
||||
rootFolders = rootFoldersResult.Select(x => new RootFolderModel { Id = x.id.ToString(), Path = x.path, FreeSpace = x.freespace}).ToList();
|
||||
}
|
||||
|
||||
var rootFoldersResult = await Cache.GetOrSetAsync(CacheKeys.SonarrRootFolders, async () =>
|
||||
{
|
||||
return await Task.Run(() => SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri));
|
||||
});
|
||||
|
||||
rootFolders = rootFoldersResult.Select(x => new RootFolderModel { Id = x.id.ToString(), Path = x.path, FreeSpace = x.freespace }).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
var sickRageSettings = await SickRageSettings.GetSettingsAsync();
|
||||
|
@ -247,6 +296,8 @@ namespace Ombi.UI.Modules
|
|||
|
||||
|
||||
var canManageRequest = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests);
|
||||
var allowViewUsers = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ViewUsers);
|
||||
|
||||
var viewModel = dbTv.Select(tv => new RequestViewModel
|
||||
{
|
||||
ProviderId = tv.ProviderId,
|
||||
|
@ -254,7 +305,7 @@ namespace Ombi.UI.Modules
|
|||
Status = tv.Status,
|
||||
ImdbId = tv.ImdbId,
|
||||
Id = tv.Id,
|
||||
PosterPath = tv.PosterPath.Contains("http:") ? tv.PosterPath.Replace("http:", "https:") : tv.PosterPath, // We make the poster path https on request, but this is just incase
|
||||
PosterPath = tv.PosterPath?.Contains("http:") ?? false ? tv.PosterPath?.Replace("http:", "https:") : tv.PosterPath ?? string.Empty, // We make the poster path https on request, but this is just incase
|
||||
ReleaseDate = tv.ReleaseDate,
|
||||
ReleaseDateTicks = tv.ReleaseDate.Ticks,
|
||||
RequestedDate = tv.RequestedDate,
|
||||
|
@ -263,7 +314,7 @@ namespace Ombi.UI.Modules
|
|||
Approved = tv.Available || tv.Approved,
|
||||
Title = tv.Title,
|
||||
Overview = tv.Overview,
|
||||
RequestedUsers = canManageRequest ? tv.AllUsers.ToArray() : new string[] { },
|
||||
RequestedUsers = canManageRequest || allowViewUsers ? tv.AllUsers.ToArray() : new string[] { },
|
||||
ReleaseYear = tv.ReleaseDate.Year.ToString(),
|
||||
Available = tv.Available,
|
||||
Admin = canManageRequest,
|
||||
|
@ -273,7 +324,7 @@ namespace Ombi.UI.Modules
|
|||
TvSeriesRequestType = tv.SeasonsRequested,
|
||||
Qualities = qualities.ToArray(),
|
||||
Episodes = tv.Episodes.ToArray(),
|
||||
RootFolders = rootFolders.ToArray(),
|
||||
RootFolders = rootFolders.ToArray(),
|
||||
HasRootFolders = rootFolders.Any(),
|
||||
CurrentRootPath = sonarrSettings.Enabled ? GetRootPath(tv.RootFolderSelected, sonarrSettings).Result : null
|
||||
}).ToList();
|
||||
|
@ -293,13 +344,48 @@ namespace Ombi.UI.Modules
|
|||
return r.path;
|
||||
}
|
||||
|
||||
// Return default path
|
||||
return rootFoldersResult.FirstOrDefault(x => x.id.Equals(int.Parse(sonarrSettings.RootPath)))?.path ?? string.Empty;
|
||||
int outRoot;
|
||||
var defaultPath = int.TryParse(sonarrSettings.RootPath, out outRoot);
|
||||
|
||||
if (defaultPath)
|
||||
{
|
||||
// Return default path
|
||||
return rootFoldersResult.FirstOrDefault(x => x.id.Equals(outRoot))?.path ?? string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return rootFoldersResult.FirstOrDefault()?.path ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetRootPath(int pathId, RadarrSettings radarrSettings)
|
||||
{
|
||||
var rootFoldersResult = await Cache.GetOrSetAsync(CacheKeys.RadarrRootFolders, async () =>
|
||||
{
|
||||
return await Task.Run(() => RadarrApi.GetRootFolders(radarrSettings.ApiKey, radarrSettings.FullUri));
|
||||
});
|
||||
|
||||
foreach (var r in rootFoldersResult.Where(r => r.id == pathId))
|
||||
{
|
||||
return r.path;
|
||||
}
|
||||
|
||||
int outRoot;
|
||||
var defaultPath = int.TryParse(radarrSettings.RootPath, out outRoot);
|
||||
|
||||
if (defaultPath)
|
||||
{
|
||||
// Return default path
|
||||
return rootFoldersResult.FirstOrDefault(x => x.id.Equals(outRoot))?.path ?? string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return rootFoldersResult.FirstOrDefault()?.path ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Response> GetAlbumRequests()
|
||||
{
|
||||
var settings = PrSettings.GetSettings();
|
||||
var dbAlbum = await Service.GetAllAsync();
|
||||
dbAlbum = dbAlbum.Where(x => x.Type == RequestType.Album);
|
||||
if (Security.HasPermissions(User, Permissions.UsersCanViewOnlyOwnRequests) && !IsAdmin)
|
||||
|
@ -438,8 +524,21 @@ namespace Ombi.UI.Modules
|
|||
originalRequest.Available = available;
|
||||
|
||||
var result = await Service.UpdateRequestAsync(originalRequest);
|
||||
var plexService = await PlexSettings.GetSettingsAsync();
|
||||
await NotificationEngine.NotifyUsers(originalRequest, plexService.PlexAuthToken, available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined);
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
await
|
||||
PlexNotificationEngine.NotifyUsers(originalRequest,
|
||||
available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined);
|
||||
}
|
||||
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
await EmbyNotificationEngine.NotifyUsers(originalRequest,
|
||||
available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined);
|
||||
}
|
||||
return Response.AsJson(result
|
||||
? new { Result = true, Available = available, Message = string.Empty }
|
||||
: new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" });
|
||||
|
@ -461,11 +560,21 @@ namespace Ombi.UI.Modules
|
|||
return Response.AsJson(vm);
|
||||
}
|
||||
|
||||
private async Task<Response> ChangeRootFolder(int id, int rootFolderId)
|
||||
private async Task<Response> ChangeRootFolder(RequestType type, int id, int rootFolderId)
|
||||
{
|
||||
// Get all root folders
|
||||
var settings = await SonarrSettings.GetSettingsAsync();
|
||||
var rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
|
||||
var rootFolders = new List<SonarrRootFolder>();
|
||||
if (type == RequestType.TvShow)
|
||||
{
|
||||
// Get all root folders
|
||||
var settings = await SonarrSettings.GetSettingsAsync();
|
||||
rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var settings = await Radarr.GetSettingsAsync();
|
||||
rootFolders = RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
|
||||
}
|
||||
|
||||
// Get Request
|
||||
var allRequests = await Service.GetAllAsync();
|
||||
|
@ -473,7 +582,7 @@ namespace Ombi.UI.Modules
|
|||
|
||||
if (request == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel {Result = false});
|
||||
return Response.AsJson(new JsonResponseModel { Result = false });
|
||||
}
|
||||
|
||||
foreach (var folder in rootFolders)
|
||||
|
@ -487,7 +596,7 @@ namespace Ombi.UI.Modules
|
|||
|
||||
await Service.UpdateRequestAsync(request);
|
||||
|
||||
return Response.AsJson(new JsonResponseModel {Result = true});
|
||||
}
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace Ombi.UI.Modules
|
|||
|
||||
public async Task<Response> Netflix(string title)
|
||||
{
|
||||
await Task.Yield();
|
||||
|
||||
var result = NetflixApi.CheckNetflix(title);
|
||||
|
||||
if (!string.IsNullOrEmpty(result.Message))
|
||||
|
|
|
@ -50,9 +50,11 @@ using Ombi.Helpers;
|
|||
using Ombi.Helpers.Analytics;
|
||||
using Ombi.Helpers.Permissions;
|
||||
using Ombi.Services.Interfaces;
|
||||
using Ombi.Services.Jobs;
|
||||
using Ombi.Services.Notification;
|
||||
using Ombi.Store;
|
||||
using Ombi.Store.Models;
|
||||
using Ombi.Store.Models.Emby;
|
||||
using Ombi.Store.Models.Plex;
|
||||
using Ombi.Store.Repository;
|
||||
using Ombi.UI.Helpers;
|
||||
|
@ -67,8 +69,8 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
public class SearchModule : BaseAuthModule
|
||||
{
|
||||
public SearchModule(ICacheProvider cache,
|
||||
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
|
||||
public SearchModule(ICacheProvider cache,
|
||||
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker plexChecker,
|
||||
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings,
|
||||
ISettingsService<SickRageSettings> sickRageService, ISickRageApi srApi,
|
||||
INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi,
|
||||
|
@ -77,7 +79,8 @@ namespace Ombi.UI.Modules
|
|||
ISettingsService<PlexSettings> plexService, ISettingsService<AuthenticationSettings> auth,
|
||||
IRepository<UsersToNotify> u, ISettingsService<EmailNotificationSettings> email,
|
||||
IIssueService issue, IAnalytics a, IRepository<RequestLimit> rl, ITransientFaultQueue tfQueue, IRepository<PlexContent> content,
|
||||
ISecurityExtensions security, IMovieSender movieSender, IRadarrCacher radarrCacher, ITraktApi traktApi, ISettingsService<CustomizationSettings> cus)
|
||||
ISecurityExtensions security, IMovieSender movieSender, IRadarrCacher radarrCacher, ITraktApi traktApi, ISettingsService<CustomizationSettings> cus,
|
||||
IEmbyAvailabilityChecker embyChecker, IRepository<EmbyContent> embyContent, ISettingsService<EmbySettings> embySettings)
|
||||
: base("search", prSettings, security)
|
||||
{
|
||||
Auth = auth;
|
||||
|
@ -86,7 +89,7 @@ namespace Ombi.UI.Modules
|
|||
PrService = prSettings;
|
||||
MovieApi = new TheMovieDbApi();
|
||||
Cache = cache;
|
||||
Checker = checker;
|
||||
PlexChecker = plexChecker;
|
||||
CpCacher = cpCacher;
|
||||
SonarrCacher = sonarrCacher;
|
||||
SickRageCacher = sickRageCacher;
|
||||
|
@ -112,9 +115,14 @@ namespace Ombi.UI.Modules
|
|||
RadarrCacher = radarrCacher;
|
||||
TraktApi = traktApi;
|
||||
CustomizationSettings = cus;
|
||||
EmbyChecker = embyChecker;
|
||||
EmbyContentRepository = embyContent;
|
||||
EmbySettings = embySettings;
|
||||
|
||||
Get["SearchIndex", "/", true] = async (x, ct) => await RequestLoad();
|
||||
|
||||
Get["actor/{searchTerm}", true] = async (x, ct) => await SearchPerson((string)x.searchTerm);
|
||||
Get["actor/new/{searchTerm}", true] = async (x, ct) => await SearchPerson((string)x.searchTerm, true);
|
||||
Get["movie/{searchTerm}", true] = async (x, ct) => await SearchMovie((string)x.searchTerm);
|
||||
Get["tv/{searchTerm}", true] = async (x, ct) => await SearchTvShow((string)x.searchTerm);
|
||||
Get["music/{searchTerm}", true] = async (x, ct) => await SearchAlbum((string)x.searchTerm);
|
||||
|
@ -135,7 +143,7 @@ namespace Ombi.UI.Modules
|
|||
async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
|
||||
Post["request/tvEpisodes", true] = async (x, ct) => await RequestTvShow(0, "episode");
|
||||
Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId);
|
||||
|
||||
|
||||
Get["/seasons"] = x => GetSeasons();
|
||||
Get["/episodes", true] = async (x, ct) => await GetEpisodes();
|
||||
}
|
||||
|
@ -143,6 +151,7 @@ namespace Ombi.UI.Modules
|
|||
private IWatcherCacher WatcherCacher { get; }
|
||||
private IMovieSender MovieSender { get; }
|
||||
private IRepository<PlexContent> PlexContentRepository { get; }
|
||||
private IRepository<EmbyContent> EmbyContentRepository { get; }
|
||||
private TvMazeApi TvApi { get; }
|
||||
private IPlexApi PlexApi { get; }
|
||||
private TheMovieDbApi MovieApi { get; }
|
||||
|
@ -152,13 +161,15 @@ namespace Ombi.UI.Modules
|
|||
private IRequestService RequestService { get; }
|
||||
private ICacheProvider Cache { get; }
|
||||
private ISettingsService<AuthenticationSettings> Auth { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
private ISettingsService<PlexSettings> PlexService { get; }
|
||||
private ISettingsService<PlexRequestSettings> PrService { get; }
|
||||
private ISettingsService<SonarrSettings> SonarrService { get; }
|
||||
private ISettingsService<SickRageSettings> SickRageService { get; }
|
||||
private ISettingsService<HeadphonesSettings> HeadphonesService { get; }
|
||||
private ISettingsService<EmailNotificationSettings> EmailNotificationSettings { get; }
|
||||
private IAvailabilityChecker Checker { get; }
|
||||
private IAvailabilityChecker PlexChecker { get; }
|
||||
private IEmbyAvailabilityChecker EmbyChecker { get; }
|
||||
private ICouchPotatoCacher CpCacher { get; }
|
||||
private ISonarrCacher SonarrCacher { get; }
|
||||
private ISickRageCacher SickRageCacher { get; }
|
||||
|
@ -173,15 +184,28 @@ namespace Ombi.UI.Modules
|
|||
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private long _plexMovieCacheTime = 0;
|
||||
private IEnumerable<PlexContent> _plexMovies = null;
|
||||
|
||||
private long _embyMovieCacheTime = 0;
|
||||
private IEnumerable<EmbyContent> _embyMovies = null;
|
||||
|
||||
|
||||
private long _dbMovieCacheTime = 0;
|
||||
private Dictionary<int, RequestedModel> _dbMovies = null;
|
||||
|
||||
private async Task<Negotiator> RequestLoad()
|
||||
{
|
||||
|
||||
var settings = await PrService.GetSettingsAsync();
|
||||
var custom = await CustomizationSettings.GetSettingsAsync();
|
||||
var emby = await EmbySettings.GetSettingsAsync();
|
||||
var plex = await PlexService.GetSettingsAsync();
|
||||
var searchViewModel = new SearchLoadViewModel
|
||||
{
|
||||
Settings = settings,
|
||||
CustomizationSettings = custom
|
||||
CustomizationSettings = custom,
|
||||
Emby = emby.Enable,
|
||||
Plex = plex.Enable
|
||||
};
|
||||
|
||||
|
||||
|
@ -209,6 +233,53 @@ namespace Ombi.UI.Modules
|
|||
return await ProcessMovies(MovieSearchType.Search, searchTerm);
|
||||
}
|
||||
|
||||
private async Task<Response> SearchPerson(string searchTerm)
|
||||
{
|
||||
var movies = TransformMovieListToMovieResultList(await MovieApi.SearchPerson(searchTerm));
|
||||
return await TransformMovieResultsToResponse(movies);
|
||||
}
|
||||
|
||||
private async Task<Response> SearchPerson(string searchTerm, bool filterExisting)
|
||||
{
|
||||
var movies = TransformMovieListToMovieResultList(await MovieApi.SearchPerson(searchTerm, AlreadyAvailable));
|
||||
return await TransformMovieResultsToResponse(movies);
|
||||
}
|
||||
|
||||
private async Task<bool> AlreadyAvailable(int id, string title, string year)
|
||||
{
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
|
||||
return IsMovieInCache(id, String.Empty) ||
|
||||
(plexSettings.Enable && PlexChecker.IsMovieAvailable(PlexMovies(), title, year)) ||
|
||||
(embySettings.Enable && EmbyChecker.IsMovieAvailable(EmbyMovies(), title, year, String.Empty));
|
||||
}
|
||||
|
||||
private IEnumerable<PlexContent> PlexMovies()
|
||||
{ long now = DateTime.Now.Ticks;
|
||||
if(_plexMovies == null || (now - _plexMovieCacheTime) > 10000)
|
||||
{
|
||||
var content = PlexContentRepository.GetAll();
|
||||
_plexMovies = PlexChecker.GetPlexMovies(content);
|
||||
_plexMovieCacheTime = now;
|
||||
}
|
||||
|
||||
return _plexMovies;
|
||||
}
|
||||
|
||||
private IEnumerable<EmbyContent> EmbyMovies()
|
||||
{
|
||||
long now = DateTime.Now.Ticks;
|
||||
if (_embyMovies == null || (now - _embyMovieCacheTime) > 10000)
|
||||
{
|
||||
var content = EmbyContentRepository.GetAll();
|
||||
_embyMovies = EmbyChecker.GetEmbyMovies(content);
|
||||
_embyMovieCacheTime = now;
|
||||
}
|
||||
|
||||
return _embyMovies;
|
||||
}
|
||||
|
||||
private Response GetTvPoster(int theTvDbId)
|
||||
{
|
||||
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
|
||||
|
@ -220,15 +291,10 @@ namespace Ombi.UI.Modules
|
|||
}
|
||||
return banner;
|
||||
}
|
||||
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
|
||||
{
|
||||
List<MovieResult> apiMovies;
|
||||
|
||||
switch (searchType)
|
||||
{
|
||||
case MovieSearchType.Search:
|
||||
var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false);
|
||||
apiMovies = movies.Select(x =>
|
||||
private List<MovieResult> TransformSearchMovieListToMovieResultList(List<TMDbLib.Objects.Search.SearchMovie> searchMovies)
|
||||
{
|
||||
return searchMovies.Select(x =>
|
||||
new MovieResult
|
||||
{
|
||||
Adult = x.Adult,
|
||||
|
@ -247,6 +313,39 @@ namespace Ombi.UI.Modules
|
|||
VoteCount = x.VoteCount
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private List<MovieResult> TransformMovieListToMovieResultList(List<TMDbLib.Objects.Movies.Movie> movies)
|
||||
{
|
||||
return movies.Select(x =>
|
||||
new MovieResult
|
||||
{
|
||||
Adult = x.Adult,
|
||||
BackdropPath = x.BackdropPath,
|
||||
GenreIds = x.Genres.Select(y => y.Id).ToList(),
|
||||
Id = x.Id,
|
||||
OriginalLanguage = x.OriginalLanguage,
|
||||
OriginalTitle = x.OriginalTitle,
|
||||
Overview = x.Overview,
|
||||
Popularity = x.Popularity,
|
||||
PosterPath = x.PosterPath,
|
||||
ReleaseDate = x.ReleaseDate,
|
||||
Title = x.Title,
|
||||
Video = x.Video,
|
||||
VoteAverage = x.VoteAverage,
|
||||
VoteCount = x.VoteCount
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
|
||||
{
|
||||
List<MovieResult> apiMovies;
|
||||
|
||||
switch (searchType)
|
||||
{
|
||||
case MovieSearchType.Search:
|
||||
var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false);
|
||||
apiMovies = TransformSearchMovieListToMovieResultList(movies);
|
||||
break;
|
||||
case MovieSearchType.CurrentlyPlaying:
|
||||
apiMovies = await MovieApi.GetCurrentPlayingMovies();
|
||||
|
@ -259,21 +358,31 @@ namespace Ombi.UI.Modules
|
|||
break;
|
||||
}
|
||||
|
||||
var allResults = await RequestService.GetAllAsync();
|
||||
allResults = allResults.Where(x => x.Type == RequestType.Movie);
|
||||
return await TransformMovieResultsToResponse(apiMovies);
|
||||
}
|
||||
|
||||
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
|
||||
var dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
|
||||
private async Task<Dictionary<int, RequestedModel>> RequestedMovies()
|
||||
{
|
||||
long now = DateTime.Now.Ticks;
|
||||
if (_dbMovies == null || (now - _dbMovieCacheTime) > 10000)
|
||||
{
|
||||
var allResults = await RequestService.GetAllAsync();
|
||||
allResults = allResults.Where(x => x.Type == RequestType.Movie);
|
||||
|
||||
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
|
||||
_dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
|
||||
_dbMovieCacheTime = now;
|
||||
}
|
||||
return _dbMovies;
|
||||
}
|
||||
|
||||
var cpCached = CpCacher.QueuedIds();
|
||||
var watcherCached = WatcherCacher.QueuedIds();
|
||||
var radarrCached = RadarrCacher.QueuedIds();
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var plexMovies = Checker.GetPlexMovies(content);
|
||||
private async Task<Response> TransformMovieResultsToResponse(List<MovieResult> movies)
|
||||
{
|
||||
await Task.Yield();
|
||||
var viewMovies = new List<SearchMovieViewModel>();
|
||||
var counter = 0;
|
||||
foreach (var movie in apiMovies)
|
||||
Dictionary<int, RequestedModel> dbMovies = await RequestedMovies();
|
||||
foreach (var movie in movies)
|
||||
{
|
||||
var viewMovie = new SearchMovieViewModel
|
||||
{
|
||||
|
@ -293,11 +402,10 @@ namespace Ombi.UI.Modules
|
|||
VoteCount = movie.VoteCount
|
||||
};
|
||||
|
||||
var imdbId = string.Empty;
|
||||
if (counter <= 5) // Let's only do it for the first 5 items
|
||||
{
|
||||
var movieInfo = MovieApi.GetMovieInformationWithVideos(movie.Id);
|
||||
|
||||
|
||||
// TODO needs to be careful about this, it's adding extra time to search...
|
||||
// https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
|
||||
viewMovie.ImdbId = movieInfo?.imdb_id;
|
||||
|
@ -313,16 +421,37 @@ namespace Ombi.UI.Modules
|
|||
counter++;
|
||||
}
|
||||
|
||||
|
||||
var canSee = CanUserSeeThisRequest(viewMovie.Id, Security.HasPermissions(User, Permissions.UsersCanViewOnlyOwnRequests), dbMovies);
|
||||
var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString(),
|
||||
imdbId);
|
||||
if (plexMovie != null)
|
||||
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
viewMovie.Available = true;
|
||||
viewMovie.PlexUrl = plexMovie.Url;
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var plexMovies = PlexChecker.GetPlexMovies(content);
|
||||
|
||||
var plexMovie = PlexChecker.GetMovie(plexMovies.ToArray(), movie.Title,
|
||||
movie.ReleaseDate?.Year.ToString(),
|
||||
viewMovie.ImdbId);
|
||||
if (plexMovie != null)
|
||||
{
|
||||
viewMovie.Available = true;
|
||||
viewMovie.PlexUrl = plexMovie.Url;
|
||||
}
|
||||
}
|
||||
else if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
var embyContent = EmbyContentRepository.GetAll();
|
||||
var embyMovies = EmbyChecker.GetEmbyMovies(embyContent);
|
||||
|
||||
var embyMovie = EmbyChecker.GetMovie(embyMovies.ToArray(), movie.Title,
|
||||
movie.ReleaseDate?.Year.ToString(), viewMovie.ImdbId);
|
||||
if (embyMovie != null)
|
||||
{
|
||||
viewMovie.Available = true;
|
||||
}
|
||||
}
|
||||
if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db
|
||||
{
|
||||
var dbm = dbMovies[movie.Id];
|
||||
|
||||
|
@ -330,20 +459,11 @@ namespace Ombi.UI.Modules
|
|||
viewMovie.Approved = dbm.Approved;
|
||||
viewMovie.Available = dbm.Available;
|
||||
}
|
||||
else if (cpCached.Contains(movie.Id) && canSee) // compare to the couchpotato db
|
||||
else if (canSee)
|
||||
{
|
||||
viewMovie.Approved = true;
|
||||
viewMovie.Requested = true;
|
||||
}
|
||||
else if(watcherCached.Contains(imdbId) && canSee) // compare to the watcher db
|
||||
{
|
||||
viewMovie.Approved = true;
|
||||
viewMovie.Requested = true;
|
||||
}
|
||||
else if (radarrCached.Contains(movie.Id) && canSee)
|
||||
{
|
||||
viewMovie.Approved = true;
|
||||
viewMovie.Requested = true;
|
||||
bool exists = IsMovieInCache(movie, viewMovie.ImdbId);
|
||||
viewMovie.Approved = exists;
|
||||
viewMovie.Requested = exists;
|
||||
}
|
||||
viewMovies.Add(viewMovie);
|
||||
}
|
||||
|
@ -351,6 +471,19 @@ namespace Ombi.UI.Modules
|
|||
return Response.AsJson(viewMovies);
|
||||
}
|
||||
|
||||
private bool IsMovieInCache(MovieResult movie, string imdbId)
|
||||
{ int id = movie.Id;
|
||||
return IsMovieInCache(id, imdbId);
|
||||
}
|
||||
|
||||
private bool IsMovieInCache(int id, string imdbId)
|
||||
{ var cpCached = CpCacher.QueuedIds();
|
||||
var watcherCached = WatcherCacher.QueuedIds();
|
||||
var radarrCached = RadarrCacher.QueuedIds();
|
||||
|
||||
return cpCached.Contains(id) || watcherCached.Contains(imdbId) || radarrCached.Contains(id);
|
||||
}
|
||||
|
||||
private bool CanUserSeeThisRequest(int movieId, bool usersCanViewOnlyOwnRequests,
|
||||
Dictionary<int, RequestedModel> moviesInDb)
|
||||
{
|
||||
|
@ -372,11 +505,11 @@ namespace Ombi.UI.Modules
|
|||
case ShowSearchType.Popular:
|
||||
Analytics.TrackEventAsync(Category.Search, Action.TvShow, "Popular", Username, CookieHelper.GetAnalyticClientId(Cookies));
|
||||
var popularShows = await TraktApi.GetPopularShows();
|
||||
|
||||
|
||||
foreach (var popularShow in popularShows)
|
||||
{
|
||||
var theTvDbId = int.Parse(popularShow.Ids.Tvdb.ToString());
|
||||
|
||||
|
||||
var model = new SearchTvShowViewModel
|
||||
{
|
||||
FirstAired = popularShow.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
|
@ -405,6 +538,11 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
var show = anticipatedShow.Show;
|
||||
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
|
||||
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var model = new SearchTvShowViewModel
|
||||
{
|
||||
|
@ -434,6 +572,12 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
var show = watched.Show;
|
||||
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
|
||||
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var model = new SearchTvShowViewModel
|
||||
{
|
||||
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
|
@ -462,6 +606,12 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
var show = watched.Show;
|
||||
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
|
||||
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var model = new SearchTvShowViewModel
|
||||
{
|
||||
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
|
@ -493,51 +643,55 @@ namespace Ombi.UI.Modules
|
|||
|
||||
private async Task<List<SearchTvShowViewModel>> MapToTvModel(List<SearchTvShowViewModel> shows, PlexRequestSettings prSettings)
|
||||
{
|
||||
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
|
||||
var providerId = string.Empty;
|
||||
// Get the requests
|
||||
var allResults = await RequestService.GetAllAsync();
|
||||
allResults = allResults.Where(x => x.Type == RequestType.TvShow);
|
||||
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
|
||||
var dbTv = distinctResults.ToDictionary(x => x.ProviderId);
|
||||
|
||||
// Check the external applications
|
||||
var sonarrCached = SonarrCacher.QueuedIds().ToList();
|
||||
var sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays
|
||||
var dbTv = distinctResults.ToDictionary(x => x.ImdbId);
|
||||
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var plexTvShows = Checker.GetPlexTvShows(content).ToList();
|
||||
var plexTvShows = PlexChecker.GetPlexTvShows(content);
|
||||
var embyContent = EmbyContentRepository.GetAll();
|
||||
var embyCached = EmbyChecker.GetEmbyTvShows(embyContent).ToList();
|
||||
|
||||
foreach (var show in shows)
|
||||
{
|
||||
if (plexSettings.AdvancedSearch)
|
||||
|
||||
var providerId = show.Id.ToString();
|
||||
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
providerId = show.Id.ToString();
|
||||
var embyShow = EmbyChecker.GetTvShow(embyCached.ToArray(), show.SeriesName, show.FirstAired?.Substring(0, 4), providerId);
|
||||
if (embyShow != null)
|
||||
{
|
||||
show.Available = true;
|
||||
}
|
||||
}
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
var plexShow = PlexChecker.GetTvShow(plexTvShows.ToArray(), show.SeriesName, show.FirstAired?.Substring(0, 4),
|
||||
providerId);
|
||||
if (plexShow != null)
|
||||
{
|
||||
show.Available = true;
|
||||
show.PlexUrl = plexShow.Url;
|
||||
}
|
||||
}
|
||||
|
||||
var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), show.SeriesName, show.FirstAired?.Substring(0, 4),
|
||||
providerId);
|
||||
if (plexShow != null)
|
||||
if (show.ImdbId != null && !show.Available)
|
||||
{
|
||||
show.Available = true;
|
||||
show.PlexUrl = plexShow.Url;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dbTv.ContainsKey(show.Id))
|
||||
var imdbId = show.ImdbId;
|
||||
if (dbTv.ContainsKey(imdbId))
|
||||
{
|
||||
var dbt = dbTv[show.Id];
|
||||
var dbt = dbTv[imdbId];
|
||||
|
||||
show.Requested = true;
|
||||
show.Episodes = dbt.Episodes.ToList();
|
||||
show.Approved = dbt.Approved;
|
||||
}
|
||||
if (sonarrCached.Select(x => x.TvdbId).Contains(show.Id) || sickRageCache.Contains(show.Id))
|
||||
// compare to the sonarr/sickrage db
|
||||
{
|
||||
show.Requested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return shows;
|
||||
|
@ -549,6 +703,7 @@ namespace Ombi.UI.Modules
|
|||
Analytics.TrackEventAsync(Category.Search, Action.TvShow, searchTerm, Username,
|
||||
CookieHelper.GetAnalyticClientId(Cookies));
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
var prSettings = await PrService.GetSettingsAsync();
|
||||
var providerId = string.Empty;
|
||||
|
||||
|
@ -571,7 +726,9 @@ namespace Ombi.UI.Modules
|
|||
var sonarrCached = SonarrCacher.QueuedIds();
|
||||
var sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var plexTvShows = Checker.GetPlexTvShows(content);
|
||||
var plexTvShows = PlexChecker.GetPlexTvShows(content);
|
||||
var embyContent = EmbyContentRepository.GetAll();
|
||||
var embyCached = EmbyChecker.GetEmbyTvShows(embyContent);
|
||||
|
||||
var viewTv = new List<SearchTvShowViewModel>();
|
||||
foreach (var t in apiTv)
|
||||
|
@ -605,20 +762,28 @@ namespace Ombi.UI.Modules
|
|||
EnableTvRequestsForOnlySeries = (prSettings.DisableTvRequestsByEpisode && prSettings.DisableTvRequestsBySeason)
|
||||
};
|
||||
|
||||
providerId = viewT.Id.ToString();
|
||||
|
||||
if (plexSettings.AdvancedSearch)
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
providerId = viewT.Id.ToString();
|
||||
var embyShow = EmbyChecker.GetTvShow(embyCached.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId);
|
||||
if (embyShow != null)
|
||||
{
|
||||
viewT.Available = true;
|
||||
}
|
||||
}
|
||||
|
||||
var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4),
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
var plexShow = PlexChecker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4),
|
||||
providerId);
|
||||
if (plexShow != null)
|
||||
{
|
||||
viewT.Available = true;
|
||||
viewT.PlexUrl = plexShow.Url;
|
||||
if (plexShow != null)
|
||||
{
|
||||
viewT.Available = true;
|
||||
viewT.PlexUrl = plexShow.Url;
|
||||
}
|
||||
}
|
||||
else if (t.show?.externals?.thetvdb != null)
|
||||
|
||||
if (t.show?.externals?.thetvdb != null && !viewT.Available)
|
||||
{
|
||||
var tvdbid = (int)t.show.externals.thetvdb;
|
||||
if (dbTv.ContainsKey(tvdbid))
|
||||
|
@ -658,7 +823,7 @@ namespace Ombi.UI.Modules
|
|||
var dbAlbum = allResults.ToDictionary(x => x.MusicBrainzId);
|
||||
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var plexAlbums = Checker.GetPlexAlbums(content);
|
||||
var plexAlbums = PlexChecker.GetPlexAlbums(content);
|
||||
|
||||
var viewAlbum = new List<SearchMusicViewModel>();
|
||||
foreach (var a in apiAlbums)
|
||||
|
@ -678,7 +843,7 @@ namespace Ombi.UI.Modules
|
|||
DateTime release;
|
||||
DateTimeHelper.CustomParse(a.ReleaseEvents?.FirstOrDefault()?.date, out release);
|
||||
var artist = a.ArtistCredit?.FirstOrDefault()?.artist;
|
||||
var plexAlbum = Checker.GetAlbum(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name);
|
||||
var plexAlbum = PlexChecker.GetAlbum(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name);
|
||||
if (plexAlbum != null)
|
||||
{
|
||||
viewA.Available = true;
|
||||
|
@ -719,7 +884,7 @@ namespace Ombi.UI.Modules
|
|||
Message = "You have reached your weekly request limit for Movies! Please contact your admin."
|
||||
});
|
||||
}
|
||||
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
Analytics.TrackEventAsync(Category.Search, Action.Request, "Movie", Username,
|
||||
CookieHelper.GetAnalyticClientId(Cookies));
|
||||
var movieInfo = await MovieApi.GetMovieInformation(movieId);
|
||||
|
@ -760,8 +925,8 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var movies = Checker.GetPlexMovies(content);
|
||||
if (Checker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
|
||||
var movies = PlexChecker.GetPlexMovies(content);
|
||||
if (PlexChecker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
|
@ -778,7 +943,7 @@ namespace Ombi.UI.Modules
|
|||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName)
|
||||
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName,GetMediaServerName())
|
||||
});
|
||||
}
|
||||
//#endif
|
||||
|
@ -817,13 +982,13 @@ namespace Ombi.UI.Modules
|
|||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Message = "Could not add movie, please contract your administrator",
|
||||
Message = "Could not add movie, please contact your administrator",
|
||||
Result = false
|
||||
});
|
||||
}
|
||||
if (!result.MovieSendingEnabled)
|
||||
{
|
||||
|
||||
|
||||
return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
||||
}
|
||||
|
||||
|
@ -918,7 +1083,7 @@ namespace Ombi.UI.Modules
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
var showInfo = TvApi.ShowLookupByTheTvDbId(showId);
|
||||
DateTime firstAir;
|
||||
DateTime.TryParse(showInfo.premiered, out firstAir);
|
||||
|
@ -1025,7 +1190,7 @@ namespace Ombi.UI.Modules
|
|||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
|
||||
Message = $"{fullShowName} {string.Format(Resources.UI.Search_AlreadyInPlex,embySettings.Enable ? "Emby" : "Plex")}"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1043,66 +1208,134 @@ namespace Ombi.UI.Modules
|
|||
try
|
||||
{
|
||||
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var shows = Checker.GetPlexTvShows(content);
|
||||
var providerId = string.Empty;
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
if (plexSettings.AdvancedSearch)
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
providerId = showId.ToString();
|
||||
}
|
||||
if (episodeRequest)
|
||||
{
|
||||
var cachedEpisodesTask = await Checker.GetEpisodes();
|
||||
var cachedEpisodes = cachedEpisodesTask.ToList();
|
||||
foreach (var d in difference) // difference is from an existing request
|
||||
{
|
||||
if (
|
||||
cachedEpisodes.Any(
|
||||
x =>
|
||||
x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber &&
|
||||
x.ProviderId == providerId))
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message =
|
||||
$"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {Resources.UI.Search_AlreadyInPlex}"
|
||||
});
|
||||
}
|
||||
}
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var shows = PlexChecker.GetPlexTvShows(content);
|
||||
|
||||
var diff = await GetEpisodeRequestDifference(showId, model);
|
||||
model.Episodes = diff.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (plexSettings.EnableTvEpisodeSearching)
|
||||
var providerId = string.Empty;
|
||||
if (plexSettings.AdvancedSearch)
|
||||
{
|
||||
foreach (var s in showInfo.Season)
|
||||
providerId = showId.ToString();
|
||||
}
|
||||
if (episodeRequest)
|
||||
{
|
||||
var cachedEpisodesTask = await PlexChecker.GetEpisodes();
|
||||
var cachedEpisodes = cachedEpisodesTask.ToList();
|
||||
foreach (var d in difference) // difference is from an existing request
|
||||
{
|
||||
var result = Checker.IsEpisodeAvailable(showId.ToString(), s.SeasonNumber, s.EpisodeNumber);
|
||||
if (result)
|
||||
if (
|
||||
cachedEpisodes.Any(
|
||||
x =>
|
||||
x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber &&
|
||||
x.ProviderId == providerId))
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
|
||||
Message =
|
||||
$"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var diff = await GetEpisodeRequestDifference(showId, model);
|
||||
model.Episodes = diff.ToList();
|
||||
}
|
||||
else if (Checker.IsTvShowAvailable(shows.ToArray(), showInfo.name, showInfo.premiered?.Substring(0, 4),
|
||||
providerId, model.SeasonList))
|
||||
else
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
if (plexSettings.EnableTvEpisodeSearching)
|
||||
{
|
||||
foreach (var s in showInfo.Season)
|
||||
{
|
||||
Result = false,
|
||||
Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
|
||||
});
|
||||
var result = PlexChecker.IsEpisodeAvailable(showId.ToString(), s.SeasonNumber,
|
||||
s.EpisodeNumber);
|
||||
if (result)
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = $"{fullShowName} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PlexChecker.IsTvShowAvailable(shows.ToArray(), showInfo.name,
|
||||
showInfo.premiered?.Substring(0, 4),
|
||||
providerId, model.SeasonList))
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = $"{fullShowName} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
var embyContent = EmbyContentRepository.GetAll();
|
||||
var embyMovies = EmbyChecker.GetEmbyTvShows(embyContent);
|
||||
var providerId = showId.ToString();
|
||||
if (episodeRequest)
|
||||
{
|
||||
var cachedEpisodesTask = await EmbyChecker.GetEpisodes();
|
||||
var cachedEpisodes = cachedEpisodesTask.ToList();
|
||||
foreach (var d in difference) // difference is from an existing request
|
||||
{
|
||||
if (
|
||||
cachedEpisodes.Any(
|
||||
x =>
|
||||
x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber &&
|
||||
x.ProviderId == providerId))
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message =
|
||||
$"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var diff = await GetEpisodeRequestDifference(showId, model);
|
||||
model.Episodes = diff.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (embySettings.EnableEpisodeSearching)
|
||||
{
|
||||
foreach (var s in showInfo.Season)
|
||||
{
|
||||
var result = EmbyChecker.IsEpisodeAvailable(showId.ToString(), s.SeasonNumber,
|
||||
s.EpisodeNumber);
|
||||
if (result)
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = $"{fullShowName} is already in Emby!"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (EmbyChecker.IsTvShowAvailable(embyMovies.ToArray(), showInfo.name,
|
||||
showInfo.premiered?.Substring(0, 4),
|
||||
providerId, model.SeasonList))
|
||||
{
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = $"{fullShowName} is already in Emby!"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1112,7 +1345,7 @@ namespace Ombi.UI.Modules
|
|||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullShowName)
|
||||
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullShowName,GetMediaServerName())
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1187,9 +1420,7 @@ namespace Ombi.UI.Modules
|
|||
|
||||
private bool ShouldSendNotification(RequestType type, PlexRequestSettings prSettings)
|
||||
{
|
||||
var sendNotification = ShouldAutoApprove(type)
|
||||
? !prSettings.IgnoreNotifyForAutoApprovedRequests
|
||||
: true;
|
||||
var sendNotification = !ShouldAutoApprove(type) || !prSettings.IgnoreNotifyForAutoApprovedRequests;
|
||||
|
||||
if (IsAdmin)
|
||||
{
|
||||
|
@ -1261,8 +1492,8 @@ namespace Ombi.UI.Modules
|
|||
|
||||
|
||||
var content = PlexContentRepository.GetAll();
|
||||
var albums = Checker.GetPlexAlbums(content);
|
||||
var alreadyInPlex = Checker.IsAlbumAvailable(albums.ToArray(), albumInfo.title, release.ToString("yyyy"),
|
||||
var albums = PlexChecker.GetPlexAlbums(content);
|
||||
var alreadyInPlex = PlexChecker.IsAlbumAvailable(albums.ToArray(), albumInfo.title, release.ToString("yyyy"),
|
||||
artist.name);
|
||||
|
||||
if (alreadyInPlex)
|
||||
|
@ -1280,6 +1511,7 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
Title = albumInfo.title,
|
||||
MusicBrainzId = albumInfo.id,
|
||||
ReleaseId = releaseId,
|
||||
Overview = albumInfo.disambiguation,
|
||||
PosterPath = img,
|
||||
Type = RequestType.Album,
|
||||
|
@ -1348,7 +1580,7 @@ namespace Ombi.UI.Modules
|
|||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
private Response GetSeasons()
|
||||
{
|
||||
var seriesId = (int)Request.Query.tvId;
|
||||
|
@ -1390,7 +1622,8 @@ namespace Ombi.UI.Modules
|
|||
|
||||
var existingRequest = requests.FirstOrDefault(x => x.Type == RequestType.TvShow && x.TvDbId == providerId.ToString());
|
||||
var show = await Task.Run(() => TvApi.ShowLookupByTheTvDbId(providerId));
|
||||
var tvMaxeEpisodes = await Task.Run(() => TvApi.EpisodeLookup(show.id));
|
||||
var tvMazeEpisodesTask = await Task.Run(() => TvApi.EpisodeLookup(show.id));
|
||||
var tvMazeEpisodes = tvMazeEpisodesTask.ToList();
|
||||
|
||||
var sonarrEpisodes = new List<SonarrEpisodes>();
|
||||
if (sonarrEnabled)
|
||||
|
@ -1400,26 +1633,59 @@ namespace Ombi.UI.Modules
|
|||
sonarrEpisodes = sonarrEp?.ToList() ?? new List<SonarrEpisodes>();
|
||||
}
|
||||
|
||||
var plexCacheTask = await Checker.GetEpisodes(providerId);
|
||||
var plexCache = plexCacheTask.ToList();
|
||||
foreach (var ep in tvMaxeEpisodes)
|
||||
var plexSettings = await PlexService.GetSettingsAsync();
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
var requested = existingRequest?.Episodes
|
||||
.Any(episodesModel =>
|
||||
ep.number == episodesModel.EpisodeNumber && ep.season == episodesModel.SeasonNumber) ?? false;
|
||||
|
||||
var alreadyInPlex = plexCache.Any(x => x.EpisodeNumber == ep.number && x.SeasonNumber == ep.season);
|
||||
var inSonarr = sonarrEpisodes.Any(x => x.seasonNumber == ep.season && x.episodeNumber == ep.number && x.hasFile);
|
||||
|
||||
model.Add(new EpisodeListViewModel
|
||||
var plexCacheTask = await PlexChecker.GetEpisodes(providerId);
|
||||
var plexCache = plexCacheTask.ToList();
|
||||
foreach (var ep in tvMazeEpisodes)
|
||||
{
|
||||
Id = show.id,
|
||||
SeasonNumber = ep.season,
|
||||
EpisodeNumber = ep.number,
|
||||
Requested = requested || alreadyInPlex || inSonarr,
|
||||
Name = ep.name,
|
||||
EpisodeId = ep.id
|
||||
});
|
||||
var requested = existingRequest?.Episodes
|
||||
.Any(episodesModel =>
|
||||
ep.number == episodesModel.EpisodeNumber &&
|
||||
ep.season == episodesModel.SeasonNumber) ?? false;
|
||||
|
||||
var alreadyInPlex = plexCache.Any(x => x.EpisodeNumber == ep.number && x.SeasonNumber == ep.season);
|
||||
var inSonarr =
|
||||
sonarrEpisodes.Any(x => x.seasonNumber == ep.season && x.episodeNumber == ep.number && x.hasFile);
|
||||
|
||||
model.Add(new EpisodeListViewModel
|
||||
{
|
||||
Id = show.id,
|
||||
SeasonNumber = ep.season,
|
||||
EpisodeNumber = ep.number,
|
||||
Requested = requested || alreadyInPlex || inSonarr,
|
||||
Name = ep.name,
|
||||
EpisodeId = ep.id
|
||||
});
|
||||
}
|
||||
}
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
var embyCacheTask = await EmbyChecker.GetEpisodes(providerId);
|
||||
var cache = embyCacheTask.ToList();
|
||||
foreach (var ep in tvMazeEpisodes)
|
||||
{
|
||||
var requested = existingRequest?.Episodes
|
||||
.Any(episodesModel =>
|
||||
ep.number == episodesModel.EpisodeNumber &&
|
||||
ep.season == episodesModel.SeasonNumber) ?? false;
|
||||
|
||||
var alreadyInEmby = cache.Any(x => x.EpisodeNumber == ep.number && x.SeasonNumber == ep.season);
|
||||
var inSonarr =
|
||||
sonarrEpisodes.Any(x => x.seasonNumber == ep.season && x.episodeNumber == ep.number && x.hasFile);
|
||||
|
||||
model.Add(new EpisodeListViewModel
|
||||
{
|
||||
Id = show.id,
|
||||
SeasonNumber = ep.season,
|
||||
EpisodeNumber = ep.number,
|
||||
Requested = requested || alreadyInEmby || inSonarr,
|
||||
Name = ep.name,
|
||||
EpisodeId = ep.id
|
||||
});
|
||||
}
|
||||
}
|
||||
return model;
|
||||
|
||||
|
@ -1649,5 +1915,12 @@ namespace Ombi.UI.Modules
|
|||
return
|
||||
Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_TvNotSetUp });
|
||||
}
|
||||
|
||||
private string GetMediaServerName()
|
||||
{
|
||||
var e = EmbySettings.GetSettings();
|
||||
return e.Enable ? "Emby" : "Plex";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,9 @@ using Nancy;
|
|||
using Nancy.Extensions;
|
||||
using Nancy.Linker;
|
||||
using NLog;
|
||||
using Ombi.Api;
|
||||
using Ombi.Api.Interfaces;
|
||||
using Ombi.Api.Models.Emby;
|
||||
using Ombi.Api.Models.Plex;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.SettingModels;
|
||||
|
@ -44,6 +46,8 @@ using Ombi.Helpers.Analytics;
|
|||
using Ombi.Helpers.Permissions;
|
||||
using Ombi.Store;
|
||||
using Ombi.Store.Models;
|
||||
using Ombi.Store.Models.Emby;
|
||||
using Ombi.Store.Models.Plex;
|
||||
using Ombi.Store.Repository;
|
||||
using Ombi.UI.Authentication;
|
||||
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
|
||||
|
@ -54,59 +58,23 @@ namespace Ombi.UI.Modules
|
|||
public class UserLoginModule : BaseModule
|
||||
{
|
||||
public UserLoginModule(ISettingsService<AuthenticationSettings> auth, IPlexApi api, ISettingsService<PlexSettings> plexSettings, ISettingsService<PlexRequestSettings> pr,
|
||||
ISettingsService<LandingPageSettings> lp, IAnalytics a, IResourceLinker linker, IRepository<UserLogins> userLogins, IPlexUserRepository plexUsers, ICustomUserMapper custom,
|
||||
ISecurityExtensions security, ISettingsService<UserManagementSettings> userManagementSettings)
|
||||
ISettingsService<LandingPageSettings> lp, IAnalytics a, IResourceLinker linker, IRepository<UserLogins> userLogins, IExternalUserRepository<PlexUsers> plexUsers, ICustomUserMapper custom,
|
||||
ISecurityExtensions security, ISettingsService<UserManagementSettings> userManagementSettings, IEmbyApi embyApi, ISettingsService<EmbySettings> emby, IExternalUserRepository<EmbyUsers> embyU)
|
||||
: base("userlogin", pr, security)
|
||||
{
|
||||
AuthService = auth;
|
||||
LandingPageSettings = lp;
|
||||
Analytics = a;
|
||||
Api = api;
|
||||
PlexApi = api;
|
||||
PlexSettings = plexSettings;
|
||||
Linker = linker;
|
||||
UserLogins = userLogins;
|
||||
PlexUserRepository = plexUsers;
|
||||
CustomUserMapper = custom;
|
||||
UserManagementSettings = userManagementSettings;
|
||||
|
||||
//Get["UserLoginIndex", "/", true] = async (x, ct) =>
|
||||
//{
|
||||
// if (Request.Query["landing"] == null)
|
||||
// {
|
||||
// var s = await LandingPageSettings.GetSettingsAsync();
|
||||
// if (s.Enabled)
|
||||
// {
|
||||
// if (s.BeforeLogin) // Before login
|
||||
// {
|
||||
// if (string.IsNullOrEmpty(Username))
|
||||
// {
|
||||
// // They are not logged in
|
||||
// return
|
||||
// Context.GetRedirect(Linker.BuildRelativeUri(Context, "LandingPageIndex").ToString());
|
||||
// }
|
||||
// return Context.GetRedirect(Linker.BuildRelativeUri(Context, "SearchIndex").ToString());
|
||||
// }
|
||||
|
||||
// // After login
|
||||
// if (string.IsNullOrEmpty(Username))
|
||||
// {
|
||||
// // Not logged in yet
|
||||
// return Context.GetRedirect(Linker.BuildRelativeUri(Context, "UserLoginIndex").ToString() + "?landing");
|
||||
// }
|
||||
// // Send them to landing
|
||||
// var landingUrl = Linker.BuildRelativeUri(Context, "LandingPageIndex").ToString();
|
||||
// return Context.GetRedirect(landingUrl);
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (!string.IsNullOrEmpty(Username) || IsAdmin)
|
||||
// {
|
||||
// var url = Linker.BuildRelativeUri(Context, "SearchIndex").ToString();
|
||||
// return Response.AsRedirect(url);
|
||||
// }
|
||||
// var settings = await AuthService.GetSettingsAsync();
|
||||
// return View["Index", settings];
|
||||
//};
|
||||
EmbySettings = emby;
|
||||
EmbyApi = embyApi;
|
||||
EmbyUserRepository = embyU;
|
||||
|
||||
Post["/", true] = async (x, ct) => await LoginUser();
|
||||
Get["/logout"] = x => Logout();
|
||||
|
@ -157,11 +125,14 @@ namespace Ombi.UI.Modules
|
|||
private ISettingsService<AuthenticationSettings> AuthService { get; }
|
||||
private ISettingsService<LandingPageSettings> LandingPageSettings { get; }
|
||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||
private IPlexApi Api { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
private IPlexApi PlexApi { get; }
|
||||
private IEmbyApi EmbyApi { get; }
|
||||
private IResourceLinker Linker { get; }
|
||||
private IAnalytics Analytics { get; }
|
||||
private IRepository<UserLogins> UserLogins { get; }
|
||||
private IPlexUserRepository PlexUserRepository { get; }
|
||||
private IExternalUserRepository<PlexUsers> PlexUserRepository { get; }
|
||||
private IExternalUserRepository<EmbyUsers> EmbyUserRepository { get; }
|
||||
private ICustomUserMapper CustomUserMapper { get; }
|
||||
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
|
||||
|
||||
|
@ -180,41 +151,77 @@ namespace Ombi.UI.Modules
|
|||
}
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
|
||||
var authenticated = false;
|
||||
var isOwner = false;
|
||||
var userId = string.Empty;
|
||||
EmbyUser embyUser = null;
|
||||
|
||||
if (settings.UserAuthentication) // Check against the users in Plex
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
Log.Debug("Need to auth");
|
||||
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||
if (authenticated)
|
||||
if (settings.UserAuthentication) // Check against the users in Plex
|
||||
{
|
||||
userId = GetUserIdIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||
Log.Debug("Need to auth");
|
||||
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||
if (authenticated)
|
||||
{
|
||||
userId = GetUserIdIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||
}
|
||||
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, username))
|
||||
{
|
||||
Log.Debug("User is the account owner");
|
||||
authenticated = true;
|
||||
isOwner = true;
|
||||
userId = GetOwnerId(plexSettings.PlexAuthToken, username);
|
||||
}
|
||||
UsersModel dbUser = await IsDbuser(username);
|
||||
if (dbUser != null) // in the db?
|
||||
{
|
||||
var perms = (Permissions) dbUser.Permissions;
|
||||
authenticated = true;
|
||||
isOwner = perms.HasFlag(Permissions.Administrator);
|
||||
userId = dbUser.UserGuid;
|
||||
}
|
||||
Log.Debug("Friends list result = {0}", authenticated);
|
||||
}
|
||||
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, username))
|
||||
else if (!settings.UserAuthentication) // No auth, let them pass!
|
||||
{
|
||||
Log.Debug("User is the account owner");
|
||||
authenticated = true;
|
||||
isOwner = true;
|
||||
userId = GetOwnerId(plexSettings.PlexAuthToken, username);
|
||||
}
|
||||
UsersModel dbUser = await IsDbuser(username);
|
||||
if (dbUser != null) // in the db?
|
||||
{
|
||||
var perms = (Permissions)dbUser.Permissions;
|
||||
authenticated = true;
|
||||
isOwner = perms.HasFlag(Permissions.Administrator);
|
||||
userId = dbUser.UserGuid;
|
||||
}
|
||||
Log.Debug("Friends list result = {0}", authenticated);
|
||||
}
|
||||
else if (!settings.UserAuthentication) // No auth, let them pass!
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
authenticated = true;
|
||||
if (settings.UserAuthentication) // Check against the users in Plex
|
||||
{
|
||||
Log.Debug("Need to auth");
|
||||
authenticated = CheckIfEmbyUser(username, embySettings);
|
||||
if (authenticated)
|
||||
{
|
||||
embyUser = GetEmbyUser(username, embySettings);
|
||||
userId = embyUser?.Id;
|
||||
}
|
||||
if (embyUser?.Policy?.IsAdministrator ?? false)
|
||||
{
|
||||
Log.Debug("User is the account owner");
|
||||
authenticated = true;
|
||||
isOwner = true;
|
||||
}
|
||||
UsersModel dbUser = await IsDbuser(username);
|
||||
if (dbUser != null) // in the db?
|
||||
{
|
||||
var perms = (Permissions)dbUser.Permissions;
|
||||
authenticated = true;
|
||||
isOwner = perms.HasFlag(Permissions.Administrator);
|
||||
userId = dbUser.UserGuid;
|
||||
}
|
||||
Log.Debug("Friends list result = {0}", authenticated);
|
||||
}
|
||||
else if (!settings.UserAuthentication) // No auth, let them pass!
|
||||
{
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.UsePassword || isOwner || Security.HasPermissions(username, Permissions.Administrator))
|
||||
{
|
||||
Session[SessionKeys.UserLoginName] = username;
|
||||
|
@ -230,7 +237,7 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
return Response.AsJson(new { result = false, message = Resources.UI.UserLogin_IncorrectUserPass });
|
||||
}
|
||||
var result = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner);
|
||||
var result = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner, plexSettings.Enable, embySettings.Enable);
|
||||
|
||||
|
||||
var landingSettings = await LandingPageSettings.GetSettingsAsync();
|
||||
|
@ -292,36 +299,68 @@ namespace Ombi.UI.Modules
|
|||
var userId = string.Empty;
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
|
||||
if (settings.UserAuthentication) // Authenticate with Plex
|
||||
// attempt local login first as it has the least amount of overhead
|
||||
userId = CustomUserMapper.ValidateUser(username, password)?.ToString();
|
||||
if (userId != null)
|
||||
{
|
||||
Log.Debug("Need to auth and also provide pass");
|
||||
var signedIn = (PlexAuthentication)Api.SignIn(username, password);
|
||||
if (signedIn.user?.authentication_token != null)
|
||||
authenticated = true;
|
||||
}
|
||||
else if (userId == null && plexSettings.Enable)
|
||||
{
|
||||
if (settings.UserAuthentication) // Authenticate with Plex
|
||||
{
|
||||
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
||||
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, signedIn.user?.username))
|
||||
Log.Debug("Need to auth and also provide pass");
|
||||
var signedIn = (PlexAuthentication) PlexApi.SignIn(username, password);
|
||||
if (signedIn.user?.authentication_token != null)
|
||||
{
|
||||
Log.Debug("User is the account owner");
|
||||
authenticated = true;
|
||||
isOwner = true;
|
||||
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
||||
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, signedIn.user?.username))
|
||||
{
|
||||
Log.Debug("User is the account owner");
|
||||
authenticated = true;
|
||||
isOwner = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||
Log.Debug("Friends list result = {0}", authenticated);
|
||||
}
|
||||
userId = signedIn.user.uuid;
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
|
||||
Log.Debug("Friends list result = {0}", authenticated);
|
||||
}
|
||||
userId = signedIn.user.uuid;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(userId))
|
||||
else if (userId == null && embySettings.Enable)
|
||||
{
|
||||
// Local user?
|
||||
userId = CustomUserMapper.ValidateUser(username, password)?.ToString();
|
||||
if (userId != null)
|
||||
if (settings.UserAuthentication) // Authenticate with Emby
|
||||
{
|
||||
authenticated = true;
|
||||
Log.Debug("Need to auth and also provide pass");
|
||||
EmbyUser signedIn = null;
|
||||
try
|
||||
{
|
||||
signedIn = (EmbyUser)EmbyApi.LogIn(username, password, embySettings.ApiKey, embySettings.FullUri);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
if (signedIn != null)
|
||||
{
|
||||
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
||||
if (signedIn?.Policy?.IsAdministrator ?? false)
|
||||
{
|
||||
Log.Debug("User is the account owner");
|
||||
authenticated = true;
|
||||
isOwner = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticated = CheckIfEmbyUser(username, embySettings);
|
||||
Log.Debug("Friends list result = {0}", authenticated);
|
||||
}
|
||||
userId = signedIn?.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,8 +369,7 @@ namespace Ombi.UI.Modules
|
|||
return Response.AsJson(new { result = false, message = Resources.UI.UserLogin_IncorrectUserPass });
|
||||
}
|
||||
|
||||
|
||||
var m = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner);
|
||||
var m = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner, plexSettings.Enable, embySettings.Enable);
|
||||
|
||||
var landingSettings = await LandingPageSettings.GetSettingsAsync();
|
||||
|
||||
|
@ -354,7 +392,6 @@ namespace Ombi.UI.Modules
|
|||
return CustomModuleExtensions.LoginAndRedirect(this, m.LoginGuid, null, retVal.ToString());
|
||||
}
|
||||
return Response.AsJson(new { result = true, url = retVal.ToString() });
|
||||
|
||||
}
|
||||
|
||||
private async Task<Response> LoginUser()
|
||||
|
@ -399,7 +436,7 @@ namespace Ombi.UI.Modules
|
|||
if (settings.UserAuthentication && settings.UsePassword) // Authenticate with Plex
|
||||
{
|
||||
Log.Debug("Need to auth and also provide pass");
|
||||
var signedIn = (PlexAuthentication)Api.SignIn(username, password);
|
||||
var signedIn = (PlexAuthentication)PlexApi.SignIn(username, password);
|
||||
if (signedIn.user?.authentication_token != null)
|
||||
{
|
||||
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
||||
|
@ -553,59 +590,47 @@ namespace Ombi.UI.Modules
|
|||
public string UserId { get; set; }
|
||||
}
|
||||
|
||||
private async Task<LoginModel> AuthenticationSetup(string userId, string username, int dateTimeOffset, Guid loginGuid, bool isOwner)
|
||||
private async Task<LoginModel> AuthenticationSetup(string userId, string username, int dateTimeOffset, Guid loginGuid, bool isOwner, bool plex, bool emby)
|
||||
{
|
||||
var m = new LoginModel();
|
||||
var settings = await AuthService.GetSettingsAsync();
|
||||
|
||||
var localUsers = await CustomUserMapper.GetUsersAsync();
|
||||
var plexLocalUsers = await PlexUserRepository.GetAllAsync();
|
||||
var embyLocalUsers = await EmbyUserRepository.GetAllAsync();
|
||||
|
||||
var localUser = false;
|
||||
|
||||
|
||||
UserLogins.Insert(new UserLogins { UserId = userId, Type = UserType.PlexUser, LastLoggedIn = DateTime.UtcNow });
|
||||
Log.Debug("We are authenticated! Setting session.");
|
||||
// Add to the session (Used in the BaseModules)
|
||||
Session[SessionKeys.UsernameKey] = username;
|
||||
Session[SessionKeys.ClientDateTimeOffsetKey] = dateTimeOffset;
|
||||
|
||||
var plexLocal = plexLocalUsers.FirstOrDefault(x => x.Username == username);
|
||||
if (plexLocal != null)
|
||||
if (plex)
|
||||
{
|
||||
loginGuid = Guid.Parse(plexLocal.LoginId);
|
||||
var plexLocal = plexLocalUsers.FirstOrDefault(x => x.Username == username);
|
||||
if (plexLocal != null)
|
||||
{
|
||||
loginGuid = Guid.Parse(plexLocal.LoginId);
|
||||
}
|
||||
}
|
||||
if (emby)
|
||||
{
|
||||
var embyLocal = embyLocalUsers.FirstOrDefault(x => x.Username == username);
|
||||
if (embyLocal != null)
|
||||
{
|
||||
loginGuid = Guid.Parse(embyLocal.LoginId);
|
||||
}
|
||||
}
|
||||
|
||||
var dbUser = localUsers.FirstOrDefault(x => x.UserName == username);
|
||||
if (dbUser != null)
|
||||
{
|
||||
loginGuid = Guid.Parse(dbUser.UserGuid);
|
||||
localUser = true;
|
||||
}
|
||||
|
||||
//if (loginGuid != Guid.Empty)
|
||||
//{
|
||||
// if (!settings.UserAuthentication)// Do not need to auth make admin use login screen for now TODO remove this
|
||||
// {
|
||||
// if (dbUser != null)
|
||||
// {
|
||||
// var perms = (Permissions)dbUser.Permissions;
|
||||
// if (perms.HasFlag(Permissions.Administrator))
|
||||
// {
|
||||
// var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
||||
// Session["TempMessage"] = Resources.UI.UserLogin_AdminUsePassword;
|
||||
// //return Response.AsRedirect(uri.ToString());
|
||||
// }
|
||||
// }
|
||||
// if (plexLocal != null)
|
||||
// {
|
||||
// var perms = (Permissions)plexLocal.Permissions;
|
||||
// if (perms.HasFlag(Permissions.Administrator))
|
||||
// {
|
||||
// var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
|
||||
// Session["TempMessage"] = Resources.UI.UserLogin_AdminUsePassword;
|
||||
// //return Response.AsRedirect(uri.ToString());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
if (loginGuid == Guid.Empty && settings.UserAuthentication)
|
||||
{
|
||||
var defaultSettings = UserManagementSettings.GetSettings();
|
||||
|
@ -620,21 +645,52 @@ namespace Ombi.UI.Modules
|
|||
defaultPermissions += (int)Permissions.Administrator;
|
||||
}
|
||||
}
|
||||
|
||||
// Looks like we still don't have an entry, so this user does not exist
|
||||
await PlexUserRepository.InsertAsync(new PlexUsers
|
||||
if (plex)
|
||||
{
|
||||
PlexUserId = userId,
|
||||
UserAlias = string.Empty,
|
||||
Permissions = (int)defaultPermissions,
|
||||
Features = UserManagementHelper.GetPermissions(defaultSettings),
|
||||
Username = username,
|
||||
EmailAddress = string.Empty, // We don't have it, we will get it on the next scheduled job run (in 30 mins)
|
||||
LoginId = loginGuid.ToString()
|
||||
});
|
||||
// Looks like we still don't have an entry, so this user does not exist
|
||||
await PlexUserRepository.InsertAsync(new PlexUsers
|
||||
{
|
||||
PlexUserId = userId,
|
||||
UserAlias = string.Empty,
|
||||
Permissions = (int) defaultPermissions,
|
||||
Features = UserManagementHelper.GetPermissions(defaultSettings),
|
||||
Username = username,
|
||||
EmailAddress = string.Empty,
|
||||
// We don't have it, we will get it on the next scheduled job run (in 30 mins)
|
||||
LoginId = loginGuid.ToString()
|
||||
});
|
||||
}
|
||||
if (emby)
|
||||
{
|
||||
await EmbyUserRepository.InsertAsync(new EmbyUsers
|
||||
{
|
||||
EmbyUserId = userId,
|
||||
UserAlias = string.Empty,
|
||||
Permissions = (int)defaultPermissions,
|
||||
Features = UserManagementHelper.GetPermissions(defaultSettings),
|
||||
Username = username,
|
||||
EmailAddress = string.Empty,
|
||||
LoginId = loginGuid.ToString()
|
||||
});
|
||||
}
|
||||
}
|
||||
m.LoginGuid = loginGuid;
|
||||
m.UserId = userId;
|
||||
var type = UserType.LocalUser;
|
||||
if (localUser)
|
||||
{
|
||||
type = UserType.LocalUser;
|
||||
}
|
||||
else if (plex)
|
||||
{
|
||||
type = UserType.PlexUser;
|
||||
}
|
||||
else if (emby)
|
||||
{
|
||||
type = UserType.EmbyUser;;
|
||||
}
|
||||
UserLogins.Insert(new UserLogins { UserId = userId, Type = type, LastLoggedIn = DateTime.UtcNow });
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
@ -651,7 +707,7 @@ namespace Ombi.UI.Modules
|
|||
|
||||
private bool CheckIfUserIsOwner(string authToken, string userName)
|
||||
{
|
||||
var userAccount = Api.GetAccount(authToken);
|
||||
var userAccount = PlexApi.GetAccount(authToken);
|
||||
if (userAccount == null)
|
||||
{
|
||||
return false;
|
||||
|
@ -661,7 +717,7 @@ namespace Ombi.UI.Modules
|
|||
|
||||
private string GetOwnerId(string authToken, string userName)
|
||||
{
|
||||
var userAccount = Api.GetAccount(authToken);
|
||||
var userAccount = PlexApi.GetAccount(authToken);
|
||||
if (userAccount == null)
|
||||
{
|
||||
return string.Empty;
|
||||
|
@ -671,15 +727,45 @@ namespace Ombi.UI.Modules
|
|||
|
||||
private bool CheckIfUserIsInPlexFriends(string username, string authToken)
|
||||
{
|
||||
var users = Api.GetUsers(authToken);
|
||||
var users = PlexApi.GetUsers(authToken);
|
||||
var allUsers = users?.User?.Where(x => !string.IsNullOrEmpty(x.Title));
|
||||
return allUsers != null && allUsers.Any(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
|
||||
private bool CheckIfEmbyUser(string username, EmbySettings s)
|
||||
{
|
||||
try
|
||||
{
|
||||
var users = EmbyApi.GetUsers(s.FullUri, s.ApiKey);
|
||||
var allUsers = users?.Where(x => !string.IsNullOrEmpty(x.Name));
|
||||
return allUsers != null && allUsers.Any(x => x.Name.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private EmbyUser GetEmbyUser(string username, EmbySettings s)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var users = EmbyApi.GetUsers(s.FullUri, s.ApiKey);
|
||||
var allUsers = users?.Where(x => !string.IsNullOrEmpty(x.Name));
|
||||
return allUsers?.FirstOrDefault(x => x.Name.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string GetUserIdIsInPlexFriends(string username, string authToken)
|
||||
{
|
||||
var users = Api.GetUsers(authToken);
|
||||
var users = PlexApi.GetUsers(authToken);
|
||||
var allUsers = users?.User?.Where(x => !string.IsNullOrEmpty(x.Title));
|
||||
return allUsers?.Where(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase)).Select(x => x.Id).FirstOrDefault();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using Nancy.Extensions;
|
|||
using Nancy.Responses.Negotiation;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Api.Interfaces;
|
||||
using Ombi.Api.Models.Emby;
|
||||
using Ombi.Api.Models.Plex;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.Models;
|
||||
|
@ -16,6 +17,8 @@ using Ombi.Helpers.Analytics;
|
|||
using Ombi.Helpers.Permissions;
|
||||
using Ombi.Store;
|
||||
using Ombi.Store.Models;
|
||||
using Ombi.Store.Models.Emby;
|
||||
using Ombi.Store.Models.Plex;
|
||||
using Ombi.Store.Repository;
|
||||
using Ombi.UI.Models;
|
||||
using Ombi.UI.Models.UserManagement;
|
||||
|
@ -26,8 +29,8 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
public class UserManagementModule : BaseModule
|
||||
{
|
||||
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService<PlexSettings> plex, IRepository<UserLogins> userLogins, IPlexUserRepository plexRepo
|
||||
, ISecurityExtensions security, IRequestService req, IAnalytics ana) : base("usermanagement", pr, security)
|
||||
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService<PlexSettings> plex, IRepository<UserLogins> userLogins, IExternalUserRepository<PlexUsers> plexRepo
|
||||
, ISecurityExtensions security, IRequestService req, IAnalytics ana, ISettingsService<EmbySettings> embyService, IEmbyApi embyApi, IExternalUserRepository<EmbyUsers> embyRepo) : base("usermanagement", pr, security)
|
||||
{
|
||||
#if !DEBUG
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
@ -40,6 +43,9 @@ namespace Ombi.UI.Modules
|
|||
PlexRequestSettings = pr;
|
||||
RequestService = req;
|
||||
Analytics = ana;
|
||||
EmbySettings = embyService;
|
||||
EmbyApi = embyApi;
|
||||
EmbyRepository = embyRepo;
|
||||
|
||||
Get["/"] = x => Load();
|
||||
|
||||
|
@ -57,10 +63,13 @@ namespace Ombi.UI.Modules
|
|||
private IPlexApi PlexApi { get; }
|
||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||
private IRepository<UserLogins> UserLoginsRepo { get; }
|
||||
private IPlexUserRepository PlexUsersRepository { get; }
|
||||
private IExternalUserRepository<PlexUsers> PlexUsersRepository { get; }
|
||||
private IExternalUserRepository<EmbyUsers> EmbyRepository { get; }
|
||||
private ISettingsService<PlexRequestSettings> PlexRequestSettings { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
private IRequestService RequestService { get; }
|
||||
private IAnalytics Analytics { get; }
|
||||
private IEmbyApi EmbyApi { get; }
|
||||
|
||||
private Negotiator Load()
|
||||
{
|
||||
|
@ -69,48 +78,19 @@ namespace Ombi.UI.Modules
|
|||
|
||||
private async Task<Response> LoadUsers()
|
||||
{
|
||||
var localUsers = await UserMapper.GetUsersAsync();
|
||||
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
|
||||
var model = new List<UserManagementUsersViewModel>();
|
||||
|
||||
var userLogins = UserLoginsRepo.GetAll().ToList();
|
||||
|
||||
foreach (var user in localUsers)
|
||||
{
|
||||
var userDb = userLogins.FirstOrDefault(x => x.UserId == user.UserGuid);
|
||||
model.Add(MapLocalUser(user, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
if (!string.IsNullOrEmpty(plexSettings.PlexAuthToken))
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
//Get Plex Users
|
||||
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
|
||||
if (plexUsers != null && plexUsers.User != null) {
|
||||
foreach (var u in plexUsers.User) {
|
||||
var dbUser = plexDbUsers.FirstOrDefault (x => x.PlexUserId == u.Id);
|
||||
var userDb = userLogins.FirstOrDefault (x => x.UserId == u.Id);
|
||||
|
||||
// We don't have the user in the database yet
|
||||
if (dbUser == null) {
|
||||
model.Add (MapPlexUser (u, null, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
} else {
|
||||
// The Plex User is in the database
|
||||
model.Add (MapPlexUser (u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also get the server admin
|
||||
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
|
||||
if (account != null)
|
||||
{
|
||||
var dbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == account.Id);
|
||||
var userDb = userLogins.FirstOrDefault(x => x.UserId == account.Id);
|
||||
model.Add(MapPlexAdmin(account, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
return await LoadPlexUsers();
|
||||
}
|
||||
return Response.AsJson(model);
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
return await LoadEmbyUsers();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<Response> CreateUser()
|
||||
|
@ -217,64 +197,95 @@ namespace Ombi.UI.Modules
|
|||
}
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
|
||||
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
|
||||
var plexDbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == model.Id);
|
||||
var plexUser = plexUsers.User.FirstOrDefault(x => x.Id == model.Id);
|
||||
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
|
||||
if (plexDbUser != null && plexUser != null)
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
// We have a user in the DB for this Plex Account
|
||||
plexDbUser.Permissions = permissionsValue;
|
||||
plexDbUser.Features = featuresValue;
|
||||
|
||||
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
|
||||
|
||||
plexDbUser.UserAlias = model.Alias;
|
||||
plexDbUser.EmailAddress = model.EmailAddress;
|
||||
|
||||
await PlexUsersRepository.UpdateAsync(plexDbUser);
|
||||
|
||||
var retUser = MapPlexUser(plexUser, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
|
||||
return Response.AsJson(retUser);
|
||||
}
|
||||
|
||||
// So it could actually be the admin
|
||||
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
|
||||
if (plexDbUser != null && account != null)
|
||||
{
|
||||
// We have a user in the DB for this Plex Account
|
||||
plexDbUser.Permissions = permissionsValue;
|
||||
plexDbUser.Features = featuresValue;
|
||||
|
||||
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
|
||||
|
||||
plexDbUser.UserAlias = model.Alias;
|
||||
|
||||
await PlexUsersRepository.UpdateAsync(plexDbUser);
|
||||
|
||||
var retUser = MapPlexAdmin(account, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
|
||||
return Response.AsJson(retUser);
|
||||
}
|
||||
|
||||
// We have a Plex Account but he's not in the DB
|
||||
if (plexUser != null)
|
||||
{
|
||||
var user = new PlexUsers
|
||||
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
|
||||
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
|
||||
var plexDbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == model.Id);
|
||||
var plexUser = plexUsers.User.FirstOrDefault(x => x.Id == model.Id);
|
||||
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
|
||||
if (plexDbUser != null && plexUser != null)
|
||||
{
|
||||
Permissions = permissionsValue,
|
||||
Features = featuresValue,
|
||||
UserAlias = model.Alias,
|
||||
PlexUserId = plexUser.Id,
|
||||
EmailAddress = plexUser.Email,
|
||||
Username = plexUser.Title,
|
||||
LoginId = Guid.NewGuid().ToString()
|
||||
};
|
||||
// We have a user in the DB for this Plex Account
|
||||
plexDbUser.Permissions = permissionsValue;
|
||||
plexDbUser.Features = featuresValue;
|
||||
|
||||
await PlexUsersRepository.InsertAsync(user);
|
||||
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
|
||||
|
||||
plexDbUser.UserAlias = model.Alias;
|
||||
plexDbUser.EmailAddress = model.EmailAddress;
|
||||
|
||||
await PlexUsersRepository.UpdateAsync(plexDbUser);
|
||||
|
||||
var retUser = MapPlexUser(plexUser, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
|
||||
return Response.AsJson(retUser);
|
||||
}
|
||||
|
||||
// So it could actually be the admin
|
||||
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
|
||||
if (plexDbUser != null && account != null)
|
||||
{
|
||||
// We have a user in the DB for this Plex Account
|
||||
plexDbUser.Permissions = permissionsValue;
|
||||
plexDbUser.Features = featuresValue;
|
||||
|
||||
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
|
||||
|
||||
plexDbUser.UserAlias = model.Alias;
|
||||
|
||||
await PlexUsersRepository.UpdateAsync(plexDbUser);
|
||||
|
||||
var retUser = MapPlexAdmin(account, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
|
||||
return Response.AsJson(retUser);
|
||||
}
|
||||
|
||||
// We have a Plex Account but he's not in the DB
|
||||
if (plexUser != null)
|
||||
{
|
||||
var user = new PlexUsers
|
||||
{
|
||||
Permissions = permissionsValue,
|
||||
Features = featuresValue,
|
||||
UserAlias = model.Alias,
|
||||
PlexUserId = plexUser.Id,
|
||||
EmailAddress = plexUser.Email,
|
||||
Username = plexUser.Title,
|
||||
LoginId = Guid.NewGuid().ToString()
|
||||
};
|
||||
|
||||
await PlexUsersRepository.InsertAsync(user);
|
||||
|
||||
var retUser = MapPlexUser(plexUser, user, userLogin?.LastLoggedIn ?? DateTime.MinValue);
|
||||
return Response.AsJson(retUser);
|
||||
}
|
||||
}
|
||||
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
var embyDbUsers = await EmbyRepository.GetAllAsync();
|
||||
var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
|
||||
var selectedDbUser = embyDbUsers.FirstOrDefault(x => x.EmbyUserId == model.Id);
|
||||
var embyUser = embyUsers.FirstOrDefault(x => x.Id == model.Id);
|
||||
|
||||
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
|
||||
if (selectedDbUser != null && embyUser != null)
|
||||
{
|
||||
// We have a user in the DB for this Plex Account
|
||||
selectedDbUser.Permissions = permissionsValue;
|
||||
selectedDbUser.Features = featuresValue;
|
||||
|
||||
await UpdateRequests(selectedDbUser.Username, selectedDbUser.UserAlias, model.Alias);
|
||||
|
||||
selectedDbUser.UserAlias = model.Alias;
|
||||
selectedDbUser.EmailAddress = model.EmailAddress;
|
||||
|
||||
await EmbyRepository.UpdateAsync(selectedDbUser);
|
||||
|
||||
var retUser = MapEmbyUser(embyUser, selectedDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
|
||||
return Response.AsJson(retUser);
|
||||
}
|
||||
|
||||
var retUser = MapPlexUser(plexUser, user, userLogin?.LastLoggedIn ?? DateTime.MinValue);
|
||||
return Response.AsJson(retUser);
|
||||
}
|
||||
return null; // We should never end up here.
|
||||
}
|
||||
|
@ -416,7 +427,7 @@ namespace Ombi.UI.Modules
|
|||
var m = new UserManagementUsersViewModel
|
||||
{
|
||||
Id = plexInfo.Id,
|
||||
PermissionsFormattedString = newUser ? "Processing..." :( permissions == 0 ? "None" : permissions.ToString()),
|
||||
PermissionsFormattedString = newUser ? "Processing..." : (permissions == 0 ? "None" : permissions.ToString()),
|
||||
FeaturesFormattedString = newUser ? "Processing..." : features.ToString(),
|
||||
Username = plexInfo.Title,
|
||||
Type = UserType.PlexUser,
|
||||
|
@ -436,6 +447,36 @@ namespace Ombi.UI.Modules
|
|||
return m;
|
||||
}
|
||||
|
||||
private UserManagementUsersViewModel MapEmbyUser(EmbyUser embyInfo, EmbyUsers dbUser, DateTime lastLoggedIn)
|
||||
{
|
||||
var newUser = false;
|
||||
if (dbUser == null)
|
||||
{
|
||||
newUser = true;
|
||||
dbUser = new EmbyUsers();
|
||||
}
|
||||
var features = (Features)dbUser?.Features;
|
||||
var permissions = (Permissions)dbUser?.Permissions;
|
||||
|
||||
var m = new UserManagementUsersViewModel
|
||||
{
|
||||
Id = embyInfo.Id,
|
||||
PermissionsFormattedString = newUser ? "Processing..." : (permissions == 0 ? "None" : permissions.ToString()),
|
||||
FeaturesFormattedString = newUser ? "Processing..." : features.ToString(),
|
||||
Username = embyInfo.Name,
|
||||
Type = UserType.EmbyUser,
|
||||
EmailAddress =dbUser.EmailAddress,
|
||||
Alias = dbUser?.UserAlias ?? string.Empty,
|
||||
LastLoggedIn = lastLoggedIn,
|
||||
ManagedUser = false
|
||||
};
|
||||
|
||||
m.Permissions.AddRange(GetPermissions(permissions));
|
||||
m.Features.AddRange(GetFeatures(features));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
private UserManagementUsersViewModel MapPlexAdmin(PlexAccount plexInfo, PlexUsers dbUser, DateTime lastLoggedIn)
|
||||
{
|
||||
var newUser = false;
|
||||
|
@ -505,6 +546,93 @@ namespace Ombi.UI.Modules
|
|||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private async Task<Response> LoadPlexUsers()
|
||||
{
|
||||
var localUsers = await UserMapper.GetUsersAsync();
|
||||
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
|
||||
var model = new List<UserManagementUsersViewModel>();
|
||||
|
||||
var userLogins = UserLoginsRepo.GetAll().ToList();
|
||||
|
||||
foreach (var user in localUsers)
|
||||
{
|
||||
var userDb = userLogins.FirstOrDefault(x => x.UserId == user.UserGuid);
|
||||
model.Add(MapLocalUser(user, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
if (!string.IsNullOrEmpty(plexSettings.PlexAuthToken))
|
||||
{
|
||||
//Get Plex Users
|
||||
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
|
||||
if (plexUsers?.User != null)
|
||||
{
|
||||
foreach (var u in plexUsers.User)
|
||||
{
|
||||
var dbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == u.Id);
|
||||
var userDb = userLogins.FirstOrDefault(x => x.UserId == u.Id);
|
||||
|
||||
// We don't have the user in the database yet
|
||||
if (dbUser == null)
|
||||
{
|
||||
model.Add(MapPlexUser(u, null, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The Plex User is in the database
|
||||
model.Add(MapPlexUser(u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also get the server admin
|
||||
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
|
||||
if (account != null)
|
||||
{
|
||||
var dbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == account.Id);
|
||||
var userDb = userLogins.FirstOrDefault(x => x.UserId == account.Id);
|
||||
model.Add(MapPlexAdmin(account, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
}
|
||||
return Response.AsJson(model);
|
||||
}
|
||||
|
||||
private async Task<Response> LoadEmbyUsers()
|
||||
{
|
||||
var localUsers = await UserMapper.GetUsersAsync();
|
||||
var embyDbUsers = await EmbyRepository.GetAllAsync();
|
||||
var model = new List<UserManagementUsersViewModel>();
|
||||
|
||||
var userLogins = UserLoginsRepo.GetAll().ToList();
|
||||
|
||||
foreach (var user in localUsers)
|
||||
{
|
||||
var userDb = userLogins.FirstOrDefault(x => x.UserId == user.UserGuid);
|
||||
model.Add(MapLocalUser(user, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
if (!string.IsNullOrEmpty(embySettings.ApiKey))
|
||||
{
|
||||
//Get Plex Users
|
||||
var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
|
||||
if (embyUsers != null)
|
||||
{
|
||||
foreach (var u in embyUsers)
|
||||
{
|
||||
var dbUser = embyDbUsers.FirstOrDefault(x => x.EmbyUserId == u.Id);
|
||||
var userDb = userLogins.FirstOrDefault(x => x.UserId == u.Id);
|
||||
|
||||
// We don't have the user in the database yet
|
||||
model.Add(dbUser == null
|
||||
? MapEmbyUser(u, null, userDb?.LastLoggedIn ?? DateTime.MinValue)
|
||||
: MapEmbyUser(u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Response.AsJson(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#region Copyright
|
||||
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: UserWizardModule.cs
|
||||
|
@ -23,6 +24,7 @@
|
|||
// 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
|
||||
|
||||
using System;
|
||||
|
@ -50,8 +52,11 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
public class UserWizardModule : BaseModule
|
||||
{
|
||||
public UserWizardModule(ISettingsService<PlexRequestSettings> pr, ISettingsService<PlexSettings> plex, IPlexApi plexApi,
|
||||
ISettingsService<AuthenticationSettings> auth, ICustomUserMapper m, IAnalytics a, ISecurityExtensions security) : base("wizard", pr, security)
|
||||
public UserWizardModule(ISettingsService<PlexRequestSettings> pr, ISettingsService<PlexSettings> plex,
|
||||
IPlexApi plexApi,
|
||||
ISettingsService<AuthenticationSettings> auth, ICustomUserMapper m, IAnalytics a,
|
||||
ISecurityExtensions security, IEmbyApi embyApi,
|
||||
ISettingsService<EmbySettings> embySettings) : base("wizard", pr, security)
|
||||
{
|
||||
PlexSettings = plex;
|
||||
PlexApi = plexApi;
|
||||
|
@ -59,10 +64,13 @@ namespace Ombi.UI.Modules
|
|||
Auth = auth;
|
||||
Mapper = m;
|
||||
Analytics = a;
|
||||
EmbySettings = embySettings;
|
||||
EmbyApi = embyApi;
|
||||
|
||||
Get["/", true] = async (x, ct) =>
|
||||
{
|
||||
a.TrackEventAsync(Category.Wizard, Action.Start, "Started the wizard", Username, CookieHelper.GetAnalyticClientId(Cookies));
|
||||
a.TrackEventAsync(Category.Wizard, Action.Start, "Started the wizard", Username,
|
||||
CookieHelper.GetAnalyticClientId(Cookies));
|
||||
|
||||
var settings = await PlexRequestSettings.GetSettingsAsync();
|
||||
|
||||
|
@ -76,7 +84,10 @@ namespace Ombi.UI.Modules
|
|||
Post["/plex", true] = async (x, ct) => await Plex();
|
||||
Post["/plexrequest", true] = async (x, ct) => await PlexRequest();
|
||||
Post["/auth", true] = async (x, ct) => await Authentication();
|
||||
Post["/createuser",true] = async (x,ct) => await CreateUser();
|
||||
Post["/createuser", true] = async (x, ct) => await CreateUser();
|
||||
|
||||
|
||||
Post["/embyauth", true] = async (x, ct) => await EmbyAuth();
|
||||
}
|
||||
|
||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||
|
@ -85,6 +96,8 @@ namespace Ombi.UI.Modules
|
|||
private ISettingsService<AuthenticationSettings> Auth { get; }
|
||||
private ICustomUserMapper Mapper { get; }
|
||||
private IAnalytics Analytics { get; }
|
||||
private IEmbyApi EmbyApi { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
@ -95,23 +108,31 @@ namespace Ombi.UI.Modules
|
|||
|
||||
if (string.IsNullOrEmpty(user.username) || string.IsNullOrEmpty(user.password))
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please provide a valid username and password" });
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "Please provide a valid username and password"
|
||||
});
|
||||
}
|
||||
|
||||
var model = PlexApi.SignIn(user.username, user.password);
|
||||
|
||||
if (model?.user == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Incorrect username or password!" });
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel { Result = false, Message = "Incorrect username or password!" });
|
||||
}
|
||||
|
||||
// Set the auth token in the session so we can use it in the next form
|
||||
Session[SessionKeys.UserWizardPlexAuth] = model.user.authentication_token;
|
||||
|
||||
|
||||
var servers = PlexApi.GetServer(model.user.authentication_token);
|
||||
var firstServer = servers.Server.FirstOrDefault();
|
||||
|
||||
return Response.AsJson(new { Result = true, firstServer?.Port, Ip = firstServer?.LocalAddresses, firstServer?.Scheme });
|
||||
|
||||
return
|
||||
Response.AsJson(
|
||||
new { Result = true, firstServer?.Port, Ip = firstServer?.LocalAddresses, firstServer?.Scheme });
|
||||
}
|
||||
|
||||
private async Task<Response> Plex()
|
||||
|
@ -122,7 +143,8 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
return Response.AsJson(valid.SendJsonError());
|
||||
}
|
||||
form.PlexAuthToken = Session[SessionKeys.UserWizardPlexAuth].ToString(); // Set the auth token from the previous form
|
||||
form.PlexAuthToken = Session[SessionKeys.UserWizardPlexAuth].ToString();
|
||||
// Set the auth token from the previous form
|
||||
|
||||
// Get the machine ID from the settings (This could have changed)
|
||||
try
|
||||
|
@ -131,6 +153,7 @@ namespace Ombi.UI.Modules
|
|||
var firstServer = servers.Server.FirstOrDefault(x => x.AccessToken == form.PlexAuthToken);
|
||||
|
||||
Session[SessionKeys.UserWizardMachineId] = firstServer?.MachineIdentifier;
|
||||
form.MachineIdentifier = firstServer?.MachineIdentifier;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -143,7 +166,12 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save the settings to the database, please try again." });
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "Could not save the settings to the database, please try again."
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<Response> PlexRequest()
|
||||
|
@ -158,14 +186,19 @@ namespace Ombi.UI.Modules
|
|||
currentSettings.SearchForMovies = form.SearchForMovies;
|
||||
currentSettings.SearchForTvShows = form.SearchForTvShows;
|
||||
currentSettings.SearchForMusic = form.SearchForMusic;
|
||||
|
||||
|
||||
var result = await PlexRequestSettings.SaveSettingsAsync(currentSettings);
|
||||
if (result)
|
||||
{
|
||||
return Response.AsJson(new { Result = true });
|
||||
}
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save the settings to the database, please try again." });
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "Could not save the settings to the database, please try again."
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<Response> Authentication()
|
||||
|
@ -177,14 +210,21 @@ namespace Ombi.UI.Modules
|
|||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save the settings to the database, please try again." });
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "Could not save the settings to the database, please try again."
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<Response> CreateUser()
|
||||
{
|
||||
var username = (string)Request.Form.Username;
|
||||
var userId = Mapper.CreateUser(username, Request.Form.Password, EnumHelper<Permissions>.All() - (int)Permissions.ReadOnlyUser, 0);
|
||||
Analytics.TrackEventAsync(Category.Wizard, Action.Finish, "Finished the wizard", username, CookieHelper.GetAnalyticClientId(Cookies));
|
||||
var userId = Mapper.CreateUser(username, Request.Form.Password,
|
||||
EnumHelper<Permissions>.All() - (int)Permissions.ReadOnlyUser, 0);
|
||||
Analytics.TrackEventAsync(Category.Wizard, Action.Finish, "Finished the wizard", username,
|
||||
CookieHelper.GetAnalyticClientId(Cookies));
|
||||
Session[SessionKeys.UsernameKey] = username;
|
||||
|
||||
// Destroy the Plex Auth Token
|
||||
|
@ -197,7 +237,55 @@ namespace Ombi.UI.Modules
|
|||
|
||||
var baseUrl = string.IsNullOrEmpty(settings.BaseUrl) ? string.Empty : $"/{settings.BaseUrl}";
|
||||
|
||||
return CustomModuleExtensions.LoginAndRedirect(this,(Guid)userId, fallbackRedirectUrl: $"{baseUrl}/search");
|
||||
return CustomModuleExtensions.LoginAndRedirect(this, (Guid)userId, fallbackRedirectUrl: $"{baseUrl}/search");
|
||||
}
|
||||
|
||||
private async Task<Response> EmbyAuth()
|
||||
{
|
||||
var ip = (string)Request.Form.Ip;
|
||||
var port = (int)Request.Form.Port;
|
||||
var apiKey = (string)Request.Form.ApiKey;
|
||||
var ssl = (bool)Request.Form.Ssl;
|
||||
|
||||
var settings = new EmbySettings
|
||||
{
|
||||
ApiKey = apiKey,
|
||||
Enable = true,
|
||||
Ip = ip,
|
||||
Port = port,
|
||||
Ssl = ssl,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// Test that we can connect
|
||||
var result = EmbyApi.GetUsers(settings.FullUri, apiKey);
|
||||
|
||||
if (result != null && result.Any())
|
||||
{
|
||||
settings.AdministratorId = result.FirstOrDefault(x => x.Policy.IsAdministrator)?.Id ?? string.Empty;
|
||||
await EmbySettings.SaveSettingsAsync(settings);
|
||||
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = true
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = $"Could not connect to Emby, please check your settings. Error: {e.Message}"
|
||||
});
|
||||
}
|
||||
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "Could not connect to Emby, please check your settings."
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue