mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-19 21:03:17 -07:00
commit
f4e75f20ac
64 changed files with 1812 additions and 8322 deletions
|
@ -26,6 +26,8 @@
|
|||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PlexRequests.Store;
|
||||
|
||||
namespace PlexRequests.Core
|
||||
|
@ -33,13 +35,21 @@ namespace PlexRequests.Core
|
|||
public interface IRequestService
|
||||
{
|
||||
long AddRequest(RequestedModel model);
|
||||
Task<int> AddRequestAsync(RequestedModel model);
|
||||
RequestedModel CheckRequest(int providerId);
|
||||
Task<RequestedModel> CheckRequestAsync(int providerId);
|
||||
RequestedModel CheckRequest(string musicId);
|
||||
Task<RequestedModel> CheckRequestAsync(string musicId);
|
||||
|
||||
void DeleteRequest(RequestedModel request);
|
||||
Task DeleteRequestAsync(RequestedModel request);
|
||||
bool UpdateRequest(RequestedModel model);
|
||||
Task<bool> UpdateRequestAsync(RequestedModel model);
|
||||
RequestedModel Get(int id);
|
||||
Task<RequestedModel> GetAsync(int id);
|
||||
IEnumerable<RequestedModel> GetAll();
|
||||
Task<IEnumerable<RequestedModel>> GetAllAsync();
|
||||
bool BatchUpdate(List<RequestedModel> model);
|
||||
bool BatchDelete(List<RequestedModel> model);
|
||||
}
|
||||
}
|
|
@ -24,12 +24,18 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PlexRequests.Core
|
||||
{
|
||||
public interface ISettingsService<T>
|
||||
{
|
||||
T GetSettings();
|
||||
Task<T> GetSettingsAsync();
|
||||
bool SaveSettings(T model);
|
||||
Task<bool> SaveSettingsAsync(T model);
|
||||
bool Delete(T model);
|
||||
Task<bool> DeleteAsync(T model);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
@ -57,6 +58,19 @@ namespace PlexRequests.Core
|
|||
return result ? id : -1;
|
||||
}
|
||||
|
||||
public async Task<int> AddRequestAsync(RequestedModel model)
|
||||
{
|
||||
var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId };
|
||||
var id = await Repo.InsertAsync(entity);
|
||||
|
||||
model.Id = id;
|
||||
|
||||
entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId, Id = id, MusicId = model.MusicBrainzId };
|
||||
var result = await Repo.UpdateAsync(entity);
|
||||
|
||||
return result ? id : -1;
|
||||
}
|
||||
|
||||
public RequestedModel CheckRequest(int providerId)
|
||||
{
|
||||
var blobs = Repo.GetAll();
|
||||
|
@ -64,6 +78,13 @@ namespace PlexRequests.Core
|
|||
return blob != null ? ByteConverterHelper.ReturnObject<RequestedModel>(blob.Content) : null;
|
||||
}
|
||||
|
||||
public async Task<RequestedModel> CheckRequestAsync(int providerId)
|
||||
{
|
||||
var blobs = await Repo.GetAllAsync();
|
||||
var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId);
|
||||
return blob != null ? ByteConverterHelper.ReturnObject<RequestedModel>(blob.Content) : null;
|
||||
}
|
||||
|
||||
public RequestedModel CheckRequest(string musicId)
|
||||
{
|
||||
var blobs = Repo.GetAll();
|
||||
|
@ -71,18 +92,37 @@ namespace PlexRequests.Core
|
|||
return blob != null ? ByteConverterHelper.ReturnObject<RequestedModel>(blob.Content) : null;
|
||||
}
|
||||
|
||||
public async Task<RequestedModel> CheckRequestAsync(string musicId)
|
||||
{
|
||||
var blobs = await Repo.GetAllAsync();
|
||||
var blob = blobs.FirstOrDefault(x => x.MusicId == musicId);
|
||||
return blob != null ? ByteConverterHelper.ReturnObject<RequestedModel>(blob.Content) : null;
|
||||
}
|
||||
|
||||
public void DeleteRequest(RequestedModel request)
|
||||
{
|
||||
var blob = Repo.Get(request.Id);
|
||||
Repo.Delete(blob);
|
||||
}
|
||||
|
||||
public async Task DeleteRequestAsync(RequestedModel request)
|
||||
{
|
||||
var blob = await Repo.GetAsync(request.Id);
|
||||
await Repo.DeleteAsync(blob);
|
||||
}
|
||||
|
||||
public bool UpdateRequest(RequestedModel model)
|
||||
{
|
||||
var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId, Id = model.Id };
|
||||
return Repo.Update(entity);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateRequestAsync(RequestedModel model)
|
||||
{
|
||||
var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId, Id = model.Id };
|
||||
return await Repo.UpdateAsync(entity);
|
||||
}
|
||||
|
||||
public RequestedModel Get(int id)
|
||||
{
|
||||
var blob = Repo.Get(id);
|
||||
|
@ -94,6 +134,17 @@ namespace PlexRequests.Core
|
|||
return model;
|
||||
}
|
||||
|
||||
public async Task<RequestedModel> GetAsync(int id)
|
||||
{
|
||||
var blob = await Repo.GetAsync(id);
|
||||
if (blob == null)
|
||||
{
|
||||
return new RequestedModel();
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<RequestedModel>(blob.Content);
|
||||
return model;
|
||||
}
|
||||
|
||||
public IEnumerable<RequestedModel> GetAll()
|
||||
{
|
||||
var blobs = Repo.GetAll();
|
||||
|
@ -102,10 +153,24 @@ namespace PlexRequests.Core
|
|||
.ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<RequestedModel>> GetAllAsync()
|
||||
{
|
||||
var blobs = await Repo.GetAllAsync();
|
||||
return blobs.Select(b => Encoding.UTF8.GetString(b.Content))
|
||||
.Select(JsonConvert.DeserializeObject<RequestedModel>)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public bool BatchUpdate(List<RequestedModel> model)
|
||||
{
|
||||
var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ByteConverterHelper.ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList();
|
||||
return Repo.UpdateAll(entities);
|
||||
}
|
||||
|
||||
public bool BatchDelete(List<RequestedModel> model)
|
||||
{
|
||||
var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ByteConverterHelper.ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList();
|
||||
return Repo.DeleteAll(entities);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,8 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PlexRequests.Core.SettingModels;
|
||||
|
@ -62,6 +64,21 @@ namespace PlexRequests.Core
|
|||
return model;
|
||||
}
|
||||
|
||||
public async Task<T> GetSettingsAsync()
|
||||
{
|
||||
var result = await Repo.GetAsync(EntityName);
|
||||
if (result == null)
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
result.Content = DecryptSettings(result);
|
||||
var obj = string.IsNullOrEmpty(result.Content) ? null : JsonConvert.DeserializeObject<T>(result.Content, SerializerSettings.Settings);
|
||||
|
||||
var model = obj;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
public bool SaveSettings(T model)
|
||||
{
|
||||
var entity = Repo.Get(EntityName);
|
||||
|
@ -88,6 +105,31 @@ namespace PlexRequests.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
public async Task<bool> SaveSettingsAsync(T model)
|
||||
{
|
||||
var entity = await Repo.GetAsync(EntityName);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
var newEntity = model;
|
||||
|
||||
var settings = new GlobalSettings { SettingsName = EntityName, Content = JsonConvert.SerializeObject(newEntity, SerializerSettings.Settings) };
|
||||
settings.Content = EncryptSettings(settings);
|
||||
var insertResult = await Repo.InsertAsync(settings);
|
||||
|
||||
return insertResult != int.MinValue;
|
||||
}
|
||||
|
||||
var modified = model;
|
||||
modified.Id = entity.Id;
|
||||
|
||||
var globalSettings = new GlobalSettings { SettingsName = EntityName, Content = JsonConvert.SerializeObject(modified, SerializerSettings.Settings), Id = entity.Id };
|
||||
globalSettings.Content = EncryptSettings(globalSettings);
|
||||
var result = await Repo.UpdateAsync(globalSettings);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool Delete(T model)
|
||||
{
|
||||
var entity = Repo.Get(EntityName);
|
||||
|
@ -100,6 +142,17 @@ namespace PlexRequests.Core
|
|||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAsync(T model)
|
||||
{
|
||||
var entity = Repo.Get(EntityName);
|
||||
if (entity != null)
|
||||
{
|
||||
return await Repo.DeleteAsync(entity);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string EncryptSettings(GlobalSettings settings)
|
||||
{
|
||||
return StringCipher.Encrypt(settings.Content, settings.SettingsName);
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace PlexRequests.Core
|
|||
{
|
||||
CreateDefaultSettingsPage(urlBase);
|
||||
}
|
||||
|
||||
|
||||
var version = CheckSchema();
|
||||
if (version > 0)
|
||||
{
|
||||
|
@ -61,6 +61,10 @@ namespace PlexRequests.Core
|
|||
{
|
||||
MigrateToVersion1700();
|
||||
}
|
||||
if (version > 1800 && version <= 1899)
|
||||
{
|
||||
MigrateToVersion1800();
|
||||
}
|
||||
}
|
||||
|
||||
return Db.DbConnection().ConnectionString;
|
||||
|
@ -73,7 +77,7 @@ namespace PlexRequests.Core
|
|||
{
|
||||
var productVersion = AssemblyHelper.GetProductVersion();
|
||||
var trimStatus = new Regex("[^0-9]", RegexOptions.Compiled).Replace(productVersion, string.Empty).PadRight(4, '0');
|
||||
var version = int.Parse(trimStatus);
|
||||
var version = int.Parse(trimStatus);
|
||||
|
||||
var connection = Db.DbConnection();
|
||||
var schema = connection.GetSchemaVersion();
|
||||
|
@ -173,5 +177,50 @@ namespace PlexRequests.Core
|
|||
TableCreation.DropTable(Db.DbConnection(), "User");
|
||||
TableCreation.DropTable(Db.DbConnection(), "Log");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrates to version 1.8.
|
||||
/// <para>This includes updating the admin account to have all roles.</para>
|
||||
/// <para>Set the log level to info</para>
|
||||
/// </summary>
|
||||
private void MigrateToVersion1800()
|
||||
{
|
||||
try
|
||||
{
|
||||
var userMapper = new UserMapper(new UserRepository<UsersModel>(Db, new MemoryCacheProvider()));
|
||||
var users = userMapper.GetUsers();
|
||||
|
||||
foreach (var u in users)
|
||||
{
|
||||
var claims = new[] { UserClaims.User, UserClaims.Admin, UserClaims.PowerUser };
|
||||
u.Claims = ByteConverterHelper.ReturnBytes(claims);
|
||||
|
||||
userMapper.EditUser(u);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
throw;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var settingsService = new SettingsServiceV2<LogSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
|
||||
var logSettings = settingsService.GetSettings();
|
||||
logSettings.Level = LogLevel.Info.Ordinal;
|
||||
settingsService.SaveSettings(logSettings);
|
||||
|
||||
LoggingHelper.ReconfigureLogLevel(LogLevel.FromOrdinal(logSettings.Level));
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
throw;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,16 @@ namespace PlexRequests.Core
|
|||
return null;
|
||||
}
|
||||
|
||||
public UsersModel EditUser(UsersModel user)
|
||||
{
|
||||
var existingUser = Repo.Get(user.UserGuid);
|
||||
|
||||
user.Id = existingUser.Id;
|
||||
user.UserGuid = existingUser.UserGuid;
|
||||
Repo.Update(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
public bool DoUsersExist()
|
||||
{
|
||||
var users = Repo.GetAll();
|
||||
|
@ -88,7 +98,7 @@ namespace PlexRequests.Core
|
|||
return users.Any();
|
||||
}
|
||||
|
||||
public Guid? CreateUser(string username, string password, string[] claims = default(string[]))
|
||||
private Guid? CreateUser(string username, string password, string[] claims = default(string[]))
|
||||
{
|
||||
var salt = PasswordHasher.GenerateSalt();
|
||||
|
||||
|
@ -108,6 +118,21 @@ namespace PlexRequests.Core
|
|||
return new Guid(userRecord.UserGuid);
|
||||
}
|
||||
|
||||
public Guid? CreateAdmin(string username, string password)
|
||||
{
|
||||
return CreateUser(username, password, new[] { UserClaims.User, UserClaims.PowerUser, UserClaims.Admin });
|
||||
}
|
||||
|
||||
public Guid? CreatePowerUser(string username, string password)
|
||||
{
|
||||
return CreateUser(username, password, new[] { UserClaims.User, UserClaims.PowerUser });
|
||||
}
|
||||
|
||||
public Guid? CreateRegularUser(string username, string password)
|
||||
{
|
||||
return CreateUser(username, password, new[] { UserClaims.User });
|
||||
}
|
||||
|
||||
public bool UpdatePassword(string username, string oldPassword, string newPassword)
|
||||
{
|
||||
var users = Repo.GetAll();
|
||||
|
@ -134,15 +159,25 @@ namespace PlexRequests.Core
|
|||
{
|
||||
return Repo.GetAll();
|
||||
}
|
||||
|
||||
public UsersModel GetUser(Guid userId)
|
||||
{
|
||||
var user = Repo.Get(userId.ToString());
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICustomUserMapper
|
||||
{
|
||||
IEnumerable<UsersModel> GetUsers();
|
||||
Guid? CreateUser(string username, string password, string[] claims = default(string[]));
|
||||
UsersModel GetUser(Guid userId);
|
||||
UsersModel EditUser(UsersModel user);
|
||||
bool DoUsersExist();
|
||||
Guid? ValidateUser(string username, string password);
|
||||
bool UpdatePassword(string username, string oldPassword, string newPassword);
|
||||
Guid? CreateAdmin(string username, string password);
|
||||
Guid? CreatePowerUser(string username, string password);
|
||||
Guid? CreateRegularUser(string username, string password);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
using System.Diagnostics;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
|
@ -41,7 +40,7 @@ namespace PlexRequests.Helpers.Tests
|
|||
var hash = PasswordHasher.ComputeHash(password, salt);
|
||||
|
||||
Assert.That(hash, Is.Not.EqualTo(password));
|
||||
|
||||
|
||||
var match = PasswordHasher.VerifyPassword(password, salt, hash);
|
||||
|
||||
Assert.That(match, Is.True);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PlexRequests.Helpers.Tests</RootNamespace>
|
||||
<AssemblyName>PlexRequests.Helpers.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
|
@ -16,6 +16,7 @@
|
|||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace PlexRequests.Helpers.Tests
|
||||
|
@ -35,11 +36,9 @@ namespace PlexRequests.Helpers.Tests
|
|||
public class UriHelperTests
|
||||
{
|
||||
[TestCaseSource(nameof(UriData))]
|
||||
public void CreateUri1(string uri, Uri expected)
|
||||
public Uri CreateUri1(string uri)
|
||||
{
|
||||
var result = uri.ReturnUri();
|
||||
|
||||
Assert.That(result, Is.EqualTo(expected));
|
||||
return uri.ReturnUri();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -52,54 +51,58 @@ namespace PlexRequests.Helpers.Tests
|
|||
}
|
||||
|
||||
[TestCaseSource(nameof(UriDataWithPort))]
|
||||
public void CreateUri2(string uri, int port, Uri expected)
|
||||
public Uri CreateUri2(string uri, int port)
|
||||
{
|
||||
var result = uri.ReturnUri(port);
|
||||
|
||||
Assert.That(result, Is.EqualTo(expected));
|
||||
return uri.ReturnUri(port);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(UriDataWithSubDir))]
|
||||
public void CreateUriWithSubDir(string uri, int port, bool ssl, string subDir, Uri expected)
|
||||
public Uri CreateUriWithSubDir(string uri, int port, bool ssl, string subDir)
|
||||
{
|
||||
var result = uri.ReturnUriWithSubDir(port, ssl, subDir);
|
||||
|
||||
Assert.That(result, Is.EqualTo(expected));
|
||||
return uri.ReturnUriWithSubDir(port, ssl, subDir);
|
||||
}
|
||||
|
||||
static readonly object[] UriData =
|
||||
private static IEnumerable<TestCaseData> UriData
|
||||
{
|
||||
new object[] { "google.com", new Uri("http://google.com/"), },
|
||||
new object[] { "http://google.com", new Uri("http://google.com/"), },
|
||||
new object[] { "https://google.com", new Uri("https://google.com/"), },
|
||||
new object[] { "192.168.1.1", new Uri("http://192.168.1.1")},
|
||||
new object[] { "0.0.0.0:5533", new Uri("http://0.0.0.0:5533")},
|
||||
new object[] {"www.google.com", new Uri("http://www.google.com/")},
|
||||
new object[] {"http://www.google.com/", new Uri("http://www.google.com/") },
|
||||
new object[] {"https://www.google.com", new Uri("https://www.google.com/") },
|
||||
new object[] {"www.google.com:443", new Uri("http://www.google.com:443/") },
|
||||
new object[] {"https://www.google.com:443", new Uri("https://www.google.com:443/") },
|
||||
new object[] {"http://www.google.com:443/id=2", new Uri("http://www.google.com:443/id=2") },
|
||||
new object[] {"www.google.com:4438/id=22", new Uri("http://www.google.com:4438/id=22") }
|
||||
};
|
||||
get
|
||||
{
|
||||
yield return new TestCaseData("google.com").Returns(new Uri("http://google.com/"));
|
||||
yield return new TestCaseData("http://google.com").Returns(new Uri("http://google.com/"));
|
||||
yield return new TestCaseData("https://google.com").Returns(new Uri("https://google.com/"));
|
||||
yield return new TestCaseData("192.168.1.1").Returns(new Uri("http://192.168.1.1"));
|
||||
yield return new TestCaseData("0.0.0.0:5533").Returns(new Uri("http://0.0.0.0:5533"));
|
||||
yield return new TestCaseData("www.google.com").Returns(new Uri("http://www.google.com/"));
|
||||
yield return new TestCaseData("http://www.google.com/").Returns(new Uri("http://www.google.com/"));
|
||||
yield return new TestCaseData("https://www.google.com").Returns(new Uri("https://www.google.com/"));
|
||||
yield return new TestCaseData("www.google.com:443").Returns(new Uri("http://www.google.com:443/"));
|
||||
yield return new TestCaseData("https://www.google.com:443").Returns(new Uri("https://www.google.com/"));
|
||||
yield return new TestCaseData("http://www.google.com:443/id=2").Returns(new Uri("http://www.google.com:443/id=2"));
|
||||
yield return new TestCaseData("www.google.com:4438/id=22").Returns(new Uri("http://www.google.com:4438/id=22"));
|
||||
}
|
||||
}
|
||||
|
||||
static readonly object[] UriDataWithPort =
|
||||
private static IEnumerable<TestCaseData> UriDataWithPort
|
||||
{
|
||||
new object[] {"www.google.com", 80, new Uri("http://www.google.com:80/"), },
|
||||
new object[] {"www.google.com", 443, new Uri("http://www.google.com:443/") },
|
||||
new object[] {"http://www.google.com", 443, new Uri("http://www.google.com:443/") },
|
||||
new object[] {"https://www.google.com", 443, new Uri("https://www.google.com:443/") },
|
||||
new object[] {"http://www.google.com/id=2", 443, new Uri("http://www.google.com:443/id=2") },
|
||||
new object[] {"http://www.google.com/id=2", 443, new Uri("http://www.google.com:443/id=2") },
|
||||
new object[] {"https://www.google.com/id=2", 443, new Uri("https://www.google.com:443/id=2") },
|
||||
};
|
||||
get
|
||||
{
|
||||
yield return new TestCaseData("www.google.com", 80).Returns(new Uri("http://www.google.com:80/"));
|
||||
yield return new TestCaseData("www.google.com", 443).Returns(new Uri("http://www.google.com:443/"));
|
||||
yield return new TestCaseData("http://www.google.com", 443).Returns(new Uri("http://www.google.com:443/"));
|
||||
yield return new TestCaseData("https://www.google.com", 443).Returns(new Uri("https://www.google.com:443/"));
|
||||
yield return new TestCaseData("http://www.google.com/id=2", 443).Returns(new Uri("http://www.google.com:443/id=2"));
|
||||
yield return new TestCaseData("https://www.google.com/id=2", 443).Returns(new Uri("https://www.google.com:443/id=2"));
|
||||
}
|
||||
}
|
||||
|
||||
static readonly object[] UriDataWithSubDir =
|
||||
{
|
||||
new object[] {"www.google.com", 80, false,"test", new Uri("http://www.google.com:80/test"), },
|
||||
new object[] {"www.google.com", 443, false,"test", new Uri("http://www.google.com:443/test") },
|
||||
new object[] {"http://www.google.com", 443, true,"test", new Uri("https://www.google.com:443/test") },
|
||||
new object[] {"https://www.google.com", 443,true,"test", new Uri("https://www.google.com:443/test") },
|
||||
};
|
||||
private static IEnumerable<TestCaseData> UriDataWithSubDir
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new TestCaseData("www.google.com", 80, false, "test").Returns(new Uri("http://www.google.com:80/test"));
|
||||
yield return new TestCaseData("www.google.com", 443, false, "test").Returns(new Uri("http://www.google.com:443/test"));
|
||||
yield return new TestCaseData("http://www.google.com", 443, true, "test").Returns(new Uri("https://www.google.com:443/test"));
|
||||
yield return new TestCaseData("https://www.google.com", 443, true, "test").Returns(new Uri("https://www.google.com:443/test"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PlexRequests.Helpers
|
||||
{
|
||||
|
@ -40,6 +41,7 @@ namespace PlexRequests.Helpers
|
|||
/// <param name="cacheTime">The amount of time we want to cache the object</param>
|
||||
/// <returns><see cref="T"/></returns>
|
||||
T GetOrSet<T>(string key, Func<T> itemCallback, int cacheTime = 20) where T : class;
|
||||
Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> itemCallback, int cacheTime = 20) where T : class;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified item from the cache.
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.Caching;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PlexRequests.Helpers
|
||||
{
|
||||
|
@ -65,6 +66,23 @@ namespace PlexRequests.Helpers
|
|||
return item.CloneJson();
|
||||
}
|
||||
|
||||
public async Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> itemCallback, int cacheTime = 20) where T : class
|
||||
{
|
||||
var item = Get<T>(key);
|
||||
if (item == null)
|
||||
{
|
||||
item = await itemCallback();
|
||||
if (item != null)
|
||||
{
|
||||
Set(key, item, cacheTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Return a copy, not the stored cache reference
|
||||
// The cached object will not change
|
||||
return item.CloneJson();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified item from the cache.
|
||||
/// </summary>
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace PlexRequests.Services.Jobs
|
|||
public int[] QueuedIds()
|
||||
{
|
||||
var movies = Cache.Get<CouchPotatoMovies>(CacheKeys.CouchPotatoQueued);
|
||||
return movies?.movies.Select(x => x.info.tmdb_id).ToArray() ?? new int[] { };
|
||||
return movies?.movies?.Select(x => x.info.tmdb_id).ToArray() ?? new int[] { };
|
||||
}
|
||||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace PlexRequests.Services
|
||||
namespace PlexRequests.Services.Jobs
|
||||
{
|
||||
public static class JobNames
|
||||
{
|
||||
|
@ -33,5 +33,6 @@ namespace PlexRequests.Services
|
|||
public const string SonarrCacher = "Sonarr Cacher";
|
||||
public const string SrCacher = "SickRage Cacher";
|
||||
public const string PlexChecker = "Plex Availability Cacher";
|
||||
public const string StoreCleanup = "Database Cleanup";
|
||||
}
|
||||
}
|
|
@ -326,33 +326,36 @@ namespace PlexRequests.Services.Jobs
|
|||
try
|
||||
{
|
||||
var plexUser = PlexApi.GetUsers(apiKey);
|
||||
if (plexUser?.User == null || plexUser.User.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var userAccount = PlexApi.GetAccount(apiKey);
|
||||
|
||||
var adminUsername = userAccount.Username ?? string.Empty;
|
||||
|
||||
var users = UserNotifyRepo.GetAll().ToList();
|
||||
Log.Debug("Notifying Users Count {0}", users.Count);
|
||||
foreach (var model in modelChanged)
|
||||
{
|
||||
var selectedUsers = users.Select(x => x.Username).Intersect(model.RequestedUsers);
|
||||
Log.Debug("Selected Users {0}", selectedUsers.DumpJson());
|
||||
foreach (var user in selectedUsers)
|
||||
{
|
||||
Log.Info("Notifying user {0}", user);
|
||||
if (user == adminUsername)
|
||||
{
|
||||
Log.Info("This user is the Plex server owner");
|
||||
PublishUserNotification(userAccount.Username, userAccount.Email, model.Title);
|
||||
return;
|
||||
}
|
||||
|
||||
var email = plexUser.User.FirstOrDefault(x => x.Username == user);
|
||||
if (email == null)
|
||||
{
|
||||
Log.Info("There is no email address for this Plex user, cannot send notification");
|
||||
// We do not have a plex user that requested this!
|
||||
continue;
|
||||
}
|
||||
var notificationModel = new NotificationModel
|
||||
{
|
||||
User = email.Username,
|
||||
UserEmail = email.Email,
|
||||
NotificationType = NotificationType.RequestAvailable,
|
||||
Title = model.Title
|
||||
};
|
||||
|
||||
// Send the notification to the user.
|
||||
Notification.Publish(notificationModel);
|
||||
Log.Info("Sending notification to: {0} at: {1}, for title: {2}", email.Username, email.Email, model.Title);
|
||||
PublishUserNotification(email.Username, email.Email, model.Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,6 +365,20 @@ namespace PlexRequests.Services.Jobs
|
|||
}
|
||||
}
|
||||
|
||||
private void PublishUserNotification(string username, string email, string title)
|
||||
{
|
||||
var notificationModel = new NotificationModel
|
||||
{
|
||||
User = username,
|
||||
UserEmail = email,
|
||||
NotificationType = NotificationType.RequestAvailable,
|
||||
Title = title
|
||||
};
|
||||
|
||||
// Send the notification to the user.
|
||||
Notification.Publish(notificationModel);
|
||||
}
|
||||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
CheckAndUpdateAll();
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace PlexRequests.Services.Jobs
|
|||
public int[] QueuedIds()
|
||||
{
|
||||
var tv = Cache.Get<SickrageShows>(CacheKeys.SickRageQueued);
|
||||
return tv?.data.Values.Select(x => x.tvdbid).ToArray() ?? new int[] { };
|
||||
return tv?.data?.Values.Select(x => x.tvdbid).ToArray() ?? new int[] { };
|
||||
}
|
||||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
|
|
|
@ -26,15 +26,11 @@
|
|||
#endregion
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
|
||||
using NLog;
|
||||
|
||||
using PlexRequests.Services.Interfaces;
|
||||
using PlexRequests.Store;
|
||||
using PlexRequests.Store.Models;
|
||||
using PlexRequests.Store.Repository;
|
||||
|
||||
using Quartz;
|
||||
|
||||
|
@ -57,7 +53,7 @@ namespace PlexRequests.Services.Jobs
|
|||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
TakeBackup();
|
||||
Cleanup ();
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
private void TakeBackup()
|
||||
|
@ -81,11 +77,11 @@ namespace PlexRequests.Services.Jobs
|
|||
|
||||
try
|
||||
{
|
||||
if(DoWeNeedToBackup(backupDir.FullName))
|
||||
{
|
||||
File.Copy(dbPath, Path.Combine(backupDir.FullName, $"PlexRequests.sqlite_{DateTime.Now.ToString("yyyy-MM-dd hh.mm.ss")}.bak"));
|
||||
}
|
||||
}
|
||||
if (DoWeNeedToBackup(backupDir.FullName))
|
||||
{
|
||||
File.Copy(dbPath, Path.Combine(backupDir.FullName, $"PlexRequests.sqlite_{DateTime.Now.ToString("yyyy-MM-dd hh.mm.ss")}.bak"));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warn(e);
|
||||
|
@ -98,53 +94,58 @@ namespace PlexRequests.Services.Jobs
|
|||
|
||||
}
|
||||
|
||||
private void Cleanup()
|
||||
{
|
||||
Log.Trace("Starting DB Cleanup");
|
||||
var dbPath = Sql.CurrentPath;
|
||||
var dir = Path.GetDirectoryName(dbPath);
|
||||
if (dir == null)
|
||||
{
|
||||
Log.Warn("We couldn't find the DB path. We cannot backup.");
|
||||
return;
|
||||
}
|
||||
var backupDir = Directory.CreateDirectory(Path.Combine(dir, "Backup"));
|
||||
private void Cleanup()
|
||||
{
|
||||
Log.Trace("Starting DB Cleanup");
|
||||
var dbPath = Sql.CurrentPath;
|
||||
var dir = Path.GetDirectoryName(dbPath);
|
||||
if (dir == null)
|
||||
{
|
||||
Log.Warn("We couldn't find the DB path. We cannot backup.");
|
||||
return;
|
||||
}
|
||||
var backupDir = Directory.CreateDirectory(Path.Combine(dir, "Backup"));
|
||||
|
||||
var files = backupDir.GetFiles();
|
||||
var files = backupDir.GetFiles();
|
||||
|
||||
foreach (var file in files) {
|
||||
var dt = ParseName(file.Name);
|
||||
if(dt < DateTime.Now.AddDays(-7)){
|
||||
try {
|
||||
foreach (var file in files)
|
||||
{
|
||||
var dt = ParseName(file.Name);
|
||||
if (dt < DateTime.Now.AddDays(-7))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
File.Delete(file.FullName);
|
||||
} catch (Exception ex) {
|
||||
Log.Error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
File.Delete(file.FullName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private bool DoWeNeedToBackup(string backupPath)
|
||||
{
|
||||
var files = Directory.GetFiles(backupPath);
|
||||
//TODO Get the latest file and if it's within an hour of DateTime.Now then don't bother backing up.
|
||||
return true;
|
||||
}
|
||||
private bool DoWeNeedToBackup(string backupPath)
|
||||
{
|
||||
var files = Directory.GetFiles(backupPath);
|
||||
//TODO Get the latest file and if it's within an hour of DateTime.Now then don't bother backing up.
|
||||
return true;
|
||||
}
|
||||
|
||||
private DateTime ParseName(string fileName)
|
||||
{
|
||||
var names = fileName.Split(new []{'_','.',' '}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(names.Count() > 1)
|
||||
{
|
||||
DateTime parsed;
|
||||
//DateTime.TryParseExcat(names[1], "yyyy-MM-dd hh.mm.ss",CultureInfo.CurrentUICulture, DateTimeStyles.None, out parsed);
|
||||
DateTime.TryParse(names[2], out parsed);
|
||||
return parsed;
|
||||
private DateTime ParseName(string fileName)
|
||||
{
|
||||
var names = fileName.Split(new[] { '_', '.', ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (names.Length > 1)
|
||||
{
|
||||
DateTime parsed;
|
||||
//DateTime.TryParseExcat(names[1], "yyyy-MM-dd hh.mm.ss",CultureInfo.CurrentUICulture, DateTimeStyles.None, out parsed);
|
||||
DateTime.TryParse(names[2], out parsed);
|
||||
return parsed;
|
||||
|
||||
}
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
}
|
82
PlexRequests.Services/Jobs/StoreCleanup.cs
Normal file
82
PlexRequests.Services/Jobs/StoreCleanup.cs
Normal file
|
@ -0,0 +1,82 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: StoreCleanup.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using NLog;
|
||||
|
||||
using PlexRequests.Services.Interfaces;
|
||||
using PlexRequests.Store.Models;
|
||||
using PlexRequests.Store.Repository;
|
||||
|
||||
using Quartz;
|
||||
|
||||
namespace PlexRequests.Services.Jobs
|
||||
{
|
||||
public class StoreCleanup : IJob
|
||||
{
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public StoreCleanup(IRepository<LogEntity> repo, IJobRecord rec)
|
||||
{
|
||||
Repo = repo;
|
||||
JobRecord = rec;
|
||||
}
|
||||
|
||||
private IJobRecord JobRecord { get; }
|
||||
|
||||
private IRepository<LogEntity> Repo { get; }
|
||||
|
||||
private void Cleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
var items = Repo.GetAll();
|
||||
var orderedItems = items.Where(x => x.Date < DateTime.Now.AddDays(-7));
|
||||
|
||||
foreach (var o in orderedItems)
|
||||
{
|
||||
Repo.Delete(o);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
JobRecord.Record(JobNames.StoreCleanup);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,7 +62,10 @@ namespace PlexRequests.Services.Notification
|
|||
|
||||
var emailSettings = (EmailNotificationSettings)settings;
|
||||
|
||||
if (!ValidateConfiguration(emailSettings)) return;
|
||||
if (!ValidateConfiguration(emailSettings))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (model.NotificationType)
|
||||
{
|
||||
|
@ -96,15 +99,19 @@ namespace PlexRequests.Services.Notification
|
|||
|
||||
private bool ValidateConfiguration(EmailNotificationSettings settings)
|
||||
{
|
||||
if (!settings.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(settings.EmailHost) || string.IsNullOrEmpty(settings.EmailUsername) || string.IsNullOrEmpty(settings.EmailPassword) || string.IsNullOrEmpty(settings.RecipientEmail) || string.IsNullOrEmpty(settings.EmailPort.ToString()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!settings.EnableUserEmailNotifications)
|
||||
{
|
||||
if (!settings.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace PlexRequests.Services.Notification
|
|||
Observers.TryRemove(notification.NotificationName, out notification);
|
||||
}
|
||||
|
||||
private static async Task NotifyAsync(INotification notification, NotificationModel model)
|
||||
private async Task NotifyAsync(INotification notification, NotificationModel model)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -89,7 +89,7 @@ namespace PlexRequests.Services.Notification
|
|||
|
||||
}
|
||||
|
||||
private static async Task NotifyAsync(INotification notification, NotificationModel model, Settings settings)
|
||||
private async Task NotifyAsync(INotification notification, NotificationModel model, Settings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<Compile Include="Jobs\JobRecord.cs" />
|
||||
<Compile Include="Jobs\JobNames.cs" />
|
||||
<Compile Include="Jobs\StoreBackup.cs" />
|
||||
<Compile Include="Jobs\StoreCleanup.cs" />
|
||||
<Compile Include="Jobs\CouchPotatoCacher.cs" />
|
||||
<Compile Include="Jobs\PlexAvailabilityChecker.cs" />
|
||||
<Compile Include="Jobs\SickRageCacher.cs" />
|
||||
|
|
|
@ -31,11 +31,20 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Dapper, Version=1.50.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapper.1.50.0-beta8\lib\net45\Dapper.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Dapper.Contrib, Version=1.50.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Dapper.Contrib.1.50.0-beta8\lib\net45\Dapper.Contrib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Data.Sqlite">
|
||||
<HintPath>..\Assemblies\Mono.Data.Sqlite.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Linq" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
@ -43,12 +52,6 @@
|
|||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Dapper, Version=1.40.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Dapper.1.42\lib\net45\Dapper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Dapper.Contrib, Version=1.40.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>..\packages\Dapper.Contrib.1.43\lib\net45\Dapper.Contrib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -61,6 +64,7 @@
|
|||
<Compile Include="Entity.cs" />
|
||||
<Compile Include="Models\ScheduledJobs.cs" />
|
||||
<Compile Include="Models\UsersToNotify.cs" />
|
||||
<Compile Include="Repository\BaseGenericRepository.cs" />
|
||||
<Compile Include="Repository\IRequestRepository.cs" />
|
||||
<Compile Include="Repository\ISettingsRepository.cs" />
|
||||
<Compile Include="ISqliteConfiguration.cs" />
|
||||
|
|
179
PlexRequests.Store/Repository/BaseGenericRepository.cs
Normal file
179
PlexRequests.Store/Repository/BaseGenericRepository.cs
Normal file
|
@ -0,0 +1,179 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: BaseGenericRepository.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper.Contrib.Extensions;
|
||||
using NLog;
|
||||
using PlexRequests.Helpers;
|
||||
|
||||
namespace PlexRequests.Store.Repository
|
||||
{
|
||||
public abstract class BaseGenericRepository<T> where T : class
|
||||
{
|
||||
protected BaseGenericRepository(ISqliteConfiguration config, ICacheProvider cache)
|
||||
{
|
||||
Config = config;
|
||||
Cache = cache;
|
||||
}
|
||||
protected ICacheProvider Cache { get; }
|
||||
protected ISqliteConfiguration Config { get; }
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
public abstract T Get(string id);
|
||||
public abstract Task<T> GetAsync(int id);
|
||||
public abstract T Get(int id);
|
||||
public abstract Task<T> GetAsync(string id);
|
||||
|
||||
public long Insert(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var cnn = Config.DbConnection())
|
||||
{
|
||||
cnn.Open();
|
||||
return cnn.Insert(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
db.Delete(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
await db.DeleteAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Update(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
Log.Trace("Updating entity");
|
||||
Log.Trace(entity.DumpJson());
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
return db.Update(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAsync(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
Log.Trace("Updating entity");
|
||||
Log.Trace(entity.DumpJson());
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
return await db.UpdateAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateAll(IEnumerable<T> entity)
|
||||
{
|
||||
ResetCache();
|
||||
Log.Trace("Updating all entities");
|
||||
var result = new HashSet<bool>();
|
||||
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
foreach (var e in entity)
|
||||
{
|
||||
result.Add(db.Update(e));
|
||||
}
|
||||
}
|
||||
return result.All(x => true);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAllAsync(IEnumerable<T> entity)
|
||||
{
|
||||
ResetCache();
|
||||
Log.Trace("Updating all entities");
|
||||
var result = new HashSet<bool>();
|
||||
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
foreach (var e in entity)
|
||||
{
|
||||
result.Add(await db.UpdateAsync(e));
|
||||
}
|
||||
}
|
||||
return result.All(x => true);
|
||||
}
|
||||
|
||||
public async Task<int> InsertAsync(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var cnn = Config.DbConnection())
|
||||
{
|
||||
cnn.Open();
|
||||
return await cnn.InsertAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetCache()
|
||||
{
|
||||
Cache.Remove("Get");
|
||||
Cache.Remove("GetAll");
|
||||
}
|
||||
public IEnumerable<T> GetAll()
|
||||
{
|
||||
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
var result = db.GetAll<T>();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
public async Task<IEnumerable<T>> GetAllAsync()
|
||||
{
|
||||
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
var result = await db.GetAllAsync<T>();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#region Copyright
|
||||
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: GenericRepository.cs
|
||||
|
@ -23,59 +24,38 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Dapper.Contrib.Extensions;
|
||||
|
||||
using NLog;
|
||||
|
||||
using PlexRequests.Helpers;
|
||||
|
||||
namespace PlexRequests.Store.Repository
|
||||
{
|
||||
public class GenericRepository<T> : IRepository<T> where T : Entity
|
||||
public class GenericRepository<T> : BaseGenericRepository<T>, IRepository<T> where T : Entity
|
||||
{
|
||||
private ICacheProvider Cache { get; }
|
||||
public GenericRepository(ISqliteConfiguration config, ICacheProvider cache)
|
||||
|
||||
public GenericRepository(ISqliteConfiguration config, ICacheProvider cache) : base(config, cache)
|
||||
{
|
||||
Config = config;
|
||||
Cache = cache;
|
||||
|
||||
}
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private ISqliteConfiguration Config { get; }
|
||||
public long Insert(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var cnn = Config.DbConnection())
|
||||
{
|
||||
cnn.Open();
|
||||
return cnn.Insert(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetAll()
|
||||
{
|
||||
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
var result = db.GetAll<T>();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public T Get(string id)
|
||||
|
||||
public override T Get(string id)
|
||||
{
|
||||
throw new NotSupportedException("Get(string) is not supported. Use Get(int)");
|
||||
}
|
||||
|
||||
public T Get(int id)
|
||||
public override Task<T> GetAsync(string id)
|
||||
{
|
||||
throw new NotSupportedException("GetAsync(string) is not supported. Use GetAsync(int)");
|
||||
}
|
||||
|
||||
public override T Get(int id)
|
||||
{
|
||||
var key = "Get" + id;
|
||||
var item = Cache.GetOrSet(
|
||||
|
@ -91,49 +71,22 @@ namespace PlexRequests.Store.Repository
|
|||
return item;
|
||||
}
|
||||
|
||||
public void Delete(T entity)
|
||||
public override async Task<T> GetAsync(int id)
|
||||
{
|
||||
ResetCache();
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
db.Delete(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Update(T entity)
|
||||
{
|
||||
ResetCache();
|
||||
Log.Trace("Updating entity");
|
||||
Log.Trace(entity.DumpJson());
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
return db.Update(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateAll(IEnumerable<T> entity)
|
||||
{
|
||||
ResetCache();
|
||||
Log.Trace("Updating all entities");
|
||||
var result = new HashSet<bool>();
|
||||
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
foreach (var e in entity)
|
||||
var key = "Get" + id;
|
||||
var item = await Cache.GetOrSetAsync(
|
||||
key,
|
||||
async () =>
|
||||
{
|
||||
result.Add(db.Update(e));
|
||||
}
|
||||
}
|
||||
return result.All(x => true);
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
return await db.GetAsync<T>(id);
|
||||
}
|
||||
});
|
||||
return item;
|
||||
}
|
||||
|
||||
private void ResetCache()
|
||||
{
|
||||
Cache.Remove("Get");
|
||||
Cache.Remove("GetAll");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PlexRequests.Store.Repository
|
||||
{
|
||||
|
@ -35,12 +36,15 @@ namespace PlexRequests.Store.Repository
|
|||
/// </summary>
|
||||
/// <param name="entity">The entity.</param>
|
||||
long Insert(T entity);
|
||||
Task<int> InsertAsync(T entity);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<T> GetAll();
|
||||
Task<IEnumerable<T>> GetAllAsync();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified identifier.
|
||||
|
@ -48,12 +52,15 @@ namespace PlexRequests.Store.Repository
|
|||
/// <param name="id">The identifier.</param>
|
||||
/// <returns></returns>
|
||||
T Get(string id);
|
||||
Task<T> GetAsync(string id);
|
||||
T Get(int id);
|
||||
Task<T> GetAsync(int id);
|
||||
/// <summary>
|
||||
/// Deletes the specified entity.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity.</param>
|
||||
void Delete(T entity);
|
||||
Task DeleteAsync(T entity);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified entity.
|
||||
|
@ -61,6 +68,7 @@ namespace PlexRequests.Store.Repository
|
|||
/// <param name="entity">The entity.</param>
|
||||
/// <returns></returns>
|
||||
bool Update(T entity);
|
||||
Task<bool> UpdateAsync(T entity);
|
||||
|
||||
/// <summary>
|
||||
/// Updates all.
|
||||
|
@ -68,5 +76,6 @@ namespace PlexRequests.Store.Repository
|
|||
/// <param name="entity">The entity.</param>
|
||||
/// <returns></returns>
|
||||
bool UpdateAll(IEnumerable<T> entity);
|
||||
Task<bool> UpdateAllAsync(IEnumerable<T> entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PlexRequests.Store.Models;
|
||||
|
||||
|
@ -38,13 +39,18 @@ namespace PlexRequests.Store.Repository
|
|||
/// <param name="entity">The entity.</param>
|
||||
long Insert(RequestBlobs entity);
|
||||
|
||||
Task<int> InsertAsync(RequestBlobs entity);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<RequestBlobs> GetAll();
|
||||
|
||||
Task<IEnumerable<RequestBlobs>> GetAllAsync();
|
||||
|
||||
RequestBlobs Get(int id);
|
||||
Task<RequestBlobs> GetAsync(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified entity.
|
||||
|
@ -52,6 +58,10 @@ namespace PlexRequests.Store.Repository
|
|||
/// <param name="entity">The entity.</param>
|
||||
/// <returns></returns>
|
||||
bool Delete(RequestBlobs entity);
|
||||
Task<bool> DeleteAsync(RequestBlobs entity);
|
||||
|
||||
bool DeleteAll(IEnumerable<RequestBlobs> entity);
|
||||
Task<bool> DeleteAllAsync(IEnumerable<RequestBlobs> entity);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified entity.
|
||||
|
@ -59,7 +69,9 @@ namespace PlexRequests.Store.Repository
|
|||
/// <param name="entity">The entity.</param>
|
||||
/// <returns></returns>
|
||||
bool Update(RequestBlobs entity);
|
||||
Task<bool> UpdateAsync(RequestBlobs entity);
|
||||
|
||||
bool UpdateAll(IEnumerable<RequestBlobs> entity);
|
||||
Task<bool> UpdateAllAsync(IEnumerable<RequestBlobs> entity);
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@
|
|||
// ************************************************************************/
|
||||
#endregion
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using PlexRequests.Store.Models;
|
||||
|
||||
namespace PlexRequests.Store.Repository
|
||||
|
@ -37,12 +37,14 @@ namespace PlexRequests.Store.Repository
|
|||
/// </summary>
|
||||
/// <param name="entity">The entity.</param>
|
||||
long Insert(GlobalSettings entity);
|
||||
Task<int> InsertAsync(GlobalSettings entity);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<GlobalSettings> GetAll();
|
||||
Task<IEnumerable<GlobalSettings>> GetAllAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified identifier.
|
||||
|
@ -50,12 +52,14 @@ namespace PlexRequests.Store.Repository
|
|||
/// <param name="settingsName">Name of the settings.</param>
|
||||
/// <returns></returns>
|
||||
GlobalSettings Get(string settingsName);
|
||||
Task<GlobalSettings> GetAsync(string settingsName);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified entity.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity.</param>
|
||||
/// <returns></returns>
|
||||
Task<bool> DeleteAsync(GlobalSettings entity);
|
||||
bool Delete(GlobalSettings entity);
|
||||
|
||||
/// <summary>
|
||||
|
@ -63,6 +67,7 @@ namespace PlexRequests.Store.Repository
|
|||
/// </summary>
|
||||
/// <param name="entity">The entity.</param>
|
||||
/// <returns></returns>
|
||||
Task<bool> UpdateAsync(GlobalSettings entity);
|
||||
bool Update(GlobalSettings entity);
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#endregion
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dapper.Contrib.Extensions;
|
||||
|
||||
|
@ -56,6 +57,16 @@ namespace PlexRequests.Store.Repository
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<int> InsertAsync(RequestBlobs entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
var id = await con.InsertAsync(entity);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<RequestBlobs> GetAll()
|
||||
{
|
||||
var key = "GetAll";
|
||||
|
@ -70,6 +81,20 @@ namespace PlexRequests.Store.Repository
|
|||
return item;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<RequestBlobs>> GetAllAsync()
|
||||
{
|
||||
var key = "GetAll";
|
||||
var item = await Cache.GetOrSetAsync(key, async() =>
|
||||
{
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
var page = await con.GetAllAsync<RequestBlobs>();
|
||||
return page;
|
||||
}
|
||||
}, 5);
|
||||
return item;
|
||||
}
|
||||
|
||||
public RequestBlobs Get(int id)
|
||||
{
|
||||
var key = "Get" + id;
|
||||
|
@ -84,6 +109,20 @@ namespace PlexRequests.Store.Repository
|
|||
return item;
|
||||
}
|
||||
|
||||
public async Task<RequestBlobs> GetAsync(int id)
|
||||
{
|
||||
var key = "Get" + id;
|
||||
var item = await Cache.GetOrSetAsync(key, async () =>
|
||||
{
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
var page = await con.GetAsync<RequestBlobs>(id);
|
||||
return page;
|
||||
}
|
||||
}, 5);
|
||||
return item;
|
||||
}
|
||||
|
||||
public bool Delete(RequestBlobs entity)
|
||||
{
|
||||
ResetCache();
|
||||
|
@ -93,6 +132,30 @@ namespace PlexRequests.Store.Repository
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAsync(RequestBlobs entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
return await con.DeleteAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAllAsync(IEnumerable<RequestBlobs> entity)
|
||||
{
|
||||
ResetCache();
|
||||
var result = new HashSet<bool>();
|
||||
using (var db = Db.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
foreach (var e in entity)
|
||||
{
|
||||
result.Add(await db.DeleteAsync(e));
|
||||
}
|
||||
}
|
||||
return result.All(x => true);
|
||||
}
|
||||
|
||||
public bool Update(RequestBlobs entity)
|
||||
{
|
||||
ResetCache();
|
||||
|
@ -102,6 +165,15 @@ namespace PlexRequests.Store.Repository
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAsync(RequestBlobs entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
return await con.UpdateAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetCache()
|
||||
{
|
||||
Cache.Remove("Get");
|
||||
|
@ -122,5 +194,35 @@ namespace PlexRequests.Store.Repository
|
|||
}
|
||||
return result.All(x => true);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAllAsync(IEnumerable<RequestBlobs> entity)
|
||||
{
|
||||
ResetCache();
|
||||
var result = new HashSet<bool>();
|
||||
using (var db = Db.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
foreach (var e in entity)
|
||||
{
|
||||
result.Add(await db.UpdateAsync(e));
|
||||
}
|
||||
}
|
||||
return result.All(x => true);
|
||||
}
|
||||
|
||||
public bool DeleteAll(IEnumerable<RequestBlobs> entity)
|
||||
{
|
||||
ResetCache();
|
||||
var result = new HashSet<bool>();
|
||||
using (var db = Db.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
foreach (var e in entity)
|
||||
{
|
||||
result.Add(db.Delete(e));
|
||||
}
|
||||
}
|
||||
return result.All(x => true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#endregion
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Dapper.Contrib.Extensions;
|
||||
|
||||
using PlexRequests.Helpers;
|
||||
|
@ -57,6 +57,15 @@ namespace PlexRequests.Store.Repository
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<int> InsertAsync(GlobalSettings entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
return await con.InsertAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<GlobalSettings> GetAll()
|
||||
{
|
||||
var key = TypeName + "GetAll";
|
||||
|
@ -71,6 +80,20 @@ namespace PlexRequests.Store.Repository
|
|||
return item;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<GlobalSettings>> GetAllAsync()
|
||||
{
|
||||
var key = TypeName + "GetAll";
|
||||
var item = await Cache.GetOrSetAsync(key, async() =>
|
||||
{
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
var page = await con.GetAllAsync<GlobalSettings>();
|
||||
return page;
|
||||
}
|
||||
}, 5);
|
||||
return item;
|
||||
}
|
||||
|
||||
public GlobalSettings Get(string pageName)
|
||||
{
|
||||
var key = pageName + "Get";
|
||||
|
@ -85,6 +108,38 @@ namespace PlexRequests.Store.Repository
|
|||
return item;
|
||||
}
|
||||
|
||||
public async Task<GlobalSettings> GetAsync(string settingsName)
|
||||
{
|
||||
var key = settingsName + "Get";
|
||||
var item = await Cache.GetOrSetAsync(key, async() =>
|
||||
{
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
var page = await con.GetAllAsync<GlobalSettings>();
|
||||
return page.SingleOrDefault(x => x.SettingsName == settingsName);
|
||||
}
|
||||
}, 5);
|
||||
return item;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAsync(GlobalSettings entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
return await con.DeleteAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAsync(GlobalSettings entity)
|
||||
{
|
||||
ResetCache();
|
||||
using (var con = Db.DbConnection())
|
||||
{
|
||||
return await con.UpdateAsync(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Delete(GlobalSettings entity)
|
||||
{
|
||||
ResetCache();
|
||||
|
|
|
@ -27,41 +27,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Dapper.Contrib.Extensions;
|
||||
|
||||
using PlexRequests.Helpers;
|
||||
using PlexRequests.Store.Repository;
|
||||
|
||||
namespace PlexRequests.Store
|
||||
{
|
||||
public class UserRepository<T> : IRepository<T> where T : UserEntity
|
||||
public class UserRepository<T> : BaseGenericRepository<T>, IRepository<T> where T : UserEntity
|
||||
{
|
||||
public UserRepository(ISqliteConfiguration config)
|
||||
public UserRepository(ISqliteConfiguration config, ICacheProvider cache) : base(config, cache)
|
||||
{
|
||||
Config = config;
|
||||
|
||||
}
|
||||
|
||||
private ISqliteConfiguration Config { get; }
|
||||
public long Insert(T entity)
|
||||
public override T Get(int id)
|
||||
{
|
||||
using (var cnn = Config.DbConnection())
|
||||
{
|
||||
cnn.Open();
|
||||
return cnn.Insert(entity);
|
||||
}
|
||||
throw new NotSupportedException("Get(int) is not supported. Use Get(string)");
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetAll()
|
||||
public override Task<T> GetAsync(int id)
|
||||
{
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
var result = db.GetAll<T>();
|
||||
return result;
|
||||
}
|
||||
throw new NotSupportedException("GetAsync(int) is not supported. Use GetAsync(string)");
|
||||
}
|
||||
|
||||
public T Get(string id)
|
||||
public override T Get(string id)
|
||||
{
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
|
@ -72,33 +62,18 @@ namespace PlexRequests.Store
|
|||
}
|
||||
}
|
||||
|
||||
public T Get(int id)
|
||||
{
|
||||
throw new NotSupportedException("Get(int) is not supported. Use Get(string)");
|
||||
}
|
||||
|
||||
public void Delete(T entity)
|
||||
public override async Task<T> GetAsync(string id)
|
||||
{
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
db.Delete(entity);
|
||||
var result = await db.GetAllAsync<T>();
|
||||
var selected = result.FirstOrDefault(x => x.UserGuid == id);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Update(T entity)
|
||||
{
|
||||
using (var db = Config.DbConnection())
|
||||
{
|
||||
db.Open();
|
||||
return db.Update(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateAll(IEnumerable<T> entity)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Dapper" version="1.42" targetFramework="net45" />
|
||||
<package id="Dapper.Contrib" version="1.43" targetFramework="net45" />
|
||||
<package id="Dapper" version="1.50.0-beta8" targetFramework="net45" />
|
||||
<package id="Dapper.Contrib" version="1.50.0-beta8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net45" />
|
||||
<package id="NLog" version="4.2.3" targetFramework="net45" />
|
||||
</packages>
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
@ -1,295 +0,0 @@
|
|||
@media (min-width: 768px) {
|
||||
.row {
|
||||
position: relative; }
|
||||
.bottom-align-text {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0; } }
|
||||
|
||||
@media (max-width: 48em) {
|
||||
.home {
|
||||
padding-top: 1rem; } }
|
||||
|
||||
@media (min-width: 48em) {
|
||||
.home {
|
||||
padding-top: 4rem; } }
|
||||
|
||||
.navbar-default .navbar-nav > .active > a,
|
||||
.navbar-default .navbar-nav > .active > a:hover,
|
||||
.navbar-default .navbar-nav > .active > a:focus {
|
||||
color: #fff; }
|
||||
|
||||
hr {
|
||||
border-color: #777; }
|
||||
|
||||
body.update-available {
|
||||
margin-top: 80px; }
|
||||
|
||||
.btn {
|
||||
border-radius: 0.25rem !important; }
|
||||
|
||||
.multiSelect {
|
||||
background-color: #4e5d6c; }
|
||||
|
||||
.form-control-custom {
|
||||
background-color: #333333 !important;
|
||||
color: white !important;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 0 !important; }
|
||||
|
||||
h1 {
|
||||
font-size: 3.5rem !important;
|
||||
font-weight: 600 !important; }
|
||||
|
||||
.request-title {
|
||||
margin-top: 0 !important;
|
||||
font-size: 1.9rem !important; }
|
||||
|
||||
p {
|
||||
font-size: 1.1rem !important; }
|
||||
|
||||
label {
|
||||
display: inline-block !important;
|
||||
margin-bottom: 0.5rem !important;
|
||||
font-size: 16px !important; }
|
||||
|
||||
.nav-tabs > li {
|
||||
font-size: 13px;
|
||||
line-height: 21px; }
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background: #df691a; }
|
||||
|
||||
.nav-tabs > li > a > .fa {
|
||||
padding: 3px 5px 3px 3px; }
|
||||
|
||||
.nav-tabs > li.nav-tab-right {
|
||||
float: right; }
|
||||
|
||||
.nav-tabs > li.nav-tab-right a {
|
||||
margin-right: 0;
|
||||
margin-left: 2px; }
|
||||
|
||||
.nav-tabs > li.nav-tab-icononly .fa {
|
||||
padding: 3px; }
|
||||
|
||||
.navbar .nav a .fa,
|
||||
.dropdown-menu a .fa {
|
||||
font-size: 130%;
|
||||
top: 1px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-right: 5px; }
|
||||
|
||||
.dropdown-menu a .fa {
|
||||
top: 2px; }
|
||||
|
||||
.btn-danger-outline {
|
||||
color: #d9534f !important;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: #d9534f !important; }
|
||||
|
||||
.btn-danger-outline:focus,
|
||||
.btn-danger-outline.focus,
|
||||
.btn-danger-outline:active,
|
||||
.btn-danger-outline.active,
|
||||
.btn-danger-outline:hover,
|
||||
.open > .btn-danger-outline.dropdown-toggle {
|
||||
color: #fff !important;
|
||||
background-color: #d9534f !important;
|
||||
border-color: #d9534f !important; }
|
||||
|
||||
.btn-primary-outline {
|
||||
color: #ff761b !important;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: #ff761b !important; }
|
||||
|
||||
.btn-primary-outline:focus,
|
||||
.btn-primary-outline.focus,
|
||||
.btn-primary-outline:active,
|
||||
.btn-primary-outline.active,
|
||||
.btn-primary-outline:hover,
|
||||
.open > .btn-primary-outline.dropdown-toggle {
|
||||
color: #fff !important;
|
||||
background-color: #df691a !important;
|
||||
border-color: #df691a !important; }
|
||||
|
||||
.btn-info-outline {
|
||||
color: #5bc0de !important;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: #5bc0de !important; }
|
||||
|
||||
.btn-info-outline:focus,
|
||||
.btn-info-outline.focus,
|
||||
.btn-info-outline:active,
|
||||
.btn-info-outline.active,
|
||||
.btn-info-outline:hover,
|
||||
.open > .btn-info-outline.dropdown-toggle {
|
||||
color: #fff !important;
|
||||
background-color: #5bc0de !important;
|
||||
border-color: #5bc0de !important; }
|
||||
|
||||
.btn-warning-outline {
|
||||
color: #f0ad4e !important;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: #f0ad4e !important; }
|
||||
|
||||
.btn-warning-outline:focus,
|
||||
.btn-warning-outline.focus,
|
||||
.btn-warning-outline:active,
|
||||
.btn-warning-outline.active,
|
||||
.btn-warning-outline:hover,
|
||||
.open > .btn-warning-outline.dropdown-toggle {
|
||||
color: #fff !important;
|
||||
background-color: #f0ad4e !important;
|
||||
border-color: #f0ad4e !important; }
|
||||
|
||||
.btn-success-outline {
|
||||
color: #5cb85c !important;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: #5cb85c !important; }
|
||||
|
||||
.btn-success-outline:focus,
|
||||
.btn-success-outline.focus,
|
||||
.btn-success-outline:active,
|
||||
.btn-success-outline.active,
|
||||
.btn-success-outline:hover,
|
||||
.open > .btn-success-outline.dropdown-toggle {
|
||||
color: #fff !important;
|
||||
background-color: #5cb85c !important;
|
||||
border-color: #5cb85c !important; }
|
||||
|
||||
#movieList .mix {
|
||||
display: none; }
|
||||
|
||||
#tvList .mix {
|
||||
display: none; }
|
||||
|
||||
.scroll-top-wrapper {
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
z-index: 99999999;
|
||||
background-color: #333333;
|
||||
color: #eeeeee;
|
||||
width: 50px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
right: 30px;
|
||||
bottom: 30px;
|
||||
padding-top: 2px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
-webkit-transition: all 0.5s ease-in-out;
|
||||
-moz-transition: all 0.5s ease-in-out;
|
||||
-ms-transition: all 0.5s ease-in-out;
|
||||
-o-transition: all 0.5s ease-in-out;
|
||||
transition: all 0.5s ease-in-out; }
|
||||
|
||||
.scroll-top-wrapper:hover {
|
||||
background-color: #df691a; }
|
||||
|
||||
.scroll-top-wrapper.show {
|
||||
visibility: visible;
|
||||
cursor: pointer;
|
||||
opacity: 1.0; }
|
||||
|
||||
.scroll-top-wrapper i.fa {
|
||||
line-height: inherit; }
|
||||
|
||||
.no-search-results {
|
||||
text-align: center; }
|
||||
|
||||
.no-search-results .no-search-results-icon {
|
||||
font-size: 10em;
|
||||
color: #4e5d6c; }
|
||||
|
||||
.no-search-results .no-search-results-text {
|
||||
margin: 20px 0;
|
||||
color: #ccc; }
|
||||
|
||||
.form-control-search {
|
||||
padding: 13px 105px 13px 16px;
|
||||
height: 100%; }
|
||||
|
||||
.form-control-withbuttons {
|
||||
padding-right: 105px; }
|
||||
|
||||
.input-group-addon .btn-group {
|
||||
position: absolute;
|
||||
right: 45px;
|
||||
z-index: 3;
|
||||
top: 10px;
|
||||
box-shadow: 0 0 0; }
|
||||
|
||||
.input-group-addon .btn-group .btn {
|
||||
border: 1px solid rgba(255, 255, 255, 0.7) !important;
|
||||
padding: 3px 12px;
|
||||
color: rgba(255, 255, 255, 0.7) !important; }
|
||||
|
||||
.btn-split .btn {
|
||||
border-radius: 0 !important; }
|
||||
|
||||
.btn-split .btn:not(.dropdown-toggle) {
|
||||
border-radius: 0.25rem 0 0 0.25rem !important; }
|
||||
|
||||
.btn-split .btn.dropdown-toggle {
|
||||
border-radius: 0 0.25rem 0.25rem 0 !important;
|
||||
padding: 12px 8px; }
|
||||
|
||||
#updateAvailable {
|
||||
background-color: #df691a;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
padding: 3px 0; }
|
||||
|
||||
.checkbox label {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
padding-left: 25px;
|
||||
margin-right: 15px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px; }
|
||||
|
||||
.checkbox label:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 1px;
|
||||
border: 2px solid #eee;
|
||||
border-radius: 3px; }
|
||||
|
||||
.checkbox input[type=checkbox] {
|
||||
display: none; }
|
||||
|
||||
.checkbox input[type=checkbox]:checked + label:before {
|
||||
content: "\2713";
|
||||
font-size: 13px;
|
||||
color: #fafafa;
|
||||
text-align: center;
|
||||
line-height: 13px; }
|
||||
|
||||
.input-group-sm {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px; }
|
||||
|
||||
.tab-pane .form-horizontal .form-group {
|
||||
margin-right: 15px;
|
||||
margin-left: 15px; }
|
||||
|
File diff suppressed because one or more lines are too long
|
@ -1,365 +0,0 @@
|
|||
$form-color: #4e5d6c;
|
||||
$form-color-lighter: #637689;
|
||||
$primary-colour: #df691a;
|
||||
$primary-colour-outline: #ff761b;
|
||||
$info-colour: #5bc0de;
|
||||
$warning-colour: #f0ad4e;
|
||||
$danger-colour: #d9534f;
|
||||
$success-colour: #5cb85c;
|
||||
$bg-colour: #333333;
|
||||
$i:
|
||||
!important;
|
||||
|
||||
@media (min-width: 768px ) {
|
||||
.row {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bottom-align-text {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 48em) {
|
||||
.home {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 48em) {
|
||||
.home {
|
||||
padding-top: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > .active > a,
|
||||
.navbar-default .navbar-nav > .active > a:hover,
|
||||
.navbar-default .navbar-nav > .active > a:focus {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
body.update-available {
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: .25rem $i;
|
||||
}
|
||||
|
||||
.multiSelect {
|
||||
background-color: $form-color;
|
||||
}
|
||||
|
||||
.form-control-custom {
|
||||
background-color: $bg-colour $i;
|
||||
color: white $i;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 0 !important;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 3.5rem $i;
|
||||
font-weight: 600 $i;
|
||||
}
|
||||
|
||||
.request-title {
|
||||
margin-top: 0 $i;
|
||||
font-size: 1.9rem $i;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.1rem $i;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block $i;
|
||||
margin-bottom: .5rem $i;
|
||||
font-size: 16px $i;
|
||||
}
|
||||
|
||||
.nav-tabs > li {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background: $primary-colour;
|
||||
}
|
||||
|
||||
.nav-tabs > li > a > .fa {
|
||||
padding: 3px 5px 3px 3px;
|
||||
}
|
||||
|
||||
.nav-tabs > li.nav-tab-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.nav-tabs > li.nav-tab-right a {
|
||||
margin-right: 0;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.nav-tabs > li.nav-tab-icononly .fa {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.navbar .nav a .fa,
|
||||
.dropdown-menu a .fa {
|
||||
font-size: 130%;
|
||||
top: 1px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.dropdown-menu a .fa {
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.btn-danger-outline {
|
||||
color: $danger-colour $i;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: $danger-colour $i;
|
||||
}
|
||||
|
||||
.btn-danger-outline:focus,
|
||||
.btn-danger-outline.focus,
|
||||
.btn-danger-outline:active,
|
||||
.btn-danger-outline.active,
|
||||
.btn-danger-outline:hover,
|
||||
.open > .btn-danger-outline.dropdown-toggle {
|
||||
color: #fff $i;
|
||||
background-color: $danger-colour $i;
|
||||
border-color: $danger-colour $i;
|
||||
}
|
||||
|
||||
|
||||
.btn-primary-outline {
|
||||
color: $primary-colour-outline $i;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: $primary-colour-outline $i;
|
||||
}
|
||||
|
||||
.btn-primary-outline:focus,
|
||||
.btn-primary-outline.focus,
|
||||
.btn-primary-outline:active,
|
||||
.btn-primary-outline.active,
|
||||
.btn-primary-outline:hover,
|
||||
.open > .btn-primary-outline.dropdown-toggle {
|
||||
color: #fff $i;
|
||||
background-color: $primary-colour $i;
|
||||
border-color: $primary-colour $i;
|
||||
}
|
||||
|
||||
.btn-info-outline {
|
||||
color: $info-colour $i;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: $info-colour $i;
|
||||
}
|
||||
|
||||
.btn-info-outline:focus,
|
||||
.btn-info-outline.focus,
|
||||
.btn-info-outline:active,
|
||||
.btn-info-outline.active,
|
||||
.btn-info-outline:hover,
|
||||
.open > .btn-info-outline.dropdown-toggle {
|
||||
color: #fff $i;
|
||||
background-color: $info-colour $i;
|
||||
border-color: $info-colour $i;
|
||||
}
|
||||
|
||||
.btn-warning-outline {
|
||||
color: $warning-colour $i;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: $warning-colour $i;
|
||||
}
|
||||
|
||||
.btn-warning-outline:focus,
|
||||
.btn-warning-outline.focus,
|
||||
.btn-warning-outline:active,
|
||||
.btn-warning-outline.active,
|
||||
.btn-warning-outline:hover,
|
||||
.open > .btn-warning-outline.dropdown-toggle {
|
||||
color: #fff $i;
|
||||
background-color: $warning-colour $i;
|
||||
border-color: $warning-colour $i;
|
||||
}
|
||||
|
||||
.btn-success-outline {
|
||||
color: $success-colour $i;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: $success-colour $i;
|
||||
}
|
||||
|
||||
.btn-success-outline:focus,
|
||||
.btn-success-outline.focus,
|
||||
.btn-success-outline:active,
|
||||
.btn-success-outline.active,
|
||||
.btn-success-outline:hover,
|
||||
.open > .btn-success-outline.dropdown-toggle {
|
||||
color: #fff $i;
|
||||
background-color: $success-colour $i;
|
||||
border-color: $success-colour $i;
|
||||
}
|
||||
|
||||
#movieList .mix {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#tvList .mix {
|
||||
display: none;
|
||||
}
|
||||
|
||||
$border-radius: 10px;
|
||||
|
||||
.scroll-top-wrapper {
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
z-index: 99999999;
|
||||
background-color: $bg-colour;
|
||||
color: #eeeeee;
|
||||
width: 50px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
right: 30px;
|
||||
bottom: 30px;
|
||||
padding-top: 2px;
|
||||
border-top-left-radius: $border-radius;
|
||||
border-top-right-radius: $border-radius;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
border-bottom-left-radius: $border-radius;
|
||||
-webkit-transition: all 0.5s ease-in-out;
|
||||
-moz-transition: all 0.5s ease-in-out;
|
||||
-ms-transition: all 0.5s ease-in-out;
|
||||
-o-transition: all 0.5s ease-in-out;
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.scroll-top-wrapper:hover {
|
||||
background-color: $primary-colour;
|
||||
}
|
||||
|
||||
.scroll-top-wrapper.show {
|
||||
visibility: visible;
|
||||
cursor: pointer;
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.scroll-top-wrapper i.fa {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
|
||||
.no-search-results {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-search-results .no-search-results-icon {
|
||||
font-size: 10em;
|
||||
color: $form-color;
|
||||
}
|
||||
|
||||
.no-search-results .no-search-results-text {
|
||||
margin: 20px 0;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.form-control-search {
|
||||
padding: 13px 105px 13px 16px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.form-control-withbuttons {
|
||||
padding-right: 105px;
|
||||
}
|
||||
|
||||
.input-group-addon .btn-group {
|
||||
position: absolute;
|
||||
right: 45px;
|
||||
z-index: 3;
|
||||
top: 10px;
|
||||
box-shadow: 0 0 0;
|
||||
}
|
||||
|
||||
.input-group-addon .btn-group .btn {
|
||||
border: 1px solid rgba(255,255,255,.7) !important;
|
||||
padding: 3px 12px;
|
||||
color: rgba(255,255,255,.7) !important;
|
||||
}
|
||||
|
||||
.btn-split .btn {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.btn-split .btn:not(.dropdown-toggle) {
|
||||
border-radius: .25rem 0 0 .25rem $i;
|
||||
}
|
||||
|
||||
.btn-split .btn.dropdown-toggle {
|
||||
border-radius: 0 .25rem .25rem 0 $i;
|
||||
padding: 12px 8px;
|
||||
}
|
||||
|
||||
#updateAvailable {
|
||||
background-color: #df691a;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.checkbox label {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
padding-left: 25px;
|
||||
margin-right: 15px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px; }
|
||||
|
||||
.checkbox label:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 1px;
|
||||
border: 2px solid #eee;
|
||||
border-radius: 3px; }
|
||||
|
||||
.checkbox input[type=checkbox] {
|
||||
display: none; }
|
||||
|
||||
.checkbox input[type=checkbox]:checked + label:before {
|
||||
content: "\2713";
|
||||
font-size: 13px;
|
||||
color: #fafafa;
|
||||
text-align: center;
|
||||
line-height: 13px; }
|
||||
|
||||
.input-group-sm{
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.tab-pane .form-horizontal .form-group {
|
||||
margin-right: 15px;
|
||||
margin-left: 15px; }
|
1
PlexRequests.UI/Content/Themes/original.css
Normal file
1
PlexRequests.UI/Content/Themes/original.css
Normal file
|
@ -0,0 +1 @@
|
|||
|
1
PlexRequests.UI/Content/Themes/original.min.css
vendored
Normal file
1
PlexRequests.UI/Content/Themes/original.min.css
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
|
2
PlexRequests.UI/Content/Themes/original.scss
Normal file
2
PlexRequests.UI/Content/Themes/original.scss
Normal file
|
@ -0,0 +1,2 @@
|
|||
body {
|
||||
}
|
158
PlexRequests.UI/Content/Themes/plex.css
Normal file
158
PlexRequests.UI/Content/Themes/plex.css
Normal file
|
@ -0,0 +1,158 @@
|
|||
.form-control-custom {
|
||||
background-color: #333333 !important; }
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background: #df691a; }
|
||||
|
||||
scroll-top-wrapper {
|
||||
background-color: #333333; }
|
||||
|
||||
.scroll-top-wrapper:hover {
|
||||
background-color: #df691a; }
|
||||
|
||||
body {
|
||||
font-family: Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||
color: #eee;
|
||||
background-color: #1f1f1f; }
|
||||
|
||||
.table-striped > tbody > tr:nth-of-type(odd) {
|
||||
background-color: #333; }
|
||||
|
||||
.table-hover > tbody > tr:hover {
|
||||
background-color: #282828; }
|
||||
|
||||
fieldset {
|
||||
padding: 15px; }
|
||||
|
||||
legend {
|
||||
border-bottom: 1px solid #333333; }
|
||||
|
||||
.form-control {
|
||||
color: #fefefe;
|
||||
background-color: #333; }
|
||||
|
||||
.radio input[type="radio"],
|
||||
.radio-inline input[type="radio"],
|
||||
.checkbox input[type="checkbox"],
|
||||
.checkbox-inline input[type="checkbox"] {
|
||||
margin-left: -0px; }
|
||||
|
||||
.form-horizontal .radio,
|
||||
.form-horizontal .checkbox,
|
||||
.form-horizontal .radio-inline,
|
||||
.form-horizontal .checkbox-inline {
|
||||
margin-top: -15px; }
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: #282828; }
|
||||
|
||||
.dropdown-menu .divider {
|
||||
background-color: #333333; }
|
||||
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-color: #333; }
|
||||
|
||||
.input-group-addon {
|
||||
background-color: #333333; }
|
||||
|
||||
.nav > li > a:hover,
|
||||
.nav > li > a:focus {
|
||||
background-color: #df691a; }
|
||||
|
||||
.nav-tabs > li > a:hover {
|
||||
border-color: #df691a #df691a transparent; }
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background-color: #df691a;
|
||||
border: 1px solid #df691a; }
|
||||
|
||||
.nav-tabs.nav-justified > .active > a,
|
||||
.nav-tabs.nav-justified > .active > a:hover,
|
||||
.nav-tabs.nav-justified > .active > a:focus {
|
||||
border: 1px solid #df691a; }
|
||||
|
||||
/*.navbar {
|
||||
position: relative;
|
||||
min-height: 40px;
|
||||
margin-bottom: 21px;
|
||||
z-index: 1000;
|
||||
padding: 0px 3px;
|
||||
font-size: 24px;
|
||||
background-color: #000;
|
||||
box-shadow: 0px 0px 0px 3px rgba(0, 0, 0, 0.2);
|
||||
}*/
|
||||
.navbar-default {
|
||||
background-color: #0a0a0a; }
|
||||
|
||||
.navbar-default .navbar-brand {
|
||||
color: #DF691A; }
|
||||
|
||||
.navbar-default .navbar-nav > li > a:hover,
|
||||
.navbar-default .navbar-nav > li > a:focus {
|
||||
color: #F0ad4e;
|
||||
background-color: #282828; }
|
||||
|
||||
.navbar-default .navbar-nav > .active > a,
|
||||
.navbar-default .navbar-nav > .active > a:hover,
|
||||
.navbar-default .navbar-nav > .active > a:focus {
|
||||
background-color: #282828; }
|
||||
|
||||
.navbar-default .navbar-nav > .open > a,
|
||||
.navbar-default .navbar-nav > .open > a:hover,
|
||||
.navbar-default .navbar-nav > .open > a:focus {
|
||||
background-color: #df691a;
|
||||
color: #fff; }
|
||||
|
||||
.pagination > li > a,
|
||||
.pagination > li > span {
|
||||
background-color: #282828; }
|
||||
|
||||
.pagination > li > a:hover,
|
||||
.pagination > li > span:hover,
|
||||
.pagination > li > a:focus,
|
||||
.pagination > li > span:focus {
|
||||
background-color: #333; }
|
||||
|
||||
.pagination > .disabled > span,
|
||||
.pagination > .disabled > span:hover,
|
||||
.pagination > .disabled > span:focus,
|
||||
.pagination > .disabled > a,
|
||||
.pagination > .disabled > a:hover,
|
||||
.pagination > .disabled > a:focus {
|
||||
color: #fefefe;
|
||||
background-color: #333333; }
|
||||
|
||||
.list-group-item {
|
||||
background-color: #282828; }
|
||||
|
||||
a.list-group-item:hover,
|
||||
button.list-group-item:hover,
|
||||
a.list-group-item:focus,
|
||||
button.list-group-item:focus {
|
||||
background-color: #333333; }
|
||||
|
||||
.input-addon,
|
||||
.input-group-addon {
|
||||
color: #df691a; }
|
||||
|
||||
.modal-header,
|
||||
.modal-footer {
|
||||
background-color: #282828; }
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
background-color: #282828;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
outline: 0; }
|
||||
|
1
PlexRequests.UI/Content/Themes/plex.min.css
vendored
Normal file
1
PlexRequests.UI/Content/Themes/plex.min.css
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.form-control-custom{background-color:#333 !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#df691a;}scroll-top-wrapper{background-color:#333;}.scroll-top-wrapper:hover{background-color:#df691a;}body{font-family:Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;color:#eee;background-color:#1f1f1f;}.table-striped>tbody>tr:nth-of-type(odd){background-color:#333;}.table-hover>tbody>tr:hover{background-color:#282828;}fieldset{padding:15px;}legend{border-bottom:1px solid #333;}.form-control{color:#fefefe;background-color:#333;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-0;}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:-15px;}.dropdown-menu{background-color:#282828;}.dropdown-menu .divider{background-color:#333;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#333;}.input-group-addon{background-color:#333;}.nav>li>a:hover,.nav>li>a:focus{background-color:#df691a;}.nav-tabs>li>a:hover{border-color:#df691a #df691a transparent;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background-color:#df691a;border:1px solid #df691a;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #df691a;}.navbar-default{background-color:#0a0a0a;}.navbar-default .navbar-brand{color:#df691a;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#f0ad4e;background-color:#282828;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background-color:#282828;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#df691a;color:#fff;}.pagination>li>a,.pagination>li>span{background-color:#282828;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#333;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#fefefe;background-color:#333;}.list-group-item{background-color:#282828;}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{background-color:#333;}.input-addon,.input-group-addon{color:#df691a;}.modal-header,.modal-footer{background-color:#282828;}.modal-content{position:relative;background-color:#282828;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:0;}
|
196
PlexRequests.UI/Content/Themes/plex.scss
Normal file
196
PlexRequests.UI/Content/Themes/plex.scss
Normal file
|
@ -0,0 +1,196 @@
|
|||
$primary-colour: #df691a;
|
||||
$primary-colour-outline: #ff761b;
|
||||
$bg-colour: #333333;
|
||||
$i: !important;
|
||||
|
||||
.form-control-custom {
|
||||
background-color: $bg-colour $i;
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background: $primary-colour;
|
||||
}
|
||||
|
||||
scroll-top-wrapper {
|
||||
background-color: $bg-colour;
|
||||
}
|
||||
|
||||
.scroll-top-wrapper:hover {
|
||||
background-color: $primary-colour;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||
color: #eee;
|
||||
background-color: #1f1f1f;
|
||||
}
|
||||
|
||||
.table-striped > tbody > tr:nth-of-type(odd) {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.table-hover > tbody > tr:hover {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
legend {
|
||||
border-bottom: 1px solid #333333;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
color: #fefefe;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.radio input[type="radio"],
|
||||
.radio-inline input[type="radio"],
|
||||
.checkbox input[type="checkbox"],
|
||||
.checkbox-inline input[type="checkbox"] {
|
||||
margin-left: -0px;
|
||||
}
|
||||
|
||||
.form-horizontal .radio,
|
||||
.form-horizontal .checkbox,
|
||||
.form-horizontal .radio-inline,
|
||||
.form-horizontal .checkbox-inline {
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
.dropdown-menu .divider {
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.input-group-addon {
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.nav > li > a:hover,
|
||||
.nav > li > a:focus {
|
||||
background-color: #df691a;
|
||||
}
|
||||
|
||||
.nav-tabs > li > a:hover {
|
||||
border-color: #df691a #df691a transparent;
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background-color: #df691a;
|
||||
border: 1px solid #df691a;
|
||||
}
|
||||
|
||||
.nav-tabs.nav-justified > .active > a,
|
||||
.nav-tabs.nav-justified > .active > a:hover,
|
||||
.nav-tabs.nav-justified > .active > a:focus {
|
||||
border: 1px solid #df691a;
|
||||
}
|
||||
|
||||
/*.navbar {
|
||||
position: relative;
|
||||
min-height: 40px;
|
||||
margin-bottom: 21px;
|
||||
z-index: 1000;
|
||||
padding: 0px 3px;
|
||||
font-size: 24px;
|
||||
background-color: #000;
|
||||
box-shadow: 0px 0px 0px 3px rgba(0, 0, 0, 0.2);
|
||||
}*/
|
||||
|
||||
.navbar-default {
|
||||
background-color: #0a0a0a;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-brand {
|
||||
color: #DF691A;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > li > a:hover,
|
||||
.navbar-default .navbar-nav > li > a:focus {
|
||||
color: #F0ad4e;
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > .active > a,
|
||||
.navbar-default .navbar-nav > .active > a:hover,
|
||||
.navbar-default .navbar-nav > .active > a:focus {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > .open > a,
|
||||
.navbar-default .navbar-nav > .open > a:hover,
|
||||
.navbar-default .navbar-nav > .open > a:focus {
|
||||
background-color: #df691a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.pagination > li > a,
|
||||
.pagination > li > span {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
.pagination > li > a:hover,
|
||||
.pagination > li > span:hover,
|
||||
.pagination > li > a:focus,
|
||||
.pagination > li > span:focus {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.pagination > .disabled > span,
|
||||
.pagination > .disabled > span:hover,
|
||||
.pagination > .disabled > span:focus,
|
||||
.pagination > .disabled > a,
|
||||
.pagination > .disabled > a:hover,
|
||||
.pagination > .disabled > a:focus {
|
||||
color: #fefefe;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
a.list-group-item:hover,
|
||||
button.list-group-item:hover,
|
||||
a.list-group-item:focus,
|
||||
button.list-group-item:focus {
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.input-addon,
|
||||
.input-group-addon {
|
||||
color: #df691a;
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-footer {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
background-color: #282828;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
outline: 0;
|
||||
}
|
|
@ -20,11 +20,15 @@
|
|||
color: #fff; }
|
||||
|
||||
hr {
|
||||
border-color: #777; }
|
||||
border: 1px dashed #777; }
|
||||
|
||||
.btn {
|
||||
border-radius: 0.25rem !important; }
|
||||
|
||||
.btn-group-separated .btn,
|
||||
.btn-group-separated .btn + .btn {
|
||||
margin-left: 3px; }
|
||||
|
||||
.multiSelect {
|
||||
background-color: #4e5d6c; }
|
||||
|
1
PlexRequests.UI/Content/base.min.css
vendored
Normal file
1
PlexRequests.UI/Content/base.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -6,8 +6,7 @@ $info-colour: #5bc0de;
|
|||
$warning-colour: #f0ad4e;
|
||||
$danger-colour: #d9534f;
|
||||
$success-colour: #5cb85c;
|
||||
$i:
|
||||
!important;
|
||||
$i: !important;
|
||||
|
||||
@media (min-width: 768px ) {
|
||||
.row {
|
||||
|
@ -40,13 +39,18 @@ $i:
|
|||
}
|
||||
|
||||
hr {
|
||||
border-color: #777;
|
||||
border: 1px dashed #777;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: .25rem $i;
|
||||
}
|
||||
|
||||
.btn-group-separated .btn,
|
||||
.btn-group-separated .btn + .btn {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.multiSelect {
|
||||
background-color: $form-color;
|
||||
}
|
|
@ -12,6 +12,8 @@ var albumTemplate = Handlebars.compile(albumSource);
|
|||
var movieTimer = 0;
|
||||
var tvimer = 0;
|
||||
var base = $('#baseUrl').text();
|
||||
var tvLoaded = false;
|
||||
var albumLoaded = false;
|
||||
|
||||
var mixItUpDefault = {
|
||||
animation: { enable: true },
|
||||
|
@ -40,9 +42,14 @@ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
|||
var $tvl = $('#tvList');
|
||||
var $musicL = $('#musicList');
|
||||
|
||||
$('.approve-category').hide();
|
||||
$('.approve-category,.delete-category').hide();
|
||||
if (target === "#TvShowTab") {
|
||||
$('#approveTVShows').show();
|
||||
if (!tvLoaded) {
|
||||
tvLoaded = true;
|
||||
tvLoad();
|
||||
}
|
||||
|
||||
$('#approveTVShows,#deleteTVShows').show();
|
||||
if ($ml.mixItUp('isLoaded')) {
|
||||
activeState = $ml.mixItUp('getState');
|
||||
$ml.mixItUp('destroy');
|
||||
|
@ -51,11 +58,11 @@ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
|||
activeState = $musicL.mixItUp('getState');
|
||||
$musicL.mixItUp('destroy');
|
||||
}
|
||||
if ($tvl.mixItUp('isLoaded')) $tvl.mixItUp('destroy');
|
||||
$tvl.mixItUp(mixItUpConfig(activeState)); // init or reinit
|
||||
//if ($tvl.mixItUp('isLoaded')) $tvl.mixItUp('destroy');
|
||||
//$tvl.mixItUp(mixItUpConfig(activeState)); // init or reinit
|
||||
}
|
||||
if (target === "#MoviesTab") {
|
||||
$('#approveMovies').show();
|
||||
$('#approveMovies,#deleteMovies').show();
|
||||
if ($tvl.mixItUp('isLoaded')) {
|
||||
activeState = $tvl.mixItUp('getState');
|
||||
$tvl.mixItUp('destroy');
|
||||
|
@ -69,7 +76,11 @@ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
|||
}
|
||||
|
||||
if (target === "#MusicTab") {
|
||||
$('#approveMusic').show();
|
||||
if (!albumLoaded) {
|
||||
albumLoaded = true;
|
||||
albumLoad();
|
||||
}
|
||||
$('#approveMusic,#deleteMusic').show();
|
||||
if ($tvl.mixItUp('isLoaded')) {
|
||||
activeState = $tvl.mixItUp('getState');
|
||||
$tvl.mixItUp('destroy');
|
||||
|
@ -124,7 +135,7 @@ $('#approveTVShows').click(function (e) {
|
|||
return;
|
||||
}
|
||||
|
||||
loadingButton(buttonId, "success");
|
||||
loadingButton(buttonId, "warning");
|
||||
var url = createBaseUrl(base, '/approval/approvealltvshows');
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
|
@ -140,6 +151,72 @@ $('#approveTVShows').click(function (e) {
|
|||
console.log(e);
|
||||
generateNotify("Something went wrong!", "danger");
|
||||
},
|
||||
complete: function (e) {
|
||||
finishLoading(buttonId, "warning", origHtml);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#deleteMovies').click(function (e) {
|
||||
e.preventDefault();
|
||||
if (!confirm("Are you sure you want to delete all TV show requests?")) return;
|
||||
|
||||
var buttonId = e.target.id;
|
||||
var origHtml = $(this).html();
|
||||
|
||||
if ($('#' + buttonId).text() === " Loading...") {
|
||||
return;
|
||||
}
|
||||
|
||||
loadingButton(buttonId, "warning");
|
||||
|
||||
var url = createBaseUrl(base, '/approval/deleteallmovies');
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
if (checkJsonResponse(response)) {
|
||||
generateNotify("Success! All Movie requests deleted!", "success");
|
||||
movieLoad();
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
console.log(e);
|
||||
generateNotify("Something went wrong!", "danger");
|
||||
},
|
||||
complete: function (e) {
|
||||
finishLoading(buttonId, "warning", origHtml);
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#deleteTVShows').click(function (e) {
|
||||
e.preventDefault();
|
||||
if (!confirm("Are you sure you want to delete all TV show requests?")) return;
|
||||
|
||||
var buttonId = e.target.id;
|
||||
var origHtml = $(this).html();
|
||||
|
||||
if ($('#' + buttonId).text() === " Loading...") {
|
||||
return;
|
||||
}
|
||||
|
||||
loadingButton(buttonId, "warning");
|
||||
var url = createBaseUrl(base, '/approval/deletealltvshows');
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
if (checkJsonResponse(response)) {
|
||||
generateNotify("Success! All TV Show requests deleted!", "success");
|
||||
tvLoad();
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
console.log(e);
|
||||
generateNotify("Something went wrong!", "danger");
|
||||
},
|
||||
complete: function (e) {
|
||||
finishLoading(buttonId, "success", origHtml);
|
||||
}
|
||||
|
@ -448,10 +525,10 @@ function mixItUpConfig(activeState) {
|
|||
return conf;
|
||||
};
|
||||
|
||||
var position = 0;
|
||||
function initLoad() {
|
||||
movieLoad();
|
||||
tvLoad();
|
||||
albumLoad();
|
||||
|
||||
}
|
||||
|
||||
function movieLoad() {
|
||||
|
|
|
@ -57,12 +57,15 @@ namespace PlexRequests.UI.Helpers
|
|||
{
|
||||
settings.ThemeName = Themes.PlexTheme;
|
||||
}
|
||||
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/Themes/{settings.ThemeName}\" type=\"text/css\"/>");
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/Themes/{settings.ThemeName.Replace(".css",string.Empty)}Custom.min.css\" type=\"text/css\" />");
|
||||
if (settings.ThemeName == "PlexBootstrap.css") settings.ThemeName = Themes.PlexTheme;
|
||||
if (settings.ThemeName == "OriginalBootstrap.css") settings.ThemeName = Themes.OriginalTheme;
|
||||
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/bootstrap.css\" type=\"text/css\"/>");
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/font-awesome.css\" type=\"text/css\"/>");
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/pace.min.css\" type=\"text/css\"/>");
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/awesome-bootstrap-checkbox.css\" type=\"text/css\"/>");
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/base.css\" type=\"text/css\"/>");
|
||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/Themes/{settings.ThemeName}\" type=\"text/css\"/>");
|
||||
|
||||
sb.AppendLine($"<script src=\"{content}/Content/jquery-2.2.1.min.js\"></script>");
|
||||
sb.AppendLine($"<script src=\"{content}/Content/handlebars.min.js\"></script>");
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace PlexRequests.UI.Helpers
|
|||
{
|
||||
public static class Themes
|
||||
{
|
||||
public const string OriginalTheme = "OriginalBootstrap.css";
|
||||
public const string PlexTheme = "PlexBootstrap.css";
|
||||
public const string OriginalTheme = "original.css";
|
||||
public const string PlexTheme = "plex.css";
|
||||
}
|
||||
}
|
|
@ -56,13 +56,15 @@ namespace PlexRequests.UI.Jobs
|
|||
var sickrage = JobBuilder.Create<SickRageCacher>().WithIdentity("SickRageCacher", "Cache").Build();
|
||||
var sonarr = JobBuilder.Create<SonarrCacher>().WithIdentity("SonarrCacher", "Cache").Build();
|
||||
var cp = JobBuilder.Create<CouchPotatoCacher>().WithIdentity("CouchPotatoCacher", "Cache").Build();
|
||||
var store = JobBuilder.Create<StoreBackup>().WithIdentity("StoreBackup", "Backup").Build();
|
||||
var store = JobBuilder.Create<StoreBackup>().WithIdentity("StoreBackup", "Database").Build();
|
||||
var storeClean = JobBuilder.Create<StoreCleanup>().WithIdentity("StoreCleanup", "Database").Build();
|
||||
|
||||
jobs.Add(plex);
|
||||
jobs.Add(sickrage);
|
||||
jobs.Add(sonarr);
|
||||
jobs.Add(cp);
|
||||
jobs.Add(store);
|
||||
jobs.Add(storeClean);
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
@ -129,17 +131,25 @@ namespace PlexRequests.UI.Jobs
|
|||
|
||||
var storeBackup =
|
||||
TriggerBuilder.Create()
|
||||
.WithIdentity("StoreBackup", "Backup")
|
||||
.WithIdentity("StoreBackup", "Database")
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())
|
||||
.Build();
|
||||
|
||||
var storeCleanup =
|
||||
TriggerBuilder.Create()
|
||||
.WithIdentity("StoreCleanup", "Database")
|
||||
.StartNow()
|
||||
.WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())
|
||||
.Build();
|
||||
|
||||
|
||||
triggers.Add(plexAvailabilityChecker);
|
||||
triggers.Add(srCacher);
|
||||
triggers.Add(sonarrCacher);
|
||||
triggers.Add(cpCacher);
|
||||
triggers.Add(storeBackup);
|
||||
triggers.Add(storeCleanup);
|
||||
|
||||
return triggers;
|
||||
}
|
||||
|
|
|
@ -481,8 +481,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
return Response.AsJson(valid.SendJsonError());
|
||||
}
|
||||
Log.Trace(settings.DumpJson());
|
||||
|
||||
|
||||
var result = EmailService.SaveSettings(settings);
|
||||
|
||||
if (settings.Enabled)
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace PlexRequests.UI.Modules
|
|||
ISettingsService<SonarrSettings> sonarrSettings, ISickRageApi srApi, ISettingsService<SickRageSettings> srSettings,
|
||||
ISettingsService<HeadphonesSettings> hpSettings, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr) : base("approval", pr)
|
||||
{
|
||||
this.RequiresClaims(UserClaims.Admin);
|
||||
this.RequiresClaims(UserClaims.Admin);
|
||||
|
||||
Service = service;
|
||||
CpService = cpService;
|
||||
|
@ -66,6 +66,8 @@ namespace PlexRequests.UI.Modules
|
|||
Post["/approveall"] = x => ApproveAll();
|
||||
Post["/approveallmovies"] = x => ApproveAllMovies();
|
||||
Post["/approvealltvshows"] = x => ApproveAllTVShows();
|
||||
Post["/deleteallmovies"] = x => DeleteAllMovies();
|
||||
Post["/deletealltvshows"] = x => DeleteAllTVShows();
|
||||
}
|
||||
|
||||
private IRequestService Service { get; }
|
||||
|
@ -130,7 +132,7 @@ namespace PlexRequests.UI.Modules
|
|||
Log.Trace("Approval result: {0}", requestResult);
|
||||
if (requestResult)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel {Result = true});
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
|
@ -156,11 +158,9 @@ namespace PlexRequests.UI.Modules
|
|||
request.Approved = true;
|
||||
var requestResult = Service.UpdateRequest(request);
|
||||
Log.Trace("Approval result: {0}", requestResult);
|
||||
if (requestResult)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Updated SickRage but could not approve it in PlexRequests :(" });
|
||||
return Response.AsJson(requestResult
|
||||
? new JsonResponseModel { Result = true }
|
||||
: new JsonResponseModel { Result = false, Message = "Updated SickRage but could not approve it in PlexRequests :(" });
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
|
@ -168,17 +168,19 @@ namespace PlexRequests.UI.Modules
|
|||
Message = result?.message != null ? "<b>Message From SickRage: </b>" + result.message : "Could not add the series to SickRage"
|
||||
});
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = false,
|
||||
Message = "SickRage or Sonarr are not set up!"
|
||||
});
|
||||
|
||||
|
||||
request.Approved = true;
|
||||
var res = Service.UpdateRequest(request);
|
||||
return Response.AsJson(res
|
||||
? new JsonResponseModel { Result = true, Message = "This has been approved, but It has not been sent to Sonarr/SickRage because it has not been configured" }
|
||||
: new JsonResponseModel { Result = false, Message = "Updated SickRage but could not approve it in PlexRequests :(" });
|
||||
}
|
||||
|
||||
private Response RequestMovieAndUpdateStatus(RequestedModel request, string qualityId)
|
||||
{
|
||||
var cpSettings = CpService.GetSettings();
|
||||
var cp = new CouchPotatoApi();
|
||||
|
||||
Log.Info("Adding movie to CouchPotato : {0}", request.Title);
|
||||
if (!cpSettings.Enabled)
|
||||
{
|
||||
|
@ -197,7 +199,7 @@ namespace PlexRequests.UI.Modules
|
|||
});
|
||||
}
|
||||
|
||||
var result = cp.AddMovie(request.ImdbId, cpSettings.ApiKey, request.Title, cpSettings.FullUri, string.IsNullOrEmpty(qualityId) ? cpSettings.ProfileId : qualityId);
|
||||
var result = CpApi.AddMovie(request.ImdbId, cpSettings.ApiKey, request.Title, cpSettings.FullUri, string.IsNullOrEmpty(qualityId) ? cpSettings.ProfileId : qualityId);
|
||||
Log.Trace("Adding movie to CP result {0}", result);
|
||||
if (result)
|
||||
{
|
||||
|
@ -248,9 +250,9 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
var sender = new HeadphonesSender(HeadphoneApi, hpSettings, Service);
|
||||
var result = sender.AddAlbum(request);
|
||||
|
||||
|
||||
return Response.AsJson( new JsonResponseModel { Result = true, Message = "We have sent the approval to Headphones for processing, This can take a few minutes."} );
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = "We have sent the approval to Headphones for processing, This can take a few minutes." });
|
||||
}
|
||||
|
||||
private Response ApproveAllMovies()
|
||||
|
@ -274,6 +276,27 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
}
|
||||
|
||||
private Response DeleteAllMovies()
|
||||
{
|
||||
|
||||
var requests = Service.GetAll().Where(x => x.Type == RequestType.Movie);
|
||||
var requestedModels = requests as RequestedModel[] ?? requests.ToArray();
|
||||
if (!requestedModels.Any())
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "There are no movie requests to delete. Please refresh." });
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return DeleteRequests(requestedModels);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Fatal(e);
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something bad happened, please check the logs!" });
|
||||
}
|
||||
}
|
||||
|
||||
private Response ApproveAllTVShows()
|
||||
{
|
||||
var requests = Service.GetAll().Where(x => x.CanApprove && x.Type == RequestType.TvShow);
|
||||
|
@ -294,6 +317,27 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
}
|
||||
|
||||
private Response DeleteAllTVShows()
|
||||
{
|
||||
|
||||
var requests = Service.GetAll().Where(x => x.Type == RequestType.TvShow);
|
||||
var requestedModels = requests as RequestedModel[] ?? requests.ToArray();
|
||||
if (!requestedModels.Any())
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "There are no tv show requests to delete. Please refresh." });
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return DeleteRequests(requestedModels);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Fatal(e);
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something bad happened, please check the logs!" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Approves all.
|
||||
/// </summary>
|
||||
|
@ -319,6 +363,22 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
}
|
||||
|
||||
private Response DeleteRequests(RequestedModel[] requestedModels)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = Service.BatchDelete(requestedModels.ToList());
|
||||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true }
|
||||
: new JsonResponseModel { Result = false, Message = "We could not delete all of the requests. Please try again or check the logs." });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Fatal(e);
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something bad happened, please check the logs!" });
|
||||
}
|
||||
}
|
||||
|
||||
private Response UpdateRequests(RequestedModel[] requestedModels)
|
||||
{
|
||||
var cpSettings = CpService.GetSettings();
|
||||
|
@ -327,15 +387,23 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
if (r.Type == RequestType.Movie)
|
||||
{
|
||||
var res = SendMovie(cpSettings, r, CpApi);
|
||||
if (res)
|
||||
if (cpSettings.Enabled)
|
||||
{
|
||||
r.Approved = true;
|
||||
updatedRequests.Add(r);
|
||||
var res = SendMovie(cpSettings, r, CpApi);
|
||||
if (res)
|
||||
{
|
||||
r.Approved = true;
|
||||
updatedRequests.Add(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("Could not approve and send the movie {0} to couch potato!", r.Title);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("Could not approve and send the movie {0} to couch potato!", r.Title);
|
||||
r.Approved = true;
|
||||
updatedRequests.Add(r);
|
||||
}
|
||||
}
|
||||
if (r.Type == RequestType.TvShow)
|
||||
|
@ -358,7 +426,7 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
}
|
||||
|
||||
if (sonarr.Enabled)
|
||||
else if (sonarr.Enabled)
|
||||
{
|
||||
var res = sender.SendToSonarr(sonarr, r);
|
||||
if (!string.IsNullOrEmpty(res?.title))
|
||||
|
@ -372,11 +440,15 @@ namespace PlexRequests.UI.Modules
|
|||
res?.ErrorMessages.ForEach(x => Log.Error("Error messages: {0}", x));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Approved = true;
|
||||
updatedRequests.Add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
|
||||
var result = Service.BatchUpdate(updatedRequests);
|
||||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true }
|
||||
|
|
|
@ -35,6 +35,7 @@ using Nancy.Security;
|
|||
|
||||
using PlexRequests.Core;
|
||||
using PlexRequests.Core.SettingModels;
|
||||
using PlexRequests.Helpers;
|
||||
using PlexRequests.UI.Models;
|
||||
|
||||
namespace PlexRequests.UI.Modules
|
||||
|
@ -103,7 +104,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
return Context.GetRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/register?error=true" : "~/register?error=true");
|
||||
}
|
||||
var userId = UserMapper.CreateUser(username, Request.Form.Password, new[] { "Admin" });
|
||||
var userId = UserMapper.CreateAdmin(username, Request.Form.Password);
|
||||
Session[SessionKeys.UsernameKey] = username;
|
||||
return this.LoginAndRedirect((Guid)userId);
|
||||
};
|
||||
|
|
|
@ -74,17 +74,17 @@ namespace PlexRequests.UI.Modules
|
|||
Cache = cache;
|
||||
|
||||
Get["/"] = _ => LoadRequests();
|
||||
Get["/movies"] = _ => GetMovies();
|
||||
Get["/tvshows"] = _ => GetTvShows();
|
||||
Get["/albums"] = _ => GetAlbumRequests();
|
||||
Post["/delete"] = _ => DeleteRequest((int)Request.Form.id);
|
||||
Post["/reportissue"] = _ => ReportIssue((int)Request.Form.requestId, (IssueState)(int)Request.Form.issue, null);
|
||||
Post["/reportissuecomment"] = _ => ReportIssue((int)Request.Form.requestId, IssueState.Other, (string)Request.Form.commentArea);
|
||||
Get["/movies", true] = async (x, ct) => await GetMovies();
|
||||
Get["/tvshows", true] = async (c, ct) => await GetTvShows();
|
||||
Get["/albums", true] = async (x,ct) => await GetAlbumRequests();
|
||||
Post["/delete", true] = async (x, ct) => await DeleteRequest((int)Request.Form.id);
|
||||
Post["/reportissue", true] = async (x, ct) => await ReportIssue((int)Request.Form.requestId, (IssueState)(int)Request.Form.issue, null);
|
||||
Post["/reportissuecomment", true] = async (x, ct) => await ReportIssue((int)Request.Form.requestId, IssueState.Other, (string)Request.Form.commentArea);
|
||||
|
||||
Post["/clearissues"] = _ => ClearIssue((int)Request.Form.Id);
|
||||
Post["/clearissues", true] = async (x, ct) => await ClearIssue((int)Request.Form.Id);
|
||||
|
||||
Post["/changeavailability"] = _ => ChangeRequestAvailability((int)Request.Form.Id, (bool)Request.Form.Available);
|
||||
Post["/addnote"] = _ => AddNote((int)Request.Form.requestId, (string)Request.Form.noteArea);
|
||||
Post["/changeavailability", true] = async (x, ct) => await ChangeRequestAvailability((int)Request.Form.Id, (bool)Request.Form.Available);
|
||||
Post["/addnote", true] = async (x, ct) => await AddNote((int)Request.Form.requestId, (string)Request.Form.noteArea);
|
||||
}
|
||||
|
||||
private IRequestService Service { get; }
|
||||
|
@ -105,122 +105,94 @@ namespace PlexRequests.UI.Modules
|
|||
return View["Index", settings];
|
||||
}
|
||||
|
||||
private Response GetMovies() // TODO: async await the API calls
|
||||
private async Task<Response> GetMovies()
|
||||
{
|
||||
var settings = PrSettings.GetSettings();
|
||||
|
||||
List<Task> taskList = new List<Task>();
|
||||
var allRequests = await Service.GetAllAsync();
|
||||
allRequests = allRequests.Where(x => x.Type == RequestType.Movie);
|
||||
|
||||
List<RequestedModel> dbMovies = new List<RequestedModel>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
var dbMovies = allRequests.ToList();
|
||||
|
||||
if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin)
|
||||
{
|
||||
return Service.GetAll().Where(x => x.Type == RequestType.Movie);
|
||||
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
dbMovies = t.Result.ToList();
|
||||
|
||||
if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin)
|
||||
{
|
||||
dbMovies = dbMovies.Where(x => x.UserHasRequested(Username)).ToList();
|
||||
}
|
||||
}));
|
||||
|
||||
dbMovies = dbMovies.Where(x => x.UserHasRequested(Username)).ToList();
|
||||
}
|
||||
|
||||
List<QualityModel> qualities = new List<QualityModel>();
|
||||
|
||||
if (IsAdmin)
|
||||
if (IsAdmin)
|
||||
{
|
||||
var cpSettings = CpSettings.GetSettings();
|
||||
if (cpSettings.Enabled)
|
||||
{
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
|
||||
var result = await Cache.GetOrSetAsync(CacheKeys.CouchPotatoQualityProfiles, async () =>
|
||||
{
|
||||
return Cache.GetOrSet(CacheKeys.CouchPotatoQualityProfiles, () =>
|
||||
{
|
||||
return CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey); // TODO: cache this!
|
||||
});
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
qualities = t.Result.list.Select(x => new QualityModel() { Id = x._id, Name = x.label }).ToList();
|
||||
}));
|
||||
return await Task.Run(() => CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey)).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
qualities = result.list.Select(x => new QualityModel() { Id = x._id, Name = x.label }).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
Task.WaitAll(taskList.ToArray());
|
||||
|
||||
var viewModel = dbMovies.Select(movie =>
|
||||
var viewModel = dbMovies.Select(movie => new RequestViewModel
|
||||
{
|
||||
return new RequestViewModel
|
||||
{
|
||||
ProviderId = movie.ProviderId,
|
||||
Type = movie.Type,
|
||||
Status = movie.Status,
|
||||
ImdbId = movie.ImdbId,
|
||||
Id = movie.Id,
|
||||
PosterPath = movie.PosterPath,
|
||||
ReleaseDate = movie.ReleaseDate,
|
||||
ReleaseDateTicks = movie.ReleaseDate.Ticks,
|
||||
RequestedDate = movie.RequestedDate,
|
||||
Released = DateTime.Now > movie.ReleaseDate,
|
||||
RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(movie.RequestedDate, DateTimeOffset).Ticks,
|
||||
Approved = movie.Available || movie.Approved,
|
||||
Title = movie.Title,
|
||||
Overview = movie.Overview,
|
||||
RequestedUsers = IsAdmin ? movie.AllUsers.ToArray() : new string[] { },
|
||||
ReleaseYear = movie.ReleaseDate.Year.ToString(),
|
||||
Available = movie.Available,
|
||||
Admin = IsAdmin,
|
||||
Issues = movie.Issues.ToString().CamelCaseToWords(),
|
||||
OtherMessage = movie.OtherMessage,
|
||||
AdminNotes = movie.AdminNote,
|
||||
Qualities = qualities.ToArray()
|
||||
};
|
||||
ProviderId = movie.ProviderId,
|
||||
Type = movie.Type,
|
||||
Status = movie.Status,
|
||||
ImdbId = movie.ImdbId,
|
||||
Id = movie.Id,
|
||||
PosterPath = movie.PosterPath,
|
||||
ReleaseDate = movie.ReleaseDate,
|
||||
ReleaseDateTicks = movie.ReleaseDate.Ticks,
|
||||
RequestedDate = movie.RequestedDate,
|
||||
Released = DateTime.Now > movie.ReleaseDate,
|
||||
RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(movie.RequestedDate, DateTimeOffset).Ticks,
|
||||
Approved = movie.Available || movie.Approved,
|
||||
Title = movie.Title,
|
||||
Overview = movie.Overview,
|
||||
RequestedUsers = IsAdmin ? movie.AllUsers.ToArray() : new string[] { },
|
||||
ReleaseYear = movie.ReleaseDate.Year.ToString(),
|
||||
Available = movie.Available,
|
||||
Admin = IsAdmin,
|
||||
Issues = movie.Issues.ToString().CamelCaseToWords(),
|
||||
OtherMessage = movie.OtherMessage,
|
||||
AdminNotes = movie.AdminNote,
|
||||
Qualities = qualities.ToArray()
|
||||
}).ToList();
|
||||
|
||||
return Response.AsJson(viewModel);
|
||||
}
|
||||
|
||||
private Response GetTvShows() // TODO: async await the API calls
|
||||
private async Task<Response> GetTvShows()
|
||||
{
|
||||
var settings = PrSettings.GetSettings();
|
||||
|
||||
List<Task> taskList = new List<Task>();
|
||||
var requests = await Service.GetAllAsync();
|
||||
requests = requests.Where(x => x.Type == RequestType.TvShow);
|
||||
|
||||
List<RequestedModel> dbTv = new List<RequestedModel>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
var dbTv = requests;
|
||||
|
||||
if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin)
|
||||
{
|
||||
return Service.GetAll().Where(x => x.Type == RequestType.TvShow);
|
||||
dbTv = dbTv.Where(x => x.UserHasRequested(Username)).ToList();
|
||||
}
|
||||
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
dbTv = t.Result.ToList();
|
||||
|
||||
if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin)
|
||||
{
|
||||
dbTv = dbTv.Where(x => x.UserHasRequested(Username)).ToList();
|
||||
}
|
||||
}));
|
||||
|
||||
List<QualityModel> qualities = new List<QualityModel>();
|
||||
IEnumerable<QualityModel> qualities = new List<QualityModel>();
|
||||
if (IsAdmin)
|
||||
{
|
||||
var sonarrSettings = SonarrSettings.GetSettings();
|
||||
if (sonarrSettings.Enabled)
|
||||
{
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
var result = Cache.GetOrSetAsync(CacheKeys.SonarrQualityProfiles, async () =>
|
||||
{
|
||||
return Cache.GetOrSet(CacheKeys.SonarrQualityProfiles, () =>
|
||||
{
|
||||
return SonarrApi.GetProfiles(sonarrSettings.ApiKey, sonarrSettings.FullUri); // TODO: cache this!
|
||||
|
||||
return await Task.Run(() => SonarrApi.GetProfiles(sonarrSettings.ApiKey, sonarrSettings.FullUri));
|
||||
});
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
qualities = t.Result.Select(x => new QualityModel() { Id = x.id.ToString(), Name = x.name }).ToList();
|
||||
}));
|
||||
qualities = result.Result.Select(x => new QualityModel() { Id = x.id.ToString(), Name = x.name }).ToList();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
var sickRageSettings = SickRageSettings.GetSettings();
|
||||
if (sickRageSettings.Enabled)
|
||||
{
|
||||
|
@ -229,8 +201,6 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
}
|
||||
|
||||
Task.WaitAll(taskList.ToArray());
|
||||
|
||||
var viewModel = dbTv.Select(tv =>
|
||||
{
|
||||
return new RequestViewModel
|
||||
|
@ -264,10 +234,11 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(viewModel);
|
||||
}
|
||||
|
||||
private Response GetAlbumRequests()
|
||||
private async Task<Response> GetAlbumRequests()
|
||||
{
|
||||
var settings = PrSettings.GetSettings();
|
||||
var dbAlbum = Service.GetAll().Where(x => x.Type == RequestType.Album);
|
||||
var dbAlbum = await Service.GetAllAsync();
|
||||
dbAlbum = dbAlbum.Where(x => x.Type == RequestType.Album);
|
||||
if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin)
|
||||
{
|
||||
dbAlbum = dbAlbum.Where(x => x.UserHasRequested(Username));
|
||||
|
@ -308,12 +279,12 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(viewModel);
|
||||
}
|
||||
|
||||
private Response DeleteRequest(int requestid)
|
||||
{
|
||||
this.RequiresClaims (UserClaims.Admin);
|
||||
private async Task<Response> DeleteRequest(int requestid)
|
||||
{
|
||||
this.RequiresClaims(UserClaims.Admin);
|
||||
|
||||
var currentEntity = Service.Get(requestid);
|
||||
Service.DeleteRequest(currentEntity);
|
||||
var currentEntity = await Service.GetAsync(requestid);
|
||||
await Service.DeleteRequestAsync(currentEntity);
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
|
||||
|
@ -325,9 +296,9 @@ namespace PlexRequests.UI.Modules
|
|||
/// <param name="issue">The issue.</param>
|
||||
/// <param name="comment">The comment.</param>
|
||||
/// <returns></returns>
|
||||
private Response ReportIssue(int requestId, IssueState issue, string comment)
|
||||
private async Task<Response> ReportIssue(int requestId, IssueState issue, string comment)
|
||||
{
|
||||
var originalRequest = Service.Get(requestId);
|
||||
var originalRequest = await Service.GetAsync(requestId);
|
||||
if (originalRequest == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not add issue, please try again or contact the administrator!" });
|
||||
|
@ -338,7 +309,7 @@ namespace PlexRequests.UI.Modules
|
|||
: string.Empty;
|
||||
|
||||
|
||||
var result = Service.UpdateRequest(originalRequest);
|
||||
var result = await Service.UpdateRequestAsync(originalRequest);
|
||||
|
||||
var model = new NotificationModel
|
||||
{
|
||||
|
@ -348,18 +319,18 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime = DateTime.Now,
|
||||
Body = issue == IssueState.Other ? comment : issue.ToString().CamelCaseToWords()
|
||||
};
|
||||
NotificationService.Publish(model);
|
||||
await NotificationService.Publish(model);
|
||||
|
||||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true }
|
||||
: new JsonResponseModel { Result = false, Message = "Could not add issue, please try again or contact the administrator!" });
|
||||
}
|
||||
|
||||
private Response ClearIssue(int requestId)
|
||||
private async Task<Response> ClearIssue(int requestId)
|
||||
{
|
||||
this.RequiresClaims ( UserClaims.Admin);
|
||||
this.RequiresClaims(UserClaims.Admin);
|
||||
|
||||
var originalRequest = Service.Get(requestId);
|
||||
var originalRequest = await Service.GetAsync(requestId);
|
||||
if (originalRequest == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Request does not exist to clear it!" });
|
||||
|
@ -367,16 +338,16 @@ namespace PlexRequests.UI.Modules
|
|||
originalRequest.Issues = IssueState.None;
|
||||
originalRequest.OtherMessage = string.Empty;
|
||||
|
||||
var result = Service.UpdateRequest(originalRequest);
|
||||
var result = await Service.UpdateRequestAsync(originalRequest);
|
||||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true }
|
||||
: new JsonResponseModel { Result = false, Message = "Could not clear issue, please try again or check the logs" });
|
||||
}
|
||||
|
||||
private Response ChangeRequestAvailability(int requestId, bool available)
|
||||
{
|
||||
this.RequiresClaims (UserClaims.Admin);
|
||||
var originalRequest = Service.Get(requestId);
|
||||
private async Task<Response> ChangeRequestAvailability(int requestId, bool available)
|
||||
{
|
||||
this.RequiresClaims(UserClaims.Admin);
|
||||
var originalRequest = await Service.GetAsync(requestId);
|
||||
if (originalRequest == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Request does not exist to change the availability!" });
|
||||
|
@ -384,16 +355,16 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
originalRequest.Available = available;
|
||||
|
||||
var result = Service.UpdateRequest(originalRequest);
|
||||
var result = await Service.UpdateRequestAsync(originalRequest);
|
||||
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" });
|
||||
}
|
||||
|
||||
private Response AddNote(int requestId, string noteArea)
|
||||
{
|
||||
this.RequiresClaims (UserClaims.Admin);
|
||||
var originalRequest = Service.Get(requestId);
|
||||
private async Task<Response> AddNote(int requestId, string noteArea)
|
||||
{
|
||||
this.RequiresClaims(UserClaims.Admin);
|
||||
var originalRequest = await Service.GetAsync(requestId);
|
||||
if (originalRequest == null)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Request does not exist to add a note!" });
|
||||
|
@ -401,7 +372,7 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
originalRequest.AdminNote = noteArea;
|
||||
|
||||
var result = Service.UpdateRequest(originalRequest);
|
||||
var result = await Service.UpdateRequestAsync(originalRequest);
|
||||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true }
|
||||
: new JsonResponseModel { Result = false, Message = "Could not update the notes, please try again or check the logs" });
|
||||
|
|
|
@ -47,7 +47,7 @@ using PlexRequests.Store;
|
|||
using PlexRequests.UI.Helpers;
|
||||
using PlexRequests.UI.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Nancy.Extensions;
|
||||
using PlexRequests.Api.Models.Tv;
|
||||
using PlexRequests.Store.Models;
|
||||
|
@ -92,22 +92,22 @@ namespace PlexRequests.UI.Modules
|
|||
EmailNotificationSettings = email;
|
||||
|
||||
|
||||
Get["/"] = parameters => RequestLoad();
|
||||
Get["/", true] = async (x, ct) => await RequestLoad();
|
||||
|
||||
Get["movie/{searchTerm}"] = parameters => SearchMovie((string)parameters.searchTerm);
|
||||
Get["tv/{searchTerm}"] = parameters => SearchTvShow((string)parameters.searchTerm);
|
||||
Get["music/{searchTerm}"] = parameters => SearchMusic((string)parameters.searchTerm);
|
||||
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 SearchMusic((string)x.searchTerm);
|
||||
Get["music/coverArt/{id}"] = p => GetMusicBrainzCoverArt((string)p.id);
|
||||
|
||||
Get["movie/upcoming"] = parameters => UpcomingMovies();
|
||||
Get["movie/playing"] = parameters => CurrentlyPlayingMovies();
|
||||
Get["movie/upcoming", true] = async (x, ct) => await UpcomingMovies();
|
||||
Get["movie/playing", true] = async (x, ct) => await CurrentlyPlayingMovies();
|
||||
|
||||
Post["request/movie"] = parameters => RequestMovie((int)Request.Form.movieId);
|
||||
Post["request/tv"] = parameters => RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
|
||||
Post["request/album"] = parameters => RequestAlbum((string)Request.Form.albumId);
|
||||
Post["request/movie", true] = async (x, ct) => await RequestMovie((int)Request.Form.movieId);
|
||||
Post["request/tv", true] = async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
|
||||
Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId);
|
||||
|
||||
Post["/notifyuser"] = x => NotifyUser((bool)Request.Form.notify);
|
||||
Get["/notifyuser"] = x => GetUserNotificationSettings();
|
||||
Post["/notifyuser", true] = async (x, ct) => await NotifyUser((bool)Request.Form.notify);
|
||||
Get["/notifyuser", true] = async (x, ct) => await GetUserNotificationSettings();
|
||||
|
||||
Get["/seasons"] = x => GetSeasons();
|
||||
}
|
||||
|
@ -136,87 +136,86 @@ namespace PlexRequests.UI.Modules
|
|||
private IRepository<UsersToNotify> UsersToNotifyRepo { get; }
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private Negotiator RequestLoad()
|
||||
private async Task<Negotiator> RequestLoad()
|
||||
{
|
||||
var settings = PrService.GetSettings();
|
||||
var settings = await PrService.GetSettingsAsync();
|
||||
|
||||
Log.Trace("Loading Index");
|
||||
return View["Search/Index", settings];
|
||||
}
|
||||
|
||||
private Response UpcomingMovies()
|
||||
private async Task<Response> UpcomingMovies()
|
||||
{
|
||||
Log.Trace("Loading upcoming movies");
|
||||
return ProcessMovies(MovieSearchType.Upcoming, string.Empty);
|
||||
return await ProcessMovies(MovieSearchType.Upcoming, string.Empty);
|
||||
}
|
||||
|
||||
private Response CurrentlyPlayingMovies()
|
||||
private async Task<Response> CurrentlyPlayingMovies()
|
||||
{
|
||||
Log.Trace("Loading currently playing movies");
|
||||
return ProcessMovies(MovieSearchType.CurrentlyPlaying, string.Empty);
|
||||
return await ProcessMovies(MovieSearchType.CurrentlyPlaying, string.Empty);
|
||||
}
|
||||
|
||||
private Response SearchMovie(string searchTerm)
|
||||
private async Task<Response> SearchMovie(string searchTerm)
|
||||
{
|
||||
Log.Trace("Searching for Movie {0}", searchTerm);
|
||||
return ProcessMovies(MovieSearchType.Search, searchTerm);
|
||||
return await ProcessMovies(MovieSearchType.Search, searchTerm);
|
||||
}
|
||||
|
||||
private Response ProcessMovies(MovieSearchType searchType, string searchTerm)
|
||||
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
|
||||
{
|
||||
var taskList = new List<Task>();
|
||||
|
||||
var apiMovies = new List<MovieResult>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
{
|
||||
switch (searchType)
|
||||
await Task.Factory.StartNew(
|
||||
() =>
|
||||
{
|
||||
case MovieSearchType.Search:
|
||||
return MovieApi.SearchMovie(searchTerm).Result.Select(x => new MovieResult()
|
||||
{
|
||||
Adult = x.Adult,
|
||||
BackdropPath = x.BackdropPath,
|
||||
GenreIds = x.GenreIds,
|
||||
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();
|
||||
case MovieSearchType.CurrentlyPlaying:
|
||||
return MovieApi.GetCurrentPlayingMovies().Result.ToList();
|
||||
case MovieSearchType.Upcoming:
|
||||
return MovieApi.GetUpcomingMovies().Result.ToList();
|
||||
default:
|
||||
return new List<MovieResult>();
|
||||
}
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
apiMovies = t.Result;
|
||||
}));
|
||||
switch (searchType)
|
||||
{
|
||||
case MovieSearchType.Search:
|
||||
return
|
||||
MovieApi.SearchMovie(searchTerm)
|
||||
.Result.Select(
|
||||
x =>
|
||||
new MovieResult()
|
||||
{
|
||||
Adult = x.Adult,
|
||||
BackdropPath = x.BackdropPath,
|
||||
GenreIds = x.GenreIds,
|
||||
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();
|
||||
case MovieSearchType.CurrentlyPlaying:
|
||||
return MovieApi.GetCurrentPlayingMovies().Result.ToList();
|
||||
case MovieSearchType.Upcoming:
|
||||
return MovieApi.GetUpcomingMovies().Result.ToList();
|
||||
default:
|
||||
return new List<MovieResult>();
|
||||
}
|
||||
}).ContinueWith(
|
||||
(t) =>
|
||||
{
|
||||
apiMovies = t.Result;
|
||||
});
|
||||
|
||||
Dictionary<int, RequestedModel> dbMovies = new Dictionary<int, RequestedModel>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
{
|
||||
return RequestService.GetAll().Where(x => x.Type == RequestType.Movie);
|
||||
var allResults = await RequestService.GetAllAsync();
|
||||
allResults = allResults.Where(x => x.Type == RequestType.Movie);
|
||||
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
var distinctResults = t.Result.DistinctBy(x => x.ProviderId);
|
||||
dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
|
||||
}));
|
||||
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
|
||||
var dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
|
||||
|
||||
Task.WaitAll(taskList.ToArray());
|
||||
|
||||
var cpCached = CpCacher.QueuedIds();
|
||||
var plexMovies = Checker.GetPlexMovies();
|
||||
var settings = PrService.GetSettings();
|
||||
var settings = await PrService.GetSettingsAsync();
|
||||
var viewMovies = new List<SearchMovieViewModel>();
|
||||
foreach (MovieResult movie in apiMovies)
|
||||
{
|
||||
|
@ -272,33 +271,20 @@ namespace PlexRequests.UI.Modules
|
|||
return true;
|
||||
}
|
||||
|
||||
private Response SearchTvShow(string searchTerm)
|
||||
private async Task<Response> SearchTvShow(string searchTerm)
|
||||
{
|
||||
Log.Trace("Searching for TV Show {0}", searchTerm);
|
||||
|
||||
var taskList = new List<Task>();
|
||||
|
||||
var apiTv = new List<TvMazeSearch>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
{
|
||||
return new TvMazeApi().Search(searchTerm);
|
||||
|
||||
}).ContinueWith((t) =>
|
||||
await Task.Factory.StartNew(() => new TvMazeApi().Search(searchTerm)).ContinueWith((t) =>
|
||||
{
|
||||
apiTv = t.Result;
|
||||
}));
|
||||
});
|
||||
|
||||
var dbTv = new Dictionary<int, RequestedModel>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
{
|
||||
return RequestService.GetAll().Where(x => x.Type == RequestType.TvShow);
|
||||
var allResults = await RequestService.GetAllAsync();
|
||||
allResults = allResults.Where(x => x.Type == RequestType.TvShow);
|
||||
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
dbTv = t.Result.ToDictionary(x => x.ProviderId);
|
||||
}));
|
||||
|
||||
Task.WaitAll(taskList.ToArray());
|
||||
var dbTv = allResults.ToDictionary(x => x.ProviderId);
|
||||
|
||||
if (!apiTv.Any())
|
||||
{
|
||||
|
@ -361,31 +347,18 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(viewTv);
|
||||
}
|
||||
|
||||
private Response SearchMusic(string searchTerm)
|
||||
private async Task<Response> SearchMusic(string searchTerm)
|
||||
{
|
||||
var taskList = new List<Task>();
|
||||
|
||||
var apiAlbums = new List<Release>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
{
|
||||
return MusicBrainzApi.SearchAlbum(searchTerm);
|
||||
|
||||
}).ContinueWith((t) =>
|
||||
await Task.Run(() => MusicBrainzApi.SearchAlbum(searchTerm)).ContinueWith((t) =>
|
||||
{
|
||||
apiAlbums = t.Result.releases ?? new List<Release>();
|
||||
}));
|
||||
});
|
||||
|
||||
var dbAlbum = new Dictionary<string, RequestedModel>();
|
||||
taskList.Add(Task.Factory.StartNew(() =>
|
||||
{
|
||||
return RequestService.GetAll().Where(x => x.Type == RequestType.Album);
|
||||
var allResults = await RequestService.GetAllAsync();
|
||||
allResults = allResults.Where(x => x.Type == RequestType.Album);
|
||||
|
||||
}).ContinueWith((t) =>
|
||||
{
|
||||
dbAlbum = t.Result.ToDictionary(x => x.MusicBrainzId);
|
||||
}));
|
||||
|
||||
Task.WaitAll(taskList.ToArray());
|
||||
var dbAlbum = allResults.ToDictionary(x => x.MusicBrainzId);
|
||||
|
||||
var plexAlbums = Checker.GetPlexAlbums();
|
||||
|
||||
|
@ -407,7 +380,7 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime release;
|
||||
DateTimeHelper.CustomParse(a.ReleaseEvents?.FirstOrDefault()?.date, out release);
|
||||
var artist = a.ArtistCredit?.FirstOrDefault()?.artist;
|
||||
if (Checker.IsAlbumAvailable(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist.name))
|
||||
if (Checker.IsAlbumAvailable(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name))
|
||||
{
|
||||
viewA.Available = true;
|
||||
}
|
||||
|
@ -425,27 +398,26 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(viewAlbum);
|
||||
}
|
||||
|
||||
private Response RequestMovie(int movieId)
|
||||
private async Task<Response> RequestMovie(int movieId)
|
||||
{
|
||||
var movieApi = new TheMovieDbApi();
|
||||
var movieInfo = movieApi.GetMovieInformation(movieId).Result;
|
||||
var fullMovieName = $"{movieInfo.Title}{(movieInfo.ReleaseDate.HasValue ? $" ({movieInfo.ReleaseDate.Value.Year})" : string.Empty)}";
|
||||
Log.Trace("Getting movie info from TheMovieDb");
|
||||
Log.Trace(movieInfo.DumpJson);
|
||||
//#if !DEBUG
|
||||
|
||||
var settings = PrService.GetSettings();
|
||||
var settings = await PrService.GetSettingsAsync();
|
||||
|
||||
// check if the movie has already been requested
|
||||
Log.Info("Requesting movie with id {0}", movieId);
|
||||
var existingRequest = RequestService.CheckRequest(movieId);
|
||||
var existingRequest = await RequestService.CheckRequestAsync(movieId);
|
||||
if (existingRequest != null)
|
||||
{
|
||||
// check if the current user is already marked as a requester for this movie, if not, add them
|
||||
if (!existingRequest.UserHasRequested(Username))
|
||||
{
|
||||
existingRequest.RequestedUsers.Add(Username);
|
||||
RequestService.UpdateRequest(existingRequest);
|
||||
await RequestService.UpdateRequestAsync(existingRequest);
|
||||
}
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullMovieName} was successfully added!" : $"{fullMovieName} has already been requested!" });
|
||||
|
@ -461,8 +433,9 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullMovieName} is already in Plex!" });
|
||||
}
|
||||
}
|
||||
catch (ApplicationSettingsException)
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"We could not check if {fullMovieName} is in Plex, are you sure it's correctly setup?" });
|
||||
}
|
||||
//#endif
|
||||
|
@ -473,7 +446,7 @@ namespace PlexRequests.UI.Modules
|
|||
Type = RequestType.Movie,
|
||||
Overview = movieInfo.Overview,
|
||||
ImdbId = movieInfo.ImdbId,
|
||||
PosterPath = "http://image.tmdb.org/t/p/w150/" + movieInfo.PosterPath,
|
||||
PosterPath = "https://image.tmdb.org/t/p/w150/" + movieInfo.PosterPath,
|
||||
Title = movieInfo.Title,
|
||||
ReleaseDate = movieInfo.ReleaseDate ?? DateTime.MinValue,
|
||||
Status = movieInfo.Status,
|
||||
|
@ -484,13 +457,10 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
};
|
||||
|
||||
Log.Trace(settings.DumpJson());
|
||||
if (ShouldAutoApprove(RequestType.Movie, settings))
|
||||
{
|
||||
var cpSettings = CpService.GetSettings();
|
||||
var cpSettings = await CpService.GetSettingsAsync();
|
||||
|
||||
Log.Trace("Settings: ");
|
||||
Log.Trace(cpSettings.DumpJson);
|
||||
if (cpSettings.Enabled)
|
||||
{
|
||||
Log.Info("Adding movie to CP (No approval required)");
|
||||
|
@ -501,8 +471,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
model.Approved = true;
|
||||
Log.Info("Adding movie to database (No approval required)");
|
||||
RequestService.AddRequest(model);
|
||||
|
||||
await RequestService.AddRequestAsync(model);
|
||||
|
||||
if (ShouldSendNotification())
|
||||
{
|
||||
|
@ -513,7 +482,7 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest
|
||||
};
|
||||
NotificationService.Publish(notificationModel);
|
||||
await NotificationService.Publish(notificationModel);
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" });
|
||||
}
|
||||
|
@ -529,7 +498,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
model.Approved = true;
|
||||
Log.Info("Adding movie to database (No approval required)");
|
||||
RequestService.AddRequest(model);
|
||||
await RequestService.AddRequestAsync(model);
|
||||
|
||||
if (ShouldSendNotification())
|
||||
{
|
||||
|
@ -540,7 +509,7 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest
|
||||
};
|
||||
NotificationService.Publish(notificationModel);
|
||||
await NotificationService.Publish(notificationModel);
|
||||
}
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" });
|
||||
|
@ -550,10 +519,10 @@ namespace PlexRequests.UI.Modules
|
|||
try
|
||||
{
|
||||
Log.Info("Adding movie to database");
|
||||
var id = RequestService.AddRequest(model);
|
||||
var id = await RequestService.AddRequestAsync(model);
|
||||
|
||||
var notificationModel = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest };
|
||||
NotificationService.Publish(notificationModel);
|
||||
await NotificationService.Publish(notificationModel);
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" });
|
||||
}
|
||||
|
@ -570,9 +539,8 @@ namespace PlexRequests.UI.Modules
|
|||
/// </summary>
|
||||
/// <param name="showId">The show identifier.</param>
|
||||
/// <param name="seasons">The seasons.</param>
|
||||
/// <param name="notify">if set to <c>true</c> [notify].</param>
|
||||
/// <returns></returns>
|
||||
private Response RequestTvShow(int showId, string seasons)
|
||||
private async Task<Response> RequestTvShow(int showId, string seasons)
|
||||
{
|
||||
var tvApi = new TvMazeApi();
|
||||
|
||||
|
@ -582,18 +550,18 @@ namespace PlexRequests.UI.Modules
|
|||
string fullShowName = $"{showInfo.name} ({firstAir.Year})";
|
||||
//#if !DEBUG
|
||||
|
||||
var settings = PrService.GetSettings();
|
||||
var settings = await PrService.GetSettingsAsync();
|
||||
|
||||
// check if the show has already been requested
|
||||
Log.Info("Requesting tv show with id {0}", showId);
|
||||
var existingRequest = RequestService.CheckRequest(showId);
|
||||
var existingRequest = await RequestService.CheckRequestAsync(showId);
|
||||
if (existingRequest != null)
|
||||
{
|
||||
// check if the current user is already marked as a requester for this show, if not, add them
|
||||
if (!existingRequest.UserHasRequested(Username))
|
||||
{
|
||||
existingRequest.RequestedUsers.Add(Username);
|
||||
RequestService.UpdateRequest(existingRequest);
|
||||
await RequestService.UpdateRequestAsync(existingRequest);
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullShowName} was successfully added!" : $"{fullShowName} has already been requested!" });
|
||||
}
|
||||
|
@ -606,7 +574,7 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullShowName} is already in Plex!" });
|
||||
}
|
||||
}
|
||||
catch (ApplicationSettingsException)
|
||||
catch (Exception)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"We could not check if {fullShowName} is in Plex, are you sure it's correctly setup?" });
|
||||
}
|
||||
|
@ -627,7 +595,7 @@ namespace PlexRequests.UI.Modules
|
|||
RequestedUsers = new List<string> { Username },
|
||||
Issues = IssueState.None,
|
||||
ImdbId = showInfo.externals?.imdb ?? string.Empty,
|
||||
SeasonCount = showInfo.seasonCount
|
||||
SeasonCount = showInfo.seasonCount,
|
||||
};
|
||||
|
||||
var seasonsList = new List<int>();
|
||||
|
@ -645,6 +613,7 @@ namespace PlexRequests.UI.Modules
|
|||
model.SeasonsRequested = "All";
|
||||
break;
|
||||
default:
|
||||
model.SeasonsRequested = seasons;
|
||||
var split = seasons.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var seasonsCount = new int[split.Length];
|
||||
for (var i = 0; i < split.Length; i++)
|
||||
|
@ -661,16 +630,16 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
if (ShouldAutoApprove(RequestType.TvShow, settings))
|
||||
{
|
||||
var sonarrSettings = SonarrService.GetSettings();
|
||||
var sonarrSettings = await SonarrService.GetSettingsAsync();
|
||||
var sender = new TvSender(SonarrApi, SickrageApi);
|
||||
if (sonarrSettings.Enabled)
|
||||
{
|
||||
var result = sender.SendToSonarr(sonarrSettings, model);
|
||||
if (result != null && !string.IsNullOrEmpty(result.title))
|
||||
if (!string.IsNullOrEmpty(result?.title))
|
||||
{
|
||||
model.Approved = true;
|
||||
Log.Debug("Adding tv to database requests (No approval required & Sonarr)");
|
||||
RequestService.AddRequest(model);
|
||||
await RequestService.AddRequestAsync(model);
|
||||
|
||||
if (ShouldSendNotification())
|
||||
{
|
||||
|
@ -681,7 +650,7 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest
|
||||
};
|
||||
NotificationService.Publish(notify1);
|
||||
await NotificationService.Publish(notify1);
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
|
||||
}
|
||||
|
@ -699,7 +668,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
model.Approved = true;
|
||||
Log.Debug("Adding tv to database requests (No approval required & SickRage)");
|
||||
RequestService.AddRequest(model);
|
||||
await RequestService.AddRequestAsync(model);
|
||||
if (ShouldSendNotification())
|
||||
{
|
||||
var notify2 = new NotificationModel
|
||||
|
@ -709,7 +678,7 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest
|
||||
};
|
||||
NotificationService.Publish(notify2);
|
||||
await NotificationService.Publish(notify2);
|
||||
}
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
|
||||
|
@ -717,14 +686,33 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(new JsonResponseModel { Result = false, Message = result?.message != null ? "<b>Message From SickRage: </b>" + result.message : "Something went wrong adding the movie to SickRage! Please check your settings." });
|
||||
}
|
||||
|
||||
if (!srSettings.Enabled && !sonarrSettings.Enabled)
|
||||
{
|
||||
model.Approved = true;
|
||||
Log.Debug("Adding tv to database requests (No approval required) and Sonarr/Sickrage not setup");
|
||||
await RequestService.AddRequestAsync(model);
|
||||
if (ShouldSendNotification())
|
||||
{
|
||||
var notify2 = new NotificationModel
|
||||
{
|
||||
Title = model.Title,
|
||||
User = Username,
|
||||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest
|
||||
};
|
||||
await NotificationService.Publish(notify2);
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
|
||||
}
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "The request of TV Shows is not correctly set up. Please contact your admin." });
|
||||
|
||||
}
|
||||
|
||||
RequestService.AddRequest(model);
|
||||
await RequestService.AddRequestAsync(model);
|
||||
|
||||
var notificationModel = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest };
|
||||
NotificationService.Publish(notificationModel);
|
||||
await NotificationService.Publish(notificationModel);
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
|
||||
}
|
||||
|
@ -735,7 +723,8 @@ namespace PlexRequests.UI.Modules
|
|||
var claims = Context.CurrentUser?.Claims;
|
||||
if (claims != null)
|
||||
{
|
||||
if (claims.Contains(UserClaims.Admin) || claims.Contains(UserClaims.PowerUser))
|
||||
var enumerable = claims as string[] ?? claims.ToArray();
|
||||
if (enumerable.Contains(UserClaims.Admin) || enumerable.Contains(UserClaims.PowerUser))
|
||||
{
|
||||
sendNotification = false; // Don't bother sending a notification if the user is an admin
|
||||
}
|
||||
|
@ -744,10 +733,10 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
|
||||
|
||||
private Response RequestAlbum(string releaseId)
|
||||
private async Task<Response> RequestAlbum(string releaseId)
|
||||
{
|
||||
var settings = PrService.GetSettings();
|
||||
var existingRequest = RequestService.CheckRequest(releaseId);
|
||||
var settings = await PrService.GetSettingsAsync();
|
||||
var existingRequest = await RequestService.CheckRequestAsync(releaseId);
|
||||
Log.Debug("Checking for an existing request");
|
||||
|
||||
if (existingRequest != null)
|
||||
|
@ -758,12 +747,11 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
Log.Debug("Not in the requested list so adding them and updating the request. User: {0}", Username);
|
||||
existingRequest.RequestedUsers.Add(Username);
|
||||
RequestService.UpdateRequest(existingRequest);
|
||||
await RequestService.UpdateRequestAsync(existingRequest);
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{existingRequest.Title} was successfully added!" : $"{existingRequest.Title} has already been requested!" });
|
||||
}
|
||||
|
||||
|
||||
Log.Debug("This is a new request");
|
||||
|
||||
var albumInfo = MusicBrainzApi.GetAlbum(releaseId);
|
||||
|
@ -823,7 +811,7 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
if (!hpSettings.Enabled)
|
||||
{
|
||||
RequestService.AddRequest(model);
|
||||
await RequestService.AddRequestAsync(model);
|
||||
return
|
||||
Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
|
@ -833,9 +821,9 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
|
||||
var sender = new HeadphonesSender(HeadphonesApi, hpSettings, RequestService);
|
||||
sender.AddAlbum(model).Wait();
|
||||
await sender.AddAlbum(model);
|
||||
model.Approved = true;
|
||||
RequestService.AddRequest(model);
|
||||
await RequestService.AddRequestAsync(model);
|
||||
|
||||
if (ShouldSendNotification())
|
||||
{
|
||||
|
@ -846,7 +834,7 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest
|
||||
};
|
||||
NotificationService.Publish(notify2);
|
||||
await NotificationService.Publish(notify2);
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -866,9 +854,9 @@ namespace PlexRequests.UI.Modules
|
|||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest
|
||||
};
|
||||
NotificationService.Publish(notify2);
|
||||
await NotificationService.Publish(notify2);
|
||||
}
|
||||
var result = RequestService.AddRequest(model);
|
||||
await RequestService.AddRequestAsync(model);
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = true,
|
||||
|
@ -909,20 +897,22 @@ namespace PlexRequests.UI.Modules
|
|||
}
|
||||
}
|
||||
|
||||
private Response NotifyUser(bool notify)
|
||||
private async Task<Response> NotifyUser(bool notify)
|
||||
{
|
||||
var auth = Auth.GetSettings().UserAuthentication;
|
||||
var email = EmailNotificationSettings.GetSettings().EnableUserEmailNotifications;
|
||||
var authSettings = await Auth.GetSettingsAsync();
|
||||
var auth = authSettings.UserAuthentication;
|
||||
var emailSettings = await EmailNotificationSettings.GetSettingsAsync();
|
||||
var email = emailSettings.EnableUserEmailNotifications;
|
||||
if (!auth)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, but this functionality is currently only for users with Plex accounts"});
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, but this functionality is currently only for users with Plex accounts" });
|
||||
}
|
||||
if (!email)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, but your administrator has not yet enabled this functionality." });
|
||||
}
|
||||
var username = Username;
|
||||
var originalList = UsersToNotifyRepo.GetAll();
|
||||
var originalList = await UsersToNotifyRepo.GetAllAsync();
|
||||
if (!notify)
|
||||
{
|
||||
if (originalList == null)
|
||||
|
@ -932,7 +922,7 @@ namespace PlexRequests.UI.Modules
|
|||
var userToRemove = originalList.FirstOrDefault(x => x.Username == username);
|
||||
if (userToRemove != null)
|
||||
{
|
||||
UsersToNotifyRepo.Delete(userToRemove);
|
||||
await UsersToNotifyRepo.DeleteAsync(userToRemove);
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||
}
|
||||
|
@ -941,7 +931,7 @@ namespace PlexRequests.UI.Modules
|
|||
if (originalList == null)
|
||||
{
|
||||
var userModel = new UsersToNotify { Username = username };
|
||||
var insertResult = UsersToNotifyRepo.Insert(userModel);
|
||||
var insertResult = await UsersToNotifyRepo.InsertAsync(userModel);
|
||||
return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Could not save, please try again" });
|
||||
}
|
||||
|
||||
|
@ -953,15 +943,16 @@ namespace PlexRequests.UI.Modules
|
|||
else
|
||||
{
|
||||
var userModel = new UsersToNotify { Username = username };
|
||||
var insertResult = UsersToNotifyRepo.Insert(userModel);
|
||||
var insertResult = await UsersToNotifyRepo.InsertAsync(userModel);
|
||||
return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Could not save, please try again" });
|
||||
}
|
||||
|
||||
}
|
||||
private Response GetUserNotificationSettings()
|
||||
private async Task<Response> GetUserNotificationSettings()
|
||||
{
|
||||
var retval = UsersToNotifyRepo.GetAll().FirstOrDefault(x => x.Username == Username);
|
||||
return Response.AsJson(retval != null);
|
||||
var all = await UsersToNotifyRepo.GetAllAsync();
|
||||
var retVal = all.FirstOrDefault(x => x.Username == Username);
|
||||
return Response.AsJson(retVal != null);
|
||||
}
|
||||
|
||||
private Response GetSeasons()
|
||||
|
|
|
@ -46,24 +46,24 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(users);
|
||||
}
|
||||
|
||||
private Response CreateUser(string username, string password, string claims)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel
|
||||
{
|
||||
Result = true,
|
||||
Message = "Please enter in a valid Username and Password"
|
||||
});
|
||||
}
|
||||
var user = UserMapper.CreateUser(username, password, new string[] {claims});
|
||||
if (user.HasValue)
|
||||
{
|
||||
return Response.AsJson(new JsonResponseModel {Result = true});
|
||||
}
|
||||
//private Response CreateUser(string username, string password, string claims)
|
||||
//{
|
||||
// if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||
// {
|
||||
// return Response.AsJson(new JsonResponseModel
|
||||
// {
|
||||
// Result = true,
|
||||
// Message = "Please enter in a valid Username and Password"
|
||||
// });
|
||||
// }
|
||||
// var user = UserMapper.CreateUser(username, password, new string[] {claims});
|
||||
// if (user.HasValue)
|
||||
// {
|
||||
// return Response.AsJson(new JsonResponseModel {Result = true});
|
||||
// }
|
||||
|
||||
return Response.AsJson(new JsonResponseModel {Result = false, Message = "Could not save user"});
|
||||
}
|
||||
// return Response.AsJson(new JsonResponseModel {Result = false, Message = "Could not save user"});
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -210,7 +210,15 @@
|
|||
<Content Include="Content\bootstrap-notify.min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Themes\OriginalBootstrap.css">
|
||||
<Content Include="Content\base.css">
|
||||
<DependentUpon>base.scss</DependentUpon>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\base.min.css">
|
||||
<DependentUpon>base.css</DependentUpon>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\bootstrap.css">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Compile Include="Models\JsonResponseModel.cs" />
|
||||
|
@ -286,22 +294,21 @@
|
|||
<Content Include="Content\swagger\underscore-min.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Themes\OriginalBootstrapCustom.css">
|
||||
<DependentUpon>OriginalBootstrapCustom.scss</DependentUpon>
|
||||
<Content Include="Content\Themes\original.css">
|
||||
<DependentUpon>original.scss</DependentUpon>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Themes\OriginalBootstrapCustom.min.css">
|
||||
<DependentUpon>OriginalBootstrapCustom.css</DependentUpon>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<Content Include="Content\Themes\original.min.css">
|
||||
<DependentUpon>original.css</DependentUpon>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Themes\PlexBootstrap.css">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<Content Include="Content\Themes\plex.css">
|
||||
<DependentUpon>plex.scss</DependentUpon>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\Themes\PlexBootstrapCustom.css">
|
||||
<DependentUpon>PlexBootstrapCustom.scss</DependentUpon>
|
||||
</Content>
|
||||
<Content Include="Content\Themes\PlexBootstrapCustom.min.css">
|
||||
<DependentUpon>PlexBootstrapCustom.css</DependentUpon>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<Content Include="Content\Themes\plex.min.css">
|
||||
<DependentUpon>plex.css</DependentUpon>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Views\ApiDocs\index.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
@ -387,8 +394,9 @@
|
|||
<None Include="Content\awesome-bootstrap-checkbox.scss">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Content\Themes\PlexBootstrapCustom.scss" />
|
||||
<None Include="Content\Themes\OriginalBootstrapCustom.scss" />
|
||||
<None Include="Content\base.scss" />
|
||||
<None Include="Content\Themes\original.scss" />
|
||||
<None Include="Content\Themes\plex.scss" />
|
||||
<Content Include="Content\pace.min.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
<p class="form-group">Current users that are allowed to authenticate: </p>
|
||||
|
||||
<div class="form-group">
|
||||
<select id="users" multiple="" class="form-control-custom "></select>
|
||||
<select id="users" multiple="" class="form-control-custom" style="height: 180px;"></select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
|
@ -161,7 +161,7 @@
|
|||
$('#users').append("<option>Error!</option>");
|
||||
return;
|
||||
}
|
||||
if (response.users.length > 1) {
|
||||
if (response.users.length > 0) {
|
||||
$(response.users).each(function () {
|
||||
$('#users').append("<option>" + this + "</option>");
|
||||
});
|
||||
|
|
|
@ -54,10 +54,10 @@
|
|||
var dots = new Array(count % 10).join('.');
|
||||
document.getElementById('autoUpdate').innerHTML = "Updating" + dots;
|
||||
}, 1000);
|
||||
var url = createBaseUrl(base, "autoupdate");
|
||||
|
||||
$.ajax({
|
||||
type: "Post",
|
||||
url: url,
|
||||
url: "autoupdate",
|
||||
data: { url: "@Model.DownloadUri" },
|
||||
dataType: "json",
|
||||
error: function () {
|
||||
|
|
|
@ -35,19 +35,22 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="pull-right">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group btn-group-separated">
|
||||
@if (Context.CurrentUser.IsAuthenticated()) //TODO replace with IsAdmin
|
||||
{
|
||||
@if (Model.SearchForMovies)
|
||||
{
|
||||
<button id="deleteMovies" class="btn btn-warning-outline delete-category" type="submit"><i class="fa fa-trash"></i> Delete Movies</button>
|
||||
<button id="approveMovies" class="btn btn-success-outline approve-category" type="submit"><i class="fa fa-plus"></i> Approve Movies</button>
|
||||
}
|
||||
@if (Model.SearchForTvShows)
|
||||
{
|
||||
<button id="deleteTVShows" class="btn btn-warning-outline delete-category" type="submit" style="display: none;"><i class="fa fa-trash"></i> Delete TV Shows</button>
|
||||
<button id="approveTVShows" class="btn btn-success-outline approve-category" type="submit" style="display: none;"><i class="fa fa-plus"></i> Approve TV Shows</button>
|
||||
}
|
||||
@if (Model.SearchForMusic)
|
||||
{
|
||||
<button id="deleteMusics" class="btn btn-warning-outline delete-category" type="submit" style="display: none;"><i class="fa fa-trash"></i> Delete Music</button>
|
||||
<button id="approveMusic" class="btn btn-success-outline approve-category" type="submit" style="display: none;"><i class="fa fa-plus"></i> Approve Music</button>
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +135,7 @@
|
|||
<div class="col-sm-2">
|
||||
{{#if_eq type "movie"}}
|
||||
{{#if posterPath}}
|
||||
<img class="img-responsive" src="http://image.tmdb.org/t/p/w150/{{posterPath}}" alt="poster">
|
||||
<img class="img-responsive" src="https://image.tmdb.org/t/p/w150/{{posterPath}}" alt="poster">
|
||||
{{/if}}
|
||||
{{/if_eq}}
|
||||
{{#if_eq type "tv"}}
|
||||
|
@ -169,7 +172,7 @@
|
|||
{{/if_eq}}
|
||||
</div>
|
||||
{{#if_eq type "tv"}}
|
||||
<div>Series Requested: {{seriesRequested}}</div>
|
||||
<div>Seasons Requested: {{seriesRequested}}</div>
|
||||
{{/if_eq}}
|
||||
{{#if requestedUsers}}
|
||||
<div>Requested By: {{requestedUsers}}</div>
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
|
||||
{{#if_eq type "movie"}}
|
||||
{{#if posterPath}}
|
||||
<img class="img-responsive" src="http://image.tmdb.org/t/p/w150/{{posterPath}}" alt="poster">
|
||||
<img class="img-responsive" src="https://image.tmdb.org/t/p/w150/{{posterPath}}" alt="poster">
|
||||
{{/if}}
|
||||
{{/if_eq}}
|
||||
{{#if_eq type "tv"}}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
[
|
||||
{
|
||||
"outputFile": "Content/custom.css",
|
||||
"inputFile": "Content/custom.scss"
|
||||
},
|
||||
{
|
||||
"outputFile": "Content/pace.css",
|
||||
"inputFile": "Content/pace.scss"
|
||||
|
@ -18,5 +14,17 @@
|
|||
{
|
||||
"outputFile": "Content/Themes/PlexBootstrapCustom.css",
|
||||
"inputFile": "Content/Themes/PlexBootstrapCustom.scss"
|
||||
},
|
||||
{
|
||||
"outputFile": "Content/base.css",
|
||||
"inputFile": "Content/base.scss"
|
||||
},
|
||||
{
|
||||
"outputFile": "Content/Themes/plex.css",
|
||||
"inputFile": "Content/Themes/plex.scss"
|
||||
},
|
||||
{
|
||||
"outputFile": "Content/Themes/original.css",
|
||||
"inputFile": "Content/Themes/original.scss"
|
||||
}
|
||||
]
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.UI", "PlexRequests.UI\PlexRequests.UI.csproj", "{68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}"
|
||||
|
@ -35,20 +35,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.Services.Tests
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.Updater", "PlexRequests.Updater\PlexRequests.Updater.csproj", "{EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.Helpers.Tests", "PlexRequests.Helpers.Tests\PlexRequests.Helpers.Tests.csproj", "{0E6395D3-B074-49E8-898D-0EB99E507E0E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
@ -57,26 +51,38 @@ Global
|
|||
{8CB8D235-2674-442D-9C6A-35FCAEEB160D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8CB8D235-2674-442D-9C6A-35FCAEEB160D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8CB8D235-2674-442D-9C6A-35FCAEEB160D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{95834072-A675-415D-AA8F-877C91623810}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{95834072-A675-415D-AA8F-877C91623810}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{95834072-A675-415D-AA8F-877C91623810}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{95834072-A675-415D-AA8F-877C91623810}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{92433867-2B7B-477B-A566-96C382427525}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
@ -85,12 +91,10 @@ Global
|
|||
{EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{0E6395D3-B074-49E8-898D-0EB99E507E0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0E6395D3-B074-49E8-898D-0EB99E507E0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0E6395D3-B074-49E8-898D-0EB99E507E0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0E6395D3-B074-49E8-898D-0EB99E507E0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -3,9 +3,9 @@ configuration: Release
|
|||
assembly_info:
|
||||
patch: true
|
||||
file: '**\AssemblyInfo.*'
|
||||
assembly_version: '1.7.4'
|
||||
assembly_version: '1.7.5'
|
||||
assembly_file_version: '{version}'
|
||||
assembly_informational_version: '1.7.4'
|
||||
assembly_informational_version: '1.7.5'
|
||||
before_build:
|
||||
- cmd: appveyor-retry nuget restore
|
||||
build:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue