mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
Merge branch 'dev' of https://github.com/tidusjar/Ombi into dev
This commit is contained in:
commit
f60eec4d4a
18 changed files with 238 additions and 69 deletions
4
.gitattributes
vendored
4
.gitattributes
vendored
|
@ -62,7 +62,5 @@
|
||||||
#*.rtf diff=astextplain
|
#*.rtf diff=astextplain
|
||||||
#*.RTF diff=astextplain
|
#*.RTF diff=astextplain
|
||||||
|
|
||||||
|
Ombi.UI/Content/* linguist-vendored
|
||||||
PlexRequests.UI/Content/* linguist-vendored
|
|
||||||
PlexRequests.UI/Content/* linguist-vendored
|
|
||||||
base.scss linguist-vendored=false
|
base.scss linguist-vendored=false
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace Ombi.Api.Models.Emby
|
||||||
{
|
{
|
||||||
public class EmbyUserdata
|
public class EmbyUserdata
|
||||||
{
|
{
|
||||||
public int PlaybackPositionTicks { get; set; }
|
public double PlaybackPositionTicks { get; set; }
|
||||||
public int PlayCount { get; set; }
|
public int PlayCount { get; set; }
|
||||||
public bool IsFavorite { get; set; }
|
public bool IsFavorite { get; set; }
|
||||||
public bool Played { get; set; }
|
public bool Played { get; set; }
|
||||||
|
|
|
@ -30,6 +30,7 @@ using System.Linq;
|
||||||
using Ombi.Core.Models;
|
using Ombi.Core.Models;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Helpers.Permissions;
|
using Ombi.Helpers.Permissions;
|
||||||
|
using Ombi.Store.Models.Emby;
|
||||||
using Ombi.Store.Models.Plex;
|
using Ombi.Store.Models.Plex;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
|
@ -37,16 +38,18 @@ namespace Ombi.Core.Users
|
||||||
{
|
{
|
||||||
public class UserHelper : IUserHelper
|
public class UserHelper : IUserHelper
|
||||||
{
|
{
|
||||||
public UserHelper(IUserRepository userRepository, IExternalUserRepository<PlexUsers> plexUsers, ISecurityExtensions security)
|
public UserHelper(IUserRepository userRepository, IExternalUserRepository<PlexUsers> plexUsers, IExternalUserRepository<EmbyUsers> emby, ISecurityExtensions security)
|
||||||
{
|
{
|
||||||
LocalUserRepository = userRepository;
|
LocalUserRepository = userRepository;
|
||||||
PlexUserRepository = plexUsers;
|
PlexUserRepository = plexUsers;
|
||||||
Security = security;
|
Security = security;
|
||||||
|
EmbyUserRepository = emby;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IUserRepository LocalUserRepository { get; }
|
private IUserRepository LocalUserRepository { get; }
|
||||||
private IExternalUserRepository<PlexUsers> PlexUserRepository { get; }
|
private IExternalUserRepository<PlexUsers> PlexUserRepository { get; }
|
||||||
private ISecurityExtensions Security { get; }
|
private ISecurityExtensions Security { get; }
|
||||||
|
private IExternalUserRepository<EmbyUsers> EmbyUserRepository { get; }
|
||||||
|
|
||||||
|
|
||||||
public IEnumerable<UserHelperModel> GetUsers()
|
public IEnumerable<UserHelperModel> GetUsers()
|
||||||
|
@ -54,7 +57,8 @@ namespace Ombi.Core.Users
|
||||||
var model = new List<UserHelperModel>();
|
var model = new List<UserHelperModel>();
|
||||||
|
|
||||||
var localUsers = LocalUserRepository.GetAll();
|
var localUsers = LocalUserRepository.GetAll();
|
||||||
var plexUsers = PlexUserRepository.GetAll();
|
var plexUsers = PlexUserRepository.GetAll().ToList();
|
||||||
|
var embyUsers = EmbyUserRepository.GetAll().ToList();
|
||||||
|
|
||||||
foreach (var user in localUsers)
|
foreach (var user in localUsers)
|
||||||
{
|
{
|
||||||
|
@ -69,14 +73,30 @@ namespace Ombi.Core.Users
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
model.AddRange(plexUsers.Select(user => new UserHelperModel
|
if (plexUsers.Any())
|
||||||
{
|
{
|
||||||
Type = UserType.LocalUser,
|
model.AddRange(plexUsers.Select(user => new UserHelperModel
|
||||||
Username = user.Username,
|
{
|
||||||
UserAlias = user.UserAlias,
|
Type = UserType.PlexUser,
|
||||||
EmailAddress = user.EmailAddress,
|
Username = user.Username,
|
||||||
Permissions = (Permissions)user.Permissions
|
UserAlias = user.UserAlias,
|
||||||
}));
|
EmailAddress = user.EmailAddress,
|
||||||
|
Permissions = (Permissions) user.Permissions
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (embyUsers.Any())
|
||||||
|
{
|
||||||
|
model.AddRange(embyUsers.Select(user => new UserHelperModel
|
||||||
|
{
|
||||||
|
Type = UserType.EmbyUser,
|
||||||
|
Username = user.Username,
|
||||||
|
UserAlias = user.UserAlias,
|
||||||
|
EmailAddress = user.EmailAddress,
|
||||||
|
Permissions = (Permissions)user.Permissions
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@ -87,9 +107,11 @@ namespace Ombi.Core.Users
|
||||||
|
|
||||||
var localUsers = LocalUserRepository.GetAll().ToList();
|
var localUsers = LocalUserRepository.GetAll().ToList();
|
||||||
var plexUsers = PlexUserRepository.GetAll().ToList();
|
var plexUsers = PlexUserRepository.GetAll().ToList();
|
||||||
|
var embyUsers = EmbyUserRepository.GetAll().ToList();
|
||||||
|
|
||||||
var filteredLocal = localUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
|
var filteredLocal = localUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
|
||||||
var filteredPlex = plexUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
|
var filteredPlex = plexUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
|
||||||
|
var filteredEmby = embyUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
|
||||||
|
|
||||||
|
|
||||||
foreach (var user in filteredLocal)
|
foreach (var user in filteredLocal)
|
||||||
|
@ -108,7 +130,7 @@ namespace Ombi.Core.Users
|
||||||
|
|
||||||
model.AddRange(filteredPlex.Select(user => new UserHelperModel
|
model.AddRange(filteredPlex.Select(user => new UserHelperModel
|
||||||
{
|
{
|
||||||
Type = UserType.LocalUser,
|
Type = UserType.PlexUser,
|
||||||
Username = user.Username,
|
Username = user.Username,
|
||||||
UserAlias = user.UserAlias,
|
UserAlias = user.UserAlias,
|
||||||
EmailAddress = user.EmailAddress,
|
EmailAddress = user.EmailAddress,
|
||||||
|
@ -116,6 +138,17 @@ namespace Ombi.Core.Users
|
||||||
Features = (Features)user.Features
|
Features = (Features)user.Features
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
model.AddRange(filteredEmby.Select(user => new UserHelperModel
|
||||||
|
{
|
||||||
|
Type = UserType.EmbyUser,
|
||||||
|
Username = user.Username,
|
||||||
|
UserAlias = user.UserAlias,
|
||||||
|
EmailAddress = user.EmailAddress,
|
||||||
|
Permissions = (Permissions)user.Permissions,
|
||||||
|
Features = (Features)user.Features
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +158,11 @@ namespace Ombi.Core.Users
|
||||||
|
|
||||||
var localUsers = LocalUserRepository.GetAll().ToList();
|
var localUsers = LocalUserRepository.GetAll().ToList();
|
||||||
var plexUsers = PlexUserRepository.GetAll().ToList();
|
var plexUsers = PlexUserRepository.GetAll().ToList();
|
||||||
|
var embyUsers = PlexUserRepository.GetAll().ToList();
|
||||||
|
|
||||||
var filteredLocal = localUsers.Where(x => ((Features)x.Features).HasFlag(features));
|
var filteredLocal = localUsers.Where(x => ((Features)x.Features).HasFlag(features));
|
||||||
var filteredPlex = plexUsers.Where(x => ((Features)x.Features).HasFlag(features));
|
var filteredPlex = plexUsers.Where(x => ((Features)x.Features).HasFlag(features));
|
||||||
|
var filteredEmby = embyUsers.Where(x => ((Features)x.Features).HasFlag(features));
|
||||||
|
|
||||||
|
|
||||||
foreach (var user in filteredLocal)
|
foreach (var user in filteredLocal)
|
||||||
|
@ -146,7 +181,17 @@ namespace Ombi.Core.Users
|
||||||
|
|
||||||
model.AddRange(filteredPlex.Select(user => new UserHelperModel
|
model.AddRange(filteredPlex.Select(user => new UserHelperModel
|
||||||
{
|
{
|
||||||
Type = UserType.LocalUser,
|
Type = UserType.PlexUser,
|
||||||
|
Username = user.Username,
|
||||||
|
UserAlias = user.UserAlias,
|
||||||
|
EmailAddress = user.EmailAddress,
|
||||||
|
Permissions = (Permissions)user.Permissions,
|
||||||
|
Features = (Features)user.Features
|
||||||
|
}));
|
||||||
|
|
||||||
|
model.AddRange(filteredEmby.Select(user => new UserHelperModel
|
||||||
|
{
|
||||||
|
Type = UserType.EmbyUser,
|
||||||
Username = user.Username,
|
Username = user.Username,
|
||||||
UserAlias = user.UserAlias,
|
UserAlias = user.UserAlias,
|
||||||
EmailAddress = user.EmailAddress,
|
EmailAddress = user.EmailAddress,
|
||||||
|
|
|
@ -81,7 +81,10 @@ namespace Ombi.Services.Jobs
|
||||||
public void CheckAndUpdateAll()
|
public void CheckAndUpdateAll()
|
||||||
{
|
{
|
||||||
var embySettings = Emby.GetSettings();
|
var embySettings = Emby.GetSettings();
|
||||||
|
if (!embySettings.Enable)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!ValidateSettings(embySettings))
|
if (!ValidateSettings(embySettings))
|
||||||
{
|
{
|
||||||
Log.Debug("Validation of the Emby settings failed.");
|
Log.Debug("Validation of the Emby settings failed.");
|
||||||
|
|
|
@ -69,7 +69,10 @@ namespace Ombi.Services.Jobs
|
||||||
public void CacheContent()
|
public void CacheContent()
|
||||||
{
|
{
|
||||||
var embySettings = Emby.GetSettings();
|
var embySettings = Emby.GetSettings();
|
||||||
|
if (!embySettings.Enable)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!ValidateSettings(embySettings))
|
if (!ValidateSettings(embySettings))
|
||||||
{
|
{
|
||||||
Log.Debug("Validation of emby settings failed.");
|
Log.Debug("Validation of emby settings failed.");
|
||||||
|
|
|
@ -82,6 +82,11 @@ namespace Ombi.Services.Jobs
|
||||||
|
|
||||||
var plexSettings = Plex.GetSettings();
|
var plexSettings = Plex.GetSettings();
|
||||||
|
|
||||||
|
if (!plexSettings.Enable)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ValidateSettings(plexSettings))
|
if (!ValidateSettings(plexSettings))
|
||||||
{
|
{
|
||||||
Log.Debug("Validation of the plex settings failed.");
|
Log.Debug("Validation of the plex settings failed.");
|
||||||
|
|
|
@ -77,7 +77,10 @@ namespace Ombi.Services.Jobs
|
||||||
public void CacheContent()
|
public void CacheContent()
|
||||||
{
|
{
|
||||||
var plexSettings = Plex.GetSettings();
|
var plexSettings = Plex.GetSettings();
|
||||||
|
if (!plexSettings.Enable)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!ValidateSettings(plexSettings))
|
if (!ValidateSettings(plexSettings))
|
||||||
{
|
{
|
||||||
Log.Debug("Validation of the plex settings failed.");
|
Log.Debug("Validation of the plex settings failed.");
|
||||||
|
|
|
@ -12,19 +12,21 @@ using Ombi.Helpers.Permissions;
|
||||||
using Ombi.Services.Interfaces;
|
using Ombi.Services.Interfaces;
|
||||||
using Ombi.Store;
|
using Ombi.Store;
|
||||||
using Ombi.Store.Models;
|
using Ombi.Store.Models;
|
||||||
|
using Ombi.Store.Models.Emby;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
namespace Ombi.Services.Notification
|
namespace Ombi.Services.Notification
|
||||||
{
|
{
|
||||||
public class EmbyNotificationEngine : IEmbyNotificationEngine
|
public class EmbyNotificationEngine : IEmbyNotificationEngine
|
||||||
{
|
{
|
||||||
public EmbyNotificationEngine(IEmbyApi p, IRepository<UsersToNotify> repo, ISettingsService<EmbySettings> embySettings, INotificationService service, IUserHelper userHelper)
|
public EmbyNotificationEngine(IEmbyApi p, IRepository<UsersToNotify> repo, ISettingsService<EmbySettings> embySettings, INotificationService service, IUserHelper userHelper, IExternalUserRepository<EmbyUsers> embyUsers)
|
||||||
{
|
{
|
||||||
EmbyApi = p;
|
EmbyApi = p;
|
||||||
UserNotifyRepo = repo;
|
UserNotifyRepo = repo;
|
||||||
Notification = service;
|
Notification = service;
|
||||||
UserHelper = userHelper;
|
UserHelper = userHelper;
|
||||||
EmbySettings = embySettings;
|
EmbySettings = embySettings;
|
||||||
|
EmbyUserRepo = embyUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEmbyApi EmbyApi { get; }
|
private IEmbyApi EmbyApi { get; }
|
||||||
|
@ -33,6 +35,7 @@ namespace Ombi.Services.Notification
|
||||||
private INotificationService Notification { get; }
|
private INotificationService Notification { get; }
|
||||||
private IUserHelper UserHelper { get; }
|
private IUserHelper UserHelper { get; }
|
||||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||||
|
private IExternalUserRepository<EmbyUsers> EmbyUserRepo { get; }
|
||||||
|
|
||||||
public async Task NotifyUsers(IEnumerable<RequestedModel> modelChanged, NotificationType type)
|
public async Task NotifyUsers(IEnumerable<RequestedModel> modelChanged, NotificationType type)
|
||||||
{
|
{
|
||||||
|
@ -68,22 +71,23 @@ namespace Ombi.Services.Notification
|
||||||
|
|
||||||
foreach (var user in selectedUsers)
|
foreach (var user in selectedUsers)
|
||||||
{
|
{
|
||||||
|
var localUser =
|
||||||
|
users.FirstOrDefault(x =>
|
||||||
|
x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase) ||
|
||||||
|
x.UserAlias.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
||||||
Log.Info("Notifying user {0}", user);
|
Log.Info("Notifying user {0}", user);
|
||||||
if (user.Equals(adminUsername, StringComparison.CurrentCultureIgnoreCase))
|
if (user.Equals(adminUsername, StringComparison.CurrentCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
Log.Info("This user is the Plex server owner");
|
Log.Info("This user is the Plex server owner");
|
||||||
await PublishUserNotification(userAccount?.Name, userAccount?.Name, model.Title, model.PosterPath, type, model.Type); // TODO Emby needs email address
|
await PublishUserNotification(userAccount?.Name, localUser?.EmailAddress, model.Title, model.PosterPath, type, model.Type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var localUser =
|
|
||||||
users.FirstOrDefault( x =>
|
|
||||||
x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase) ||
|
|
||||||
x.UserAlias.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
|
||||||
|
|
||||||
// So if the request was from an alias, then we need to use the local user (since that contains the alias).
|
// So if the request was from an alias, then we need to use the local user (since that contains the alias).
|
||||||
// If we do not have a local user, then we should be using the Plex user if that user exists.
|
// If we do not have a local user, then we should be using the Emby user if that user exists.
|
||||||
// This will execute most of the time since Plex and Local users will most always be in the database.
|
// This will execute most of the time since Emby and Local users will most always be in the database.
|
||||||
if (localUser != null)
|
if (localUser != null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(localUser?.EmailAddress))
|
if (string.IsNullOrEmpty(localUser?.EmailAddress))
|
||||||
|
@ -98,16 +102,17 @@ namespace Ombi.Services.Notification
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var embyUser = EmbyUserRepo.GetUserByUsername(user);
|
||||||
var email = embyUsers.FirstOrDefault(x => x.Name.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
var email = embyUsers.FirstOrDefault(x => x.Name.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
||||||
if (string.IsNullOrEmpty(email?.Name)) // TODO this needs to be the email
|
if (string.IsNullOrEmpty(embyUser?.EmailAddress)) // TODO this needs to be the email
|
||||||
{
|
{
|
||||||
Log.Info("There is no email address for this Emby user ({0}), cannot send notification", email?.Name); //TODO
|
Log.Info("There is no email address for this Emby user ({0}), cannot send notification", email?.Name);
|
||||||
// We do not have a plex user that requested this!
|
// We do not have a plex user that requested this!
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Info("Sending notification to: {0} at: {1}, for : {2}", email.Name, email.Name, model.Title);
|
Log.Info("Sending notification to: {0} at: {1}, for : {2}", embyUser?.Username, embyUser?.EmailAddress, model.Title);
|
||||||
await PublishUserNotification(email.Name, email.Name, model.Title, model.PosterPath, type, model.Type); //TODO
|
await PublishUserNotification(email?.Name, embyUser?.EmailAddress, model.Title, model.PosterPath, type, model.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,6 +130,7 @@ namespace Ombi.Services.Notification
|
||||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||||
var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
|
var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
|
||||||
var userAccount = embyUsers.FirstOrDefault(x => x.Policy.IsAdministrator);
|
var userAccount = embyUsers.FirstOrDefault(x => x.Policy.IsAdministrator);
|
||||||
|
var localUsers = UserHelper.GetUsers().ToList();
|
||||||
|
|
||||||
var adminUsername = userAccount.Name ?? string.Empty;
|
var adminUsername = userAccount.Name ?? string.Empty;
|
||||||
|
|
||||||
|
@ -162,24 +168,31 @@ namespace Ombi.Services.Notification
|
||||||
Log.Debug("Users being notified for this request count {0}", users.Count);
|
Log.Debug("Users being notified for this request count {0}", users.Count);
|
||||||
foreach (var user in usersToNotify)
|
foreach (var user in usersToNotify)
|
||||||
{
|
{
|
||||||
|
var embyUser = EmbyUserRepo.GetUserByUsername(user);
|
||||||
Log.Info("Notifying user {0}", user);
|
Log.Info("Notifying user {0}", user);
|
||||||
if (user.Equals(adminUsername, StringComparison.CurrentCultureIgnoreCase))
|
if (user.Equals(adminUsername, StringComparison.CurrentCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
Log.Info("This user is the Emby server owner");
|
Log.Info("This user is the Emby server owner");
|
||||||
await PublishUserNotification(userAccount.Name, userAccount.Name, model.Title, model.PosterPath, type, model.Type); // TODO
|
await PublishUserNotification(userAccount.Name, embyUser.EmailAddress, model.Title, model.PosterPath, type, model.Type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var email = embyUsers.FirstOrDefault(x => x.Name.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
var email = embyUsers.FirstOrDefault(x => x.Name.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
||||||
if (email == null)
|
if (email == null)
|
||||||
{
|
{
|
||||||
Log.Info("There is no email address for this Emby user, cannot send notification");
|
// Local User?
|
||||||
// We do not have a plex user that requested this!
|
var local = localUsers.FirstOrDefault(x => x.UsernameOrAlias.Equals(user));
|
||||||
continue;
|
if (local != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
Log.Info("Sending notification to: {0} at: {1}, for title: {2}", local.UsernameOrAlias, local.EmailAddress, model.Title);
|
||||||
|
await PublishUserNotification(local.UsernameOrAlias, local.EmailAddress, model.Title, model.PosterPath, type, model.Type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Name, email.Name, model.Title); // TODO
|
Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Name, embyUser.EmailAddress, model.Title);
|
||||||
await PublishUserNotification(email.Name, email.Name, model.Title, model.PosterPath, type, model.Type); // TODO
|
await PublishUserNotification(email.Name, embyUser.EmailAddress, model.Title, model.PosterPath, type, model.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
@ -103,10 +103,31 @@ namespace Ombi.Services.Notification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var localUser =
|
UserHelperModel localUser = null;
|
||||||
users.FirstOrDefault( x =>
|
//users.FirstOrDefault( x =>
|
||||||
x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase) ||
|
// x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase) ||
|
||||||
x.UserAlias.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
// x.UserAlias.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
||||||
|
foreach (var userHelperModel in users)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(userHelperModel.Username))
|
||||||
|
{
|
||||||
|
if (userHelperModel.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
localUser = userHelperModel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(userHelperModel.UserAlias))
|
||||||
|
{
|
||||||
|
if (userHelperModel.UserAlias.Equals(user, StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
localUser = userHelperModel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// So if the request was from an alias, then we need to use the local user (since that contains the alias).
|
// So if the request was from an alias, then we need to use the local user (since that contains the alias).
|
||||||
// If we do not have a local user, then we should be using the Plex user if that user exists.
|
// If we do not have a local user, then we should be using the Plex user if that user exists.
|
||||||
|
@ -150,8 +171,10 @@ namespace Ombi.Services.Notification
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var settings = await PlexSettings.GetSettingsAsync();
|
var settings = await PlexSettings.GetSettingsAsync();
|
||||||
var plexUser = PlexApi.GetUsers(settings.PlexAuthToken);
|
|
||||||
|
var plexUser = PlexApi.GetUsers(settings.PlexAuthToken); // TODO emby
|
||||||
var userAccount = PlexApi.GetAccount(settings.PlexAuthToken);
|
var userAccount = PlexApi.GetAccount(settings.PlexAuthToken);
|
||||||
|
var localUsers = UserHelper.GetUsers().ToList();
|
||||||
|
|
||||||
var adminUsername = userAccount.Username ?? string.Empty;
|
var adminUsername = userAccount.Username ?? string.Empty;
|
||||||
|
|
||||||
|
@ -198,11 +221,17 @@ namespace Ombi.Services.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var email = plexUser.User.FirstOrDefault(x => x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
var email = plexUser.User.FirstOrDefault(x => x.Username.Equals(user, StringComparison.CurrentCultureIgnoreCase));
|
||||||
if (email == null)
|
if (email == null) // This is not a Plex User
|
||||||
{
|
{
|
||||||
Log.Info("There is no email address for this Plex user, cannot send notification");
|
// Local User?
|
||||||
// We do not have a plex user that requested this!
|
var local = localUsers.FirstOrDefault(x => x.UsernameOrAlias.Equals(user));
|
||||||
continue;
|
if (local != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
Log.Info("Sending notification to: {0} at: {1}, for title: {2}", local.UsernameOrAlias, local.EmailAddress, model.Title);
|
||||||
|
await PublishUserNotification(local.UsernameOrAlias, local.EmailAddress, model.Title, model.PosterPath, type, model.Type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Username, email.Email, model.Title);
|
Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Username, email.Email, model.Title);
|
||||||
|
|
19
Ombi.UI/Content/base.css
vendored
19
Ombi.UI/Content/base.css
vendored
|
@ -525,3 +525,22 @@ label {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
margin: 0 auto !important; }
|
margin: 0 auto !important; }
|
||||||
|
|
||||||
|
.pace {
|
||||||
|
-webkit-pointer-events: none;
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none; }
|
||||||
|
|
||||||
|
.pace-inactive {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
.pace .pace-progress {
|
||||||
|
background: #df691a;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 2000;
|
||||||
|
top: 0;
|
||||||
|
right: 100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 5px; }
|
||||||
|
|
||||||
|
|
2
Ombi.UI/Content/base.min.css
vendored
2
Ombi.UI/Content/base.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -650,4 +650,27 @@ $border-radius: 10px;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
display: block $i;
|
display: block $i;
|
||||||
margin: 0 auto $i;
|
margin: 0 auto $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pace {
|
||||||
|
-webkit-pointer-events: none;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pace-inactive {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pace .pace-progress {
|
||||||
|
background: $primary-colour;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 2000;
|
||||||
|
top: 0;
|
||||||
|
right: 100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 5px;
|
||||||
}
|
}
|
|
@ -66,8 +66,10 @@ namespace Ombi.UI.Modules
|
||||||
ICacheProvider cache,
|
ICacheProvider cache,
|
||||||
IAnalytics an,
|
IAnalytics an,
|
||||||
IPlexNotificationEngine engine,
|
IPlexNotificationEngine engine,
|
||||||
|
IEmbyNotificationEngine embyEngine,
|
||||||
ISecurityExtensions security,
|
ISecurityExtensions security,
|
||||||
ISettingsService<CustomizationSettings> customSettings) : base("requests", prSettings, security)
|
ISettingsService<CustomizationSettings> customSettings,
|
||||||
|
ISettingsService<EmbySettings> embyS) : base("requests", prSettings, security)
|
||||||
{
|
{
|
||||||
Service = service;
|
Service = service;
|
||||||
PrSettings = prSettings;
|
PrSettings = prSettings;
|
||||||
|
@ -81,8 +83,10 @@ namespace Ombi.UI.Modules
|
||||||
CpApi = cpApi;
|
CpApi = cpApi;
|
||||||
Cache = cache;
|
Cache = cache;
|
||||||
Analytics = an;
|
Analytics = an;
|
||||||
NotificationEngine = engine;
|
PlexNotificationEngine = engine;
|
||||||
|
EmbyNotificationEngine = embyEngine;
|
||||||
CustomizationSettings = customSettings;
|
CustomizationSettings = customSettings;
|
||||||
|
EmbySettings = embyS;
|
||||||
|
|
||||||
Get["/", true] = async (x, ct) => await LoadRequests();
|
Get["/", true] = async (x, ct) => await LoadRequests();
|
||||||
Get["/movies", true] = async (x, ct) => await GetMovies();
|
Get["/movies", true] = async (x, ct) => await GetMovies();
|
||||||
|
@ -111,11 +115,13 @@ namespace Ombi.UI.Modules
|
||||||
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
||||||
private ISettingsService<CouchPotatoSettings> CpSettings { get; }
|
private ISettingsService<CouchPotatoSettings> CpSettings { get; }
|
||||||
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
|
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
|
||||||
|
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||||
private ISonarrApi SonarrApi { get; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
private ISickRageApi SickRageApi { get; }
|
private ISickRageApi SickRageApi { get; }
|
||||||
private ICouchPotatoApi CpApi { get; }
|
private ICouchPotatoApi CpApi { get; }
|
||||||
private ICacheProvider Cache { get; }
|
private ICacheProvider Cache { get; }
|
||||||
private INotificationEngine NotificationEngine { get; }
|
private INotificationEngine PlexNotificationEngine { get; }
|
||||||
|
private INotificationEngine EmbyNotificationEngine { get; }
|
||||||
|
|
||||||
private async Task<Negotiator> LoadRequests()
|
private async Task<Negotiator> LoadRequests()
|
||||||
{
|
{
|
||||||
|
@ -438,7 +444,21 @@ namespace Ombi.UI.Modules
|
||||||
originalRequest.Available = available;
|
originalRequest.Available = available;
|
||||||
|
|
||||||
var result = await Service.UpdateRequestAsync(originalRequest);
|
var result = await Service.UpdateRequestAsync(originalRequest);
|
||||||
await NotificationEngine.NotifyUsers(originalRequest, 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
|
return Response.AsJson(result
|
||||||
? new { Result = true, Available = available, Message = string.Empty }
|
? 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" });
|
: new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" });
|
||||||
|
|
|
@ -153,6 +153,7 @@ namespace Ombi.UI.Modules
|
||||||
var firstServer = servers.Server.FirstOrDefault(x => x.AccessToken == form.PlexAuthToken);
|
var firstServer = servers.Server.FirstOrDefault(x => x.AccessToken == form.PlexAuthToken);
|
||||||
|
|
||||||
Session[SessionKeys.UserWizardMachineId] = firstServer?.MachineIdentifier;
|
Session[SessionKeys.UserWizardMachineId] = firstServer?.MachineIdentifier;
|
||||||
|
form.MachineIdentifier = firstServer?.MachineIdentifier;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<input type="checkbox" id="SendRecentlyAddedEmail" name="SendRecentlyAddedEmail"><label for="SendRecentlyAddedEmail">Enable newslette</label>
|
<input type="checkbox" id="SendRecentlyAddedEmail" name="SendRecentlyAddedEmail"><label for="SendRecentlyAddedEmail">Enable newsletter</label>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<label for="CustomUsers" class="control-label">Email Addresses to Send to (For users that are not in your User Management section)</label>
|
<label for="CustomUsers" class="control-label">Email Addresses to Send to (For users that are not in your User Management section)</label>
|
||||||
<small>You can add multiple email address by using the ; delimiter</small>
|
<small>You can add multiple email addresses by using the ; delimiter</small>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" class="form-control form-control-custom " placeholder="first@address.com;second@address.com" id="CustomUsers" name="CustomUsers" value="@Model.CustomUsers">
|
<input type="text" class="form-control form-control-custom " placeholder="first@address.com;second@address.com" id="CustomUsers" name="CustomUsers" value="@Model.CustomUsers">
|
||||||
</div>
|
</div>
|
||||||
|
@ -115,4 +115,4 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -64,10 +64,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="RootPath" class="control-label">Root save directory for TV shows</label>
|
<label for="RootPath" class="control-label">Root save directory for Movies</label>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" class="form-control form-control-custom " placeholder="C:\Media\Tv" id="RootPath" name="RootPath" value="@Model.RootPath">
|
<input type="text" class="form-control form-control-custom " placeholder="C:\Media\Movies" id="RootPath" name="RootPath" value="@Model.RootPath">
|
||||||
<label>Enter the root folder where movies are saved. For example <strong>C:\Media\TV</strong>.</label>
|
<label>Enter the root folder where movies are saved. For example <strong>C:\Media\Movies</strong>.</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -241,4 +241,4 @@
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
25
README.md
25
README.md
|
@ -1,5 +1,4 @@
|
||||||
# Ombi
|

|
||||||
|
|
||||||
____
|
____
|
||||||
[](https://gitter.im/tidusjar/Ombi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
[](https://gitter.im/tidusjar/Ombi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
[](https://ci.appveyor.com/project/tidusjar/requestplex)
|
[](https://ci.appveyor.com/project/tidusjar/requestplex)
|
||||||
|
@ -9,22 +8,27 @@ ____
|
||||||
[](https://github.com/tidusjar/Ombi)
|
[](https://github.com/tidusjar/Ombi)
|
||||||
[](http://waffle.io/tidusjar/Ombi)
|
[](http://waffle.io/tidusjar/Ombi)
|
||||||
|
|
||||||
|
| Service | Master | Early Access | Dev |
|
||||||
|
|----------|:---------------------------:|:----------------------------:|:----------------------------:|
|
||||||
|
| AppVeyor | [](https://ci.appveyor.com/project/tidusjar/requestplex/branch/master) | [](https://ci.appveyor.com/project/tidusjar/requestplex/branch/eap) | [](https://ci.appveyor.com/project/tidusjar/requestplex/branch/dev)
|
||||||
|
| Travis | [](https://travis-ci.org/tidusjar/Ombi) | [](https://travis-ci.org/tidusjar/Ombi) | [](https://travis-ci.org/tidusjar/Ombi)
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
Here some of the features Ombi has:
|
Here some of the features Ombi has:
|
||||||
* All your users to Request Movies, TV Shows (Whole series, whole seaons or even single episodes!) and Albums
|
* All your users to Request Movies, TV Shows (Whole series, whole seaons or even single episodes!) and Albums
|
||||||
* Easily manage your requests
|
* Easily manage your requests
|
||||||
|
|
||||||
* User mangement system (supports plex.tv accounts and local accounts) [NEW]
|
* User management system (supports plex.tv accounts and local accounts) [NEW]
|
||||||
* Sending newsletters [NEW]
|
* Sending newsletters [NEW]
|
||||||
* Fault Queue for requests (Buffer requests if Sonar/Couchpotato/SickRage is offline) [NEW]
|
* Fault Queue for requests (Buffer requests if Sonar/Couchpotato/SickRage is offline) [NEW]
|
||||||
|
|
||||||
* Allow your users to report issues and manage them seperatly
|
* Allow your users to report issues and manage them separately
|
||||||
* A landing page that will give you the availability of your Plex server and also add custom notification text to inform your users of downtime.
|
* A landing page that will give you the availability of your Plex server and also add custom notification text to inform your users of downtime.
|
||||||
* Allow your users to get notifications!
|
* Allow your users to get notifications!
|
||||||
* Secure authentication so you don't have to worry about those script kiddies
|
* Secure authentication so you don't have to worry about those script kiddies
|
||||||
* We check to see if the request is already in Plex, if it's already in Plex then why you requesting it?!
|
* We check to see if the request is already in Plex, if it's already in Plex then why you requesting it?!
|
||||||
* We have allowed the ability for a user to add a custom note on a request
|
* We have allowed the ability for a user to add a custom note on a request
|
||||||
* It automatically update the status of requests when they are available on Plex
|
* It automatically updates the status of requests when they are available on Plex
|
||||||
* Slick, responsive and mobile friendly UI
|
* Slick, responsive and mobile friendly UI
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,7 +66,7 @@ Search the existing requests to see if your suggestion has already been submitte
|
||||||
[Ubuntu Guide!](http://www.htpcguides.com/install-plex-requests-net-ubuntu-14-x/)
|
[Ubuntu Guide!](http://www.htpcguides.com/install-plex-requests-net-ubuntu-14-x/)
|
||||||
|
|
||||||
# FAQ
|
# FAQ
|
||||||
Do you have an issue or a question? if so check out our [FAQ!](https://github.com/tidusjar/Ombi/wiki/FAQ)
|
Do you have an issue or a question? if so check out our [FAQ](https://github.com/tidusjar/Ombi/wiki/FAQ)!
|
||||||
|
|
||||||
# Docker
|
# Docker
|
||||||
|
|
||||||
|
@ -72,13 +76,16 @@ Looking for a Docker Image? Well [rogueosb](https://github.com/rogueosb/) has cr
|
||||||
|
|
||||||
We are looking for any contributions to the project! Just pick up a task, if you have any questions ask and i'll get straight on it!
|
We are looking for any contributions to the project! Just pick up a task, if you have any questions ask and i'll get straight on it!
|
||||||
|
|
||||||
Please feed free to submit a pull request!
|
Please feel free to submit a pull request!
|
||||||
|
|
||||||
# Donation
|
# Donation
|
||||||
If you feel like donating you can [here!](https://paypal.me/PlexRequestsNet)
|
If you feel like donating you can donate [here](https://paypal.me/PlexRequestsNet)!
|
||||||
|
|
||||||
### A massive thanks to everyone for all their help!
|
### A massive thanks to everyone for all their helps!
|
||||||
|
|
||||||
## Stats
|
## Stats
|
||||||
[](https://waffle.io/tidusjar/PlexRequests.Net/metrics/throughput)
|
[](https://waffle.io/tidusjar/PlexRequests.Net/metrics/throughput)
|
||||||
|
|
||||||
|
### Sponsors ###
|
||||||
|
- [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
|
||||||
|
- [ReSharper](http://www.jetbrains.com/resharper/)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
version: 2.0.{build}
|
version: 2.1.{build}
|
||||||
configuration: Release
|
configuration: Release
|
||||||
assembly_info:
|
assembly_info:
|
||||||
patch: true
|
patch: true
|
||||||
file: '**\AssemblyInfo.*'
|
file: '**\AssemblyInfo.*'
|
||||||
assembly_version: '2.0.0'
|
assembly_version: '2.1.0'
|
||||||
assembly_file_version: '{version}'
|
assembly_file_version: '{version}'
|
||||||
assembly_informational_version: '2.0.0'
|
assembly_informational_version: '2.1.0'
|
||||||
before_build:
|
before_build:
|
||||||
- cmd: appveyor-retry nuget restore
|
- cmd: appveyor-retry nuget restore
|
||||||
build:
|
build:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue