mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-31 12:00:06 -07:00
commit
14d4f6f098
64 changed files with 1863 additions and 233 deletions
|
@ -33,7 +33,8 @@ namespace PlexRequests.Api.Interfaces
|
||||||
{
|
{
|
||||||
public interface ICouchPotatoApi
|
public interface ICouchPotatoApi
|
||||||
{
|
{
|
||||||
bool AddMovie(string imdbid, string apiKey, string title, Uri baseUrl);
|
bool AddMovie(string imdbid, string apiKey, string title, Uri baseUrl, string profileID = default(string));
|
||||||
CouchPotatoStatus GetStatus(Uri url, string apiKey);
|
CouchPotatoStatus GetStatus(Uri url, string apiKey);
|
||||||
|
CouchPotatoProfiles GetProfiles(Uri url, string apiKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,6 +37,6 @@ namespace PlexRequests.Api.Interfaces
|
||||||
PlexFriends GetUsers(string authToken);
|
PlexFriends GetUsers(string authToken);
|
||||||
PlexSearch SearchContent(string authToken, string searchTerm, Uri plexFullHost);
|
PlexSearch SearchContent(string authToken, string searchTerm, Uri plexFullHost);
|
||||||
PlexStatus GetStatus(string authToken, Uri uri);
|
PlexStatus GetStatus(string authToken, Uri uri);
|
||||||
|
PlexAccount GetAccount(string authToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
40
PlexRequests.Api.Interfaces/ISickRageApi.cs
Normal file
40
PlexRequests.Api.Interfaces/ISickRageApi.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: ISickRageApi.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 PlexRequests.Api.Models.SickRage;
|
||||||
|
|
||||||
|
namespace PlexRequests.Api.Interfaces
|
||||||
|
{
|
||||||
|
public interface ISickRageApi
|
||||||
|
{
|
||||||
|
SickRageTvAdd AddSeries(int tvdbId, bool latest, string quality, string apiKey,
|
||||||
|
Uri baseUrl);
|
||||||
|
|
||||||
|
SickRagePing Ping(string apiKey, Uri baseUrl);
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,7 @@
|
||||||
<Compile Include="ICouchPotatoApi.cs" />
|
<Compile Include="ICouchPotatoApi.cs" />
|
||||||
<Compile Include="IPlexApi.cs" />
|
<Compile Include="IPlexApi.cs" />
|
||||||
<Compile Include="IPushbulletApi.cs" />
|
<Compile Include="IPushbulletApi.cs" />
|
||||||
|
<Compile Include="ISickRageApi.cs" />
|
||||||
<Compile Include="ISonarrApi.cs" />
|
<Compile Include="ISonarrApi.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
53
PlexRequests.Api.Models/Movie/CouchPotatoProfiles.cs
Normal file
53
PlexRequests.Api.Models/Movie/CouchPotatoProfiles.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: CouchPotatoProfiles.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.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PlexRequests.Api.Models.Movie
|
||||||
|
{
|
||||||
|
public class ProfileList
|
||||||
|
{
|
||||||
|
public bool core { get; set; }
|
||||||
|
public string _rev { get; set; }
|
||||||
|
public List<bool> finish { get; set; }
|
||||||
|
public List<string> qualities { get; set; }
|
||||||
|
public string _id { get; set; }
|
||||||
|
public string _t { get; set; }
|
||||||
|
public string label { get; set; }
|
||||||
|
public int minimum_score { get; set; }
|
||||||
|
public List<int> stop_after { get; set; }
|
||||||
|
public List<int> wait_for { get; set; }
|
||||||
|
public int order { get; set; }
|
||||||
|
public List<object> __invalid_name__3d { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CouchPotatoProfiles
|
||||||
|
{
|
||||||
|
public List<ProfileList> list { get; set; }
|
||||||
|
public bool success { get; set; }
|
||||||
|
}
|
||||||
|
}
|
22
PlexRequests.Api.Models/Plex/PlexAccount.cs
Normal file
22
PlexRequests.Api.Models/Plex/PlexAccount.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace PlexRequests.Api.Models.Plex
|
||||||
|
{
|
||||||
|
[XmlRoot(ElementName = "user")]
|
||||||
|
public class PlexAccount
|
||||||
|
{
|
||||||
|
[XmlAttribute(AttributeName = "id")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "username")]
|
||||||
|
public string Username { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "email")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "authenticationToken")]
|
||||||
|
public string AuthToken { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -238,9 +238,79 @@ namespace PlexRequests.Api.Models.Plex
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "Directory")]
|
||||||
|
public class Directory1
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "Genre")]
|
||||||
|
public List<Genre> Genre { get; set; }
|
||||||
|
[XmlElement(ElementName = "Role")]
|
||||||
|
public List<Role> Role { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "allowSync")]
|
||||||
|
public string AllowSync { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "librarySectionID")]
|
||||||
|
public string LibrarySectionID { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "librarySectionTitle")]
|
||||||
|
public string LibrarySectionTitle { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "librarySectionUUID")]
|
||||||
|
public string LibrarySectionUUID { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "personal")]
|
||||||
|
public string Personal { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "sourceTitle")]
|
||||||
|
public string SourceTitle { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "ratingKey")]
|
||||||
|
public string RatingKey { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "key")]
|
||||||
|
public string Key { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "studio")]
|
||||||
|
public string Studio { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "title")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "contentRating")]
|
||||||
|
public string ContentRating { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "summary")]
|
||||||
|
public string Summary { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "index")]
|
||||||
|
public string Index { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "rating")]
|
||||||
|
public string Rating { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "viewCount")]
|
||||||
|
public string ViewCount { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "lastViewedAt")]
|
||||||
|
public string LastViewedAt { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "year")]
|
||||||
|
public string Year { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "thumb")]
|
||||||
|
public string Thumb { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "art")]
|
||||||
|
public string Art { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "banner")]
|
||||||
|
public string Banner { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "theme")]
|
||||||
|
public string Theme { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "duration")]
|
||||||
|
public string Duration { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "originallyAvailableAt")]
|
||||||
|
public string OriginallyAvailableAt { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "leafCount")]
|
||||||
|
public string LeafCount { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "viewedLeafCount")]
|
||||||
|
public string ViewedLeafCount { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "childCount")]
|
||||||
|
public string ChildCount { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "addedAt")]
|
||||||
|
public string AddedAt { get; set; }
|
||||||
|
[XmlAttribute(AttributeName = "updatedAt")]
|
||||||
|
public string UpdatedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[XmlRoot(ElementName = "MediaContainer")]
|
[XmlRoot(ElementName = "MediaContainer")]
|
||||||
public class PlexSearch
|
public class PlexSearch
|
||||||
{
|
{
|
||||||
|
[XmlElement(ElementName = "Directory")]
|
||||||
|
public Directory1 Directory { get; set; }
|
||||||
[XmlElement(ElementName = "Video")]
|
[XmlElement(ElementName = "Video")]
|
||||||
public List<Video> Video { get; set; }
|
public List<Video> Video { get; set; }
|
||||||
[XmlElement(ElementName = "Provider")]
|
[XmlElement(ElementName = "Provider")]
|
||||||
|
|
|
@ -46,9 +46,11 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Movie\CouchPotatoAdd.cs" />
|
<Compile Include="Movie\CouchPotatoAdd.cs" />
|
||||||
|
<Compile Include="Movie\CouchPotatoProfiles.cs" />
|
||||||
<Compile Include="Movie\CouchPotatoStatus.cs" />
|
<Compile Include="Movie\CouchPotatoStatus.cs" />
|
||||||
<Compile Include="Notifications\PushbulletPush.cs" />
|
<Compile Include="Notifications\PushbulletPush.cs" />
|
||||||
<Compile Include="Notifications\PushbulletResponse.cs" />
|
<Compile Include="Notifications\PushbulletResponse.cs" />
|
||||||
|
<Compile Include="Plex\PlexAccount.cs" />
|
||||||
<Compile Include="Plex\PlexAuthentication.cs" />
|
<Compile Include="Plex\PlexAuthentication.cs" />
|
||||||
<Compile Include="Plex\PlexError.cs" />
|
<Compile Include="Plex\PlexError.cs" />
|
||||||
<Compile Include="Plex\PlexFriends.cs" />
|
<Compile Include="Plex\PlexFriends.cs" />
|
||||||
|
@ -56,10 +58,15 @@
|
||||||
<Compile Include="Plex\PlexStatus.cs" />
|
<Compile Include="Plex\PlexStatus.cs" />
|
||||||
<Compile Include="Plex\PlexUserRequest.cs" />
|
<Compile Include="Plex\PlexUserRequest.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="SickRage\SickRagePing.cs" />
|
||||||
|
<Compile Include="SickRage\SickRageStatus.cs" />
|
||||||
|
<Compile Include="SickRage\SickRageTvAdd.cs" />
|
||||||
<Compile Include="Sonarr\SonarrAddSeries.cs" />
|
<Compile Include="Sonarr\SonarrAddSeries.cs" />
|
||||||
<Compile Include="Sonarr\SonarrProfile.cs" />
|
<Compile Include="Sonarr\SonarrProfile.cs" />
|
||||||
<Compile Include="Sonarr\SystemStatus.cs" />
|
<Compile Include="Sonarr\SystemStatus.cs" />
|
||||||
<Compile Include="Tv\Authentication.cs" />
|
<Compile Include="Tv\Authentication.cs" />
|
||||||
|
<Compile Include="Tv\TvMazeSearch.cs" />
|
||||||
|
<Compile Include="Tv\TVMazeShow.cs" />
|
||||||
<Compile Include="Tv\TvSearchResult.cs" />
|
<Compile Include="Tv\TvSearchResult.cs" />
|
||||||
<Compile Include="Tv\TvShow.cs" />
|
<Compile Include="Tv\TvShow.cs" />
|
||||||
<Compile Include="Tv\TvShowImages.cs" />
|
<Compile Include="Tv\TvShowImages.cs" />
|
||||||
|
|
40
PlexRequests.Api.Models/SickRage/SickRagePing.cs
Normal file
40
PlexRequests.Api.Models/SickRage/SickRagePing.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: SickRagePing.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
// ************************************************************************/
|
||||||
|
#endregion
|
||||||
|
namespace PlexRequests.Api.Models.SickRage
|
||||||
|
{
|
||||||
|
public class SickRagePingData
|
||||||
|
{
|
||||||
|
public int pid { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SickRagePing
|
||||||
|
{
|
||||||
|
public SickRagePingData data { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
public string result { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
#region Copyright
|
#region Copyright
|
||||||
// /************************************************************************
|
// /************************************************************************
|
||||||
// Copyright (c) 2016 Jamie Rees
|
// Copyright (c) 2016 Jamie Rees
|
||||||
// File: SettingsModel.cs
|
// File: SickRageStatus.cs
|
||||||
// Created By: Jamie Rees
|
// Created By: Jamie Rees
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
@ -24,15 +24,12 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
using Dapper.Contrib.Extensions;
|
namespace PlexRequests.Api.Models.SickRage
|
||||||
|
|
||||||
namespace PlexRequests.Store
|
|
||||||
{
|
{
|
||||||
[Table("Settings")]
|
public static class SickRageStatus
|
||||||
public class SettingsModel : Entity
|
|
||||||
{
|
{
|
||||||
public int Port { get; set; }
|
public const string Wanted = "wanted";
|
||||||
public bool UserAuthentication { get; set; }
|
public const string Skipped = "skipped";
|
||||||
public string PlexAuthToken { get; set; }
|
public const string Ignored = "Ignored";
|
||||||
}
|
}
|
||||||
}
|
}
|
41
PlexRequests.Api.Models/SickRage/SickRageTvAdd.cs
Normal file
41
PlexRequests.Api.Models/SickRage/SickRageTvAdd.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: SickRageTvAdd.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
// ************************************************************************/
|
||||||
|
#endregion
|
||||||
|
namespace PlexRequests.Api.Models.SickRage
|
||||||
|
{
|
||||||
|
public class SickRageTvAddData
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SickRageTvAdd
|
||||||
|
{
|
||||||
|
public SickRageTvAddData data { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
public string result { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
PlexRequests.Api.Models/Tv/TVMazeShow.cs
Normal file
27
PlexRequests.Api.Models/Tv/TVMazeShow.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PlexRequests.Api.Models.Tv
|
||||||
|
{
|
||||||
|
public class TvMazeShow
|
||||||
|
{
|
||||||
|
public int id { get; set; }
|
||||||
|
public string url { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public string language { get; set; }
|
||||||
|
public List<string> genres { get; set; }
|
||||||
|
public string status { get; set; }
|
||||||
|
public int runtime { get; set; }
|
||||||
|
public string premiered { get; set; }
|
||||||
|
public Schedule schedule { get; set; }
|
||||||
|
public Rating rating { get; set; }
|
||||||
|
public int weight { get; set; }
|
||||||
|
public Network network { get; set; }
|
||||||
|
public object webChannel { get; set; }
|
||||||
|
public Externals externals { get; set; }
|
||||||
|
public Image image { get; set; }
|
||||||
|
public string summary { get; set; }
|
||||||
|
public int updated { get; set; }
|
||||||
|
public Links _links { get; set; }
|
||||||
|
}
|
||||||
|
}
|
97
PlexRequests.Api.Models/Tv/TvMazeSearch.cs
Normal file
97
PlexRequests.Api.Models/Tv/TvMazeSearch.cs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PlexRequests.Api.Models.Tv
|
||||||
|
{
|
||||||
|
public class Schedule
|
||||||
|
{
|
||||||
|
public string time { get; set; }
|
||||||
|
public List<object> days { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Rating
|
||||||
|
{
|
||||||
|
public double? average { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Country
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
public string code { get; set; }
|
||||||
|
public string timezone { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Network
|
||||||
|
{
|
||||||
|
public int id { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public Country country { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Externals
|
||||||
|
{
|
||||||
|
public int? tvrage { get; set; }
|
||||||
|
public int? thetvdb { get; set; }
|
||||||
|
public string imdb { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Image
|
||||||
|
{
|
||||||
|
public string medium { get; set; }
|
||||||
|
public string original { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Self
|
||||||
|
{
|
||||||
|
public string href { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Previousepisode
|
||||||
|
{
|
||||||
|
public string href { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Nextepisode
|
||||||
|
{
|
||||||
|
public string href { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Links
|
||||||
|
{
|
||||||
|
public Self self { get; set; }
|
||||||
|
public Previousepisode previousepisode { get; set; }
|
||||||
|
public Nextepisode nextepisode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Show
|
||||||
|
{
|
||||||
|
public int id { get; set; }
|
||||||
|
public string url { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
public string language { get; set; }
|
||||||
|
public List<object> genres { get; set; }
|
||||||
|
public string status { get; set; }
|
||||||
|
public int? runtime { get; set; }
|
||||||
|
public string premiered { get; set; }
|
||||||
|
public Schedule schedule { get; set; }
|
||||||
|
public Rating rating { get; set; }
|
||||||
|
public int weight { get; set; }
|
||||||
|
public Network network { get; set; }
|
||||||
|
public object webChannel { get; set; }
|
||||||
|
public Externals externals { get; set; }
|
||||||
|
public Image image { get; set; }
|
||||||
|
public string summary { get; set; }
|
||||||
|
public int updated { get; set; }
|
||||||
|
public Links _links { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TvMazeSearch
|
||||||
|
{
|
||||||
|
public double score { get; set; }
|
||||||
|
public Show show { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,13 +98,13 @@ namespace PlexRequests.Api
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
var json = JsonConvert.DeserializeObject<T>(response.Content);
|
var json = JsonConvert.DeserializeObject<T>(response.Content);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Fatal(e);
|
Log.Fatal(e);
|
||||||
|
Log.Info(response.Content);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,17 @@ namespace PlexRequests.Api
|
||||||
private ApiRequest Api { get; set; }
|
private ApiRequest Api { get; set; }
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public bool AddMovie(string imdbid, string apiKey, string title, Uri baseUrl)
|
public bool AddMovie(string imdbid, string apiKey, string title, Uri baseUrl, string profileId = default(string))
|
||||||
{
|
{
|
||||||
var request = new RestRequest { Resource = "/api/{apikey}/movie.add?title={title}&identifier={imdbid}" };
|
RestRequest request;
|
||||||
|
request = string.IsNullOrEmpty(profileId)
|
||||||
|
? new RestRequest {Resource = "/api/{apikey}/movie.add?title={title}&identifier={imdbid}"}
|
||||||
|
: new RestRequest { Resource = "/api/{apikey}/movie.add?title={title}&identifier={imdbid}&profile_id={profileId}" };
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(profileId))
|
||||||
|
{
|
||||||
|
request.AddUrlSegment("profileId", profileId);
|
||||||
|
}
|
||||||
|
|
||||||
request.AddUrlSegment("apikey", apiKey);
|
request.AddUrlSegment("apikey", apiKey);
|
||||||
request.AddUrlSegment("imdbid", imdbid);
|
request.AddUrlSegment("imdbid", imdbid);
|
||||||
|
@ -93,5 +101,19 @@ namespace PlexRequests.Api
|
||||||
|
|
||||||
return Api.Execute<CouchPotatoStatus>(request,url);
|
return Api.Execute<CouchPotatoStatus>(request,url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CouchPotatoProfiles GetProfiles(Uri url, string apiKey)
|
||||||
|
{
|
||||||
|
Log.Trace("Getting CP Profiles, ApiKey = {0}", apiKey);
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Resource = "api/{apikey}/profile.list/",
|
||||||
|
Method = Method.GET
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddUrlSegment("apikey", apiKey);
|
||||||
|
|
||||||
|
return Api.Execute<CouchPotatoProfiles>(request, url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -134,6 +134,25 @@ namespace PlexRequests.Api
|
||||||
|
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PlexAccount GetAccount(string authToken)
|
||||||
|
{
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Method = Method.GET,
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddHeader("X-Plex-Client-Identifier", "Test213");
|
||||||
|
request.AddHeader("X-Plex-Product", "Request Plex");
|
||||||
|
request.AddHeader("X-Plex-Version", Version);
|
||||||
|
request.AddHeader("X-Plex-Token", authToken);
|
||||||
|
request.AddHeader("Content-Type", "application/xml");
|
||||||
|
|
||||||
|
var api = new ApiRequest();
|
||||||
|
var account = api.ExecuteXml<PlexAccount>(request, new Uri("https://plex.tv/users/account"));
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Mocks\MockSonarrApi.cs" />
|
<Compile Include="Mocks\MockSonarrApi.cs" />
|
||||||
<Compile Include="PushbulletApi.cs" />
|
<Compile Include="PushbulletApi.cs" />
|
||||||
|
<Compile Include="SickrageApi.cs" />
|
||||||
<Compile Include="SonarrApi.cs" />
|
<Compile Include="SonarrApi.cs" />
|
||||||
<Compile Include="CouchPotatoApi.cs" />
|
<Compile Include="CouchPotatoApi.cs" />
|
||||||
<Compile Include="MovieBase.cs" />
|
<Compile Include="MovieBase.cs" />
|
||||||
|
@ -81,6 +82,8 @@
|
||||||
<Compile Include="TvBase.cs" />
|
<Compile Include="TvBase.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="TheTvDbApi.cs" />
|
<Compile Include="TheTvDbApi.cs" />
|
||||||
|
<Compile Include="TvMazeApi.cs" />
|
||||||
|
<Compile Include="TvMazeBase.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
|
91
PlexRequests.Api/SickrageApi.cs
Normal file
91
PlexRequests.Api/SickrageApi.cs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#region Copyright
|
||||||
|
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: CouchPotatoApi.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 NLog;
|
||||||
|
using PlexRequests.Api.Interfaces;
|
||||||
|
using PlexRequests.Api.Models.SickRage;
|
||||||
|
using RestSharp;
|
||||||
|
|
||||||
|
namespace PlexRequests.Api
|
||||||
|
{
|
||||||
|
public class SickrageApi : ISickRageApi
|
||||||
|
{
|
||||||
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
public SickrageApi()
|
||||||
|
{
|
||||||
|
Api = new ApiRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiRequest Api { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public SickRageTvAdd AddSeries(int tvdbId, bool latest, string quality, string apiKey,
|
||||||
|
Uri baseUrl)
|
||||||
|
{
|
||||||
|
string status;
|
||||||
|
var futureStatus = SickRageStatus.Wanted;
|
||||||
|
|
||||||
|
status = latest ? SickRageStatus.Skipped : SickRageStatus.Wanted;
|
||||||
|
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Resource = "/api/{apiKey}/?cmd=show.addnew",
|
||||||
|
Method = Method.GET
|
||||||
|
};
|
||||||
|
request.AddUrlSegment("apiKey", apiKey);
|
||||||
|
request.AddQueryParameter("tvdbid", tvdbId.ToString());
|
||||||
|
request.AddQueryParameter("status", status);
|
||||||
|
request.AddQueryParameter("future_status", futureStatus);
|
||||||
|
if (!quality.Equals("default", StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
request.AddQueryParameter("initial", quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = Api.Execute<SickRageTvAdd>(request, baseUrl);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SickRagePing Ping(string apiKey, Uri baseUrl)
|
||||||
|
{
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Resource = "/api/{apiKey}/?cmd=sb.ping",
|
||||||
|
Method = Method.GET
|
||||||
|
};
|
||||||
|
|
||||||
|
request.AddUrlSegment("apiKey", apiKey);
|
||||||
|
var obj = Api.ExecuteJson<SickRagePing>(request, baseUrl);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
PlexRequests.Api/TvMazeApi.cs
Normal file
86
PlexRequests.Api/TvMazeApi.cs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: TvMazeApi.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 NLog;
|
||||||
|
|
||||||
|
using PlexRequests.Api.Models.Tv;
|
||||||
|
|
||||||
|
using RestSharp;
|
||||||
|
|
||||||
|
namespace PlexRequests.Api
|
||||||
|
{
|
||||||
|
public class TvMazeApi : TvMazeBase
|
||||||
|
{
|
||||||
|
public TvMazeApi()
|
||||||
|
{
|
||||||
|
Api = new ApiRequest();
|
||||||
|
}
|
||||||
|
private ApiRequest Api { get; }
|
||||||
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
public List<TvMazeSearch> Search(string searchTerm)
|
||||||
|
{
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Method = Method.GET,
|
||||||
|
Resource = "search/shows?q={searchTerm}"
|
||||||
|
};
|
||||||
|
request.AddUrlSegment("searchTerm", searchTerm);
|
||||||
|
request.AddHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
|
return Api.Execute<List<TvMazeSearch>>(request, new Uri(Uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TvMazeShow ShowLookup(int showId)
|
||||||
|
{
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Method = Method.GET,
|
||||||
|
Resource = "shows/{id}"
|
||||||
|
};
|
||||||
|
request.AddUrlSegment("id", showId.ToString());
|
||||||
|
request.AddHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
|
return Api.Execute<TvMazeShow>(request, new Uri(Uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TvMazeShow ShowLookupByTheTvDbId(int theTvDbId)
|
||||||
|
{
|
||||||
|
var request = new RestRequest
|
||||||
|
{
|
||||||
|
Method = Method.GET,
|
||||||
|
Resource = "lookup/shows?thetvdb={id}"
|
||||||
|
};
|
||||||
|
request.AddUrlSegment("id", theTvDbId.ToString());
|
||||||
|
request.AddHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
|
return Api.Execute<TvMazeShow>(request, new Uri(Uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
33
PlexRequests.Api/TvMazeBase.cs
Normal file
33
PlexRequests.Api/TvMazeBase.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: TvMazeBase.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
// ************************************************************************/
|
||||||
|
#endregion
|
||||||
|
namespace PlexRequests.Api
|
||||||
|
{
|
||||||
|
public class TvMazeBase
|
||||||
|
{
|
||||||
|
protected string Uri = "http://api.tvmaze.com";
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ namespace PlexRequests.Core.Tests
|
||||||
public class StatusCheckerTests
|
public class StatusCheckerTests
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
|
[Ignore("API Limit")]
|
||||||
public void CheckStatusTest()
|
public void CheckStatusTest()
|
||||||
{
|
{
|
||||||
var checker = new StatusChecker();
|
var checker = new StatusChecker();
|
||||||
|
@ -42,4 +43,4 @@ namespace PlexRequests.Core.Tests
|
||||||
Assert.That(status, Is.Not.Null);
|
Assert.That(status, Is.Not.Null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,10 @@ namespace PlexRequests.Core
|
||||||
{
|
{
|
||||||
public interface IRequestService
|
public interface IRequestService
|
||||||
{
|
{
|
||||||
long AddRequest(int providerId, RequestedModel model);
|
long AddRequest(RequestedModel model);
|
||||||
bool CheckRequest(int providerId);
|
bool CheckRequest(int providerId);
|
||||||
void DeleteRequest(int tmdbId);
|
void DeleteRequest(RequestedModel request);
|
||||||
void UpdateRequest(RequestedModel model);
|
bool UpdateRequest(RequestedModel model);
|
||||||
RequestedModel Get(int id);
|
RequestedModel Get(int id);
|
||||||
IEnumerable<RequestedModel> GetAll();
|
IEnumerable<RequestedModel> GetAll();
|
||||||
bool BatchUpdate(List<RequestedModel> model);
|
bool BatchUpdate(List<RequestedModel> model);
|
||||||
|
|
|
@ -42,11 +42,18 @@ namespace PlexRequests.Core
|
||||||
Repo = repo;
|
Repo = repo;
|
||||||
}
|
}
|
||||||
private IRequestRepository Repo { get; }
|
private IRequestRepository Repo { get; }
|
||||||
public long AddRequest(int providerId, RequestedModel model)
|
public long AddRequest(RequestedModel model)
|
||||||
{
|
{
|
||||||
var entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId};
|
var entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId };
|
||||||
|
var id = Repo.Insert(entity);
|
||||||
|
|
||||||
return Repo.Insert(entity);
|
// TODO Keep an eye on this, since we are now doing 2 DB update for 1 single request, inserting and then updating
|
||||||
|
model.Id = (int)id;
|
||||||
|
|
||||||
|
entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId, Id = (int)id };
|
||||||
|
var result = Repo.Update(entity);
|
||||||
|
|
||||||
|
return result ? id : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CheckRequest(int providerId)
|
public bool CheckRequest(int providerId)
|
||||||
|
@ -55,16 +62,16 @@ namespace PlexRequests.Core
|
||||||
return blobs.Any(x => x.ProviderId == providerId);
|
return blobs.Any(x => x.ProviderId == providerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteRequest(int tmdbId)
|
public void DeleteRequest(RequestedModel request)
|
||||||
{
|
{
|
||||||
var blob = Repo.GetAll().FirstOrDefault(x => x.ProviderId == tmdbId);
|
var blob = Repo.Get(request.Id);
|
||||||
Repo.Delete(blob);
|
Repo.Delete(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateRequest(RequestedModel model)
|
public bool UpdateRequest(RequestedModel model)
|
||||||
{
|
{
|
||||||
var entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId, Id = model.Id};
|
var entity = new RequestBlobs { Type = model.Type, Content = ReturnBytes(model), ProviderId = model.ProviderId, Id = model.Id };
|
||||||
Repo.Update(entity);
|
return Repo.Update(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestedModel Get(int id)
|
public RequestedModel Get(int id)
|
||||||
|
@ -85,7 +92,7 @@ namespace PlexRequests.Core
|
||||||
|
|
||||||
public bool BatchUpdate(List<RequestedModel> model)
|
public bool BatchUpdate(List<RequestedModel> model)
|
||||||
{
|
{
|
||||||
var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ReturnBytes(m), ProviderId = m.ProviderId }).ToList();
|
var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList();
|
||||||
return Repo.UpdateAll(entities);
|
return Repo.UpdateAll(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,10 @@
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PlexRequests.Api.Models\PlexRequests.Api.Models.csproj">
|
||||||
|
<Project>{CB37A5F8-6DFC-4554-99D3-A42B502E4591}</Project>
|
||||||
|
<Name>PlexRequests.Api.Models</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\PlexRequests.Api\PlexRequests.Api.csproj">
|
<ProjectReference Include="..\PlexRequests.Api\PlexRequests.Api.csproj">
|
||||||
<Project>{8CB8D235-2674-442D-9C6A-35FCAEEB160D}</Project>
|
<Project>{8CB8D235-2674-442D-9C6A-35FCAEEB160D}</Project>
|
||||||
<Name>PlexRequests.Api</Name>
|
<Name>PlexRequests.Api</Name>
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace PlexRequests.Core
|
||||||
|
|
||||||
private IRepository<RequestedModel> Repo { get; set; }
|
private IRepository<RequestedModel> Repo { get; set; }
|
||||||
|
|
||||||
public long AddRequest(int providerId, RequestedModel model)
|
public long AddRequest(RequestedModel model)
|
||||||
{
|
{
|
||||||
return Repo.Insert(model);
|
return Repo.Insert(model);
|
||||||
}
|
}
|
||||||
|
@ -50,16 +50,15 @@ namespace PlexRequests.Core
|
||||||
return Repo.GetAll().Any(x => x.ProviderId == providerId);
|
return Repo.GetAll().Any(x => x.ProviderId == providerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteRequest(int tmdbId)
|
public void DeleteRequest(RequestedModel model)
|
||||||
{
|
{
|
||||||
var entity = Repo.GetAll().FirstOrDefault(x => x.ProviderId == tmdbId);
|
var entity = Repo.Get(model.Id);
|
||||||
Repo.Delete(entity);
|
Repo.Delete(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateRequest(RequestedModel model)
|
public bool UpdateRequest(RequestedModel model)
|
||||||
{
|
{
|
||||||
|
return Repo.Update(model);
|
||||||
Repo.Update(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -36,13 +36,15 @@ namespace PlexRequests.Core.SettingModels
|
||||||
public string Ip { get; set; }
|
public string Ip { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string ApiKey { get; set; }
|
public string ApiKey { get; set; }
|
||||||
|
public bool Ssl { get; set; }
|
||||||
|
public string ProfileId { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Uri FullUri
|
public Uri FullUri
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var formatted = Ip.ReturnUri(Port);
|
var formatted = Ip.ReturnUri(Port, Ssl);
|
||||||
return formatted;
|
return formatted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,30 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using PlexRequests.Helpers;
|
||||||
|
|
||||||
namespace PlexRequests.Core.SettingModels
|
namespace PlexRequests.Core.SettingModels
|
||||||
{
|
{
|
||||||
public class SickRageSettings : Settings
|
public class SickRageSettings : Settings
|
||||||
{
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
public string Ip { get; set; }
|
public string Ip { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string ApiKey { get; set; }
|
public string ApiKey { get; set; }
|
||||||
public bool Enabled { get; set; }
|
public string QualityProfile { get; set; }
|
||||||
|
public bool Ssl { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public Uri FullUri
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var formatted = Ip.ReturnUri(Port, Ssl);
|
||||||
|
return formatted;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,19 +33,21 @@ namespace PlexRequests.Core.SettingModels
|
||||||
{
|
{
|
||||||
public class SonarrSettings : Settings
|
public class SonarrSettings : Settings
|
||||||
{
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
public string Ip { get; set; }
|
public string Ip { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string ApiKey { get; set; }
|
public string ApiKey { get; set; }
|
||||||
public string QualityProfile { get; set; }
|
public string QualityProfile { get; set; }
|
||||||
public bool SeasonFolders { get; set; }
|
public bool SeasonFolders { get; set; }
|
||||||
public string RootPath { get; set; }
|
public string RootPath { get; set; }
|
||||||
|
public bool Ssl { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Uri FullUri
|
public Uri FullUri
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var formatted = Ip.ReturnUri(Port);
|
var formatted = Ip.ReturnUri(Port, Ssl);
|
||||||
return formatted;
|
return formatted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,13 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using Mono.Data.Sqlite;
|
using Mono.Data.Sqlite;
|
||||||
|
using PlexRequests.Api;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Helpers;
|
using PlexRequests.Helpers;
|
||||||
using PlexRequests.Store;
|
using PlexRequests.Store;
|
||||||
|
@ -46,6 +52,7 @@ namespace PlexRequests.Core
|
||||||
CreateDefaultSettingsPage();
|
CreateDefaultSettingsPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MigrateDb();
|
||||||
return Db.DbConnection().ConnectionString;
|
return Db.DbConnection().ConnectionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,5 +70,82 @@ namespace PlexRequests.Core
|
||||||
var s = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
|
var s = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
|
||||||
s.SaveSettings(defaultSettings);
|
s.SaveSettings(defaultSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MigrateDb() // TODO: Remove when no longer needed
|
||||||
|
{
|
||||||
|
var result = new List<long>();
|
||||||
|
RequestedModel[] requestedModels;
|
||||||
|
var repo = new GenericRepository<RequestedModel>(Db);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var records = repo.GetAll();
|
||||||
|
requestedModels = records as RequestedModel[] ?? records.ToArray();
|
||||||
|
}
|
||||||
|
catch (SqliteException)
|
||||||
|
{
|
||||||
|
// There is no requested table so they do not have an old version of the DB
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!requestedModels.Any())
|
||||||
|
{ return; }
|
||||||
|
|
||||||
|
var jsonRepo = new JsonRequestService(new RequestJsonRepository(Db, new MemoryCacheProvider()));
|
||||||
|
|
||||||
|
var api = new TvMazeApi();
|
||||||
|
|
||||||
|
foreach (var r in requestedModels.Where(x => x.Type == RequestType.TvShow))
|
||||||
|
{
|
||||||
|
var show = api.ShowLookupByTheTvDbId(r.ProviderId);
|
||||||
|
|
||||||
|
var model = new RequestedModel
|
||||||
|
{
|
||||||
|
Title = show.name,
|
||||||
|
PosterPath = show.image?.medium,
|
||||||
|
Type = RequestType.TvShow,
|
||||||
|
ProviderId = show.externals.thetvdb ?? 0,
|
||||||
|
ReleaseDate = r.ReleaseDate,
|
||||||
|
AdminNote = r.AdminNote,
|
||||||
|
Approved = r.Approved,
|
||||||
|
Available = r.Available,
|
||||||
|
ImdbId = show.externals.imdb,
|
||||||
|
Issues = r.Issues,
|
||||||
|
LatestTv = r.LatestTv,
|
||||||
|
OtherMessage = r.OtherMessage,
|
||||||
|
Overview = show.summary.RemoveHtml(),
|
||||||
|
RequestedBy = r.RequestedBy,
|
||||||
|
RequestedDate = r.ReleaseDate,
|
||||||
|
Status = show.status
|
||||||
|
};
|
||||||
|
var id = jsonRepo.AddRequest(model);
|
||||||
|
result.Add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var source in requestedModels.Where(x => x.Type== RequestType.Movie))
|
||||||
|
{
|
||||||
|
var id = jsonRepo.AddRequest(source);
|
||||||
|
result.Add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (result.Any(x => x == -1))
|
||||||
|
{
|
||||||
|
throw new SqliteException("Could not migrate the DB!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (result.Count != requestedModels.Length)
|
||||||
|
{
|
||||||
|
throw new SqliteException("Could not migrate the DB! count is different");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now delete the old requests
|
||||||
|
foreach (var oldRequest in requestedModels)
|
||||||
|
{
|
||||||
|
repo.Delete(oldRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
56
PlexRequests.Helpers.Tests/HtmlRemoverTests.cs
Normal file
56
PlexRequests.Helpers.Tests/HtmlRemoverTests.cs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#region Copyright
|
||||||
|
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: HtmlRemoverTests.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 NUnit.Framework;
|
||||||
|
|
||||||
|
namespace PlexRequests.Helpers.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class HtmlRemoverTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void RemoveHtmlBasic()
|
||||||
|
{
|
||||||
|
var html = "this is <b>bold</b> <p>para</p> OK!";
|
||||||
|
var result = html.RemoveHtml();
|
||||||
|
Assert.That(result, Is.Not.Null);
|
||||||
|
Assert.That(result, Is.EqualTo("this is bold para OK!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void RemoveHtmlMoreTags()
|
||||||
|
{
|
||||||
|
// Good 'ol Ali G ;)
|
||||||
|
var html = "<p><strong><em>\"Ali G: Rezurection\"</em></strong> includes every episode of <em>Da Ali G Show</em> with new, original introductions by star, creator/writer Sacha Baron Cohen, along with the BAFTA(R) Award-winning English episodes of <em>Da Ali G Show</em> which have never aired on American television and <em>The Best of Ali G</em>.</p>";
|
||||||
|
var result = html.RemoveHtml();
|
||||||
|
Assert.That(result, Is.Not.Null);
|
||||||
|
Assert.That(result, Is.EqualTo("\"Ali G: Rezurection\" includes every episode of Da Ali G Show with new, original introductions by star, creator/writer Sacha Baron Cohen, along with the BAFTA(R) Award-winning English episodes of Da Ali G Show which have never aired on American television and The Best of Ali G."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -70,6 +70,7 @@
|
||||||
</Otherwise>
|
</Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="HtmlRemoverTests.cs" />
|
||||||
<Compile Include="AssemblyHelperTests.cs" />
|
<Compile Include="AssemblyHelperTests.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="UriHelperTests.cs" />
|
<Compile Include="UriHelperTests.cs" />
|
||||||
|
|
45
PlexRequests.Helpers/HtmlRemover.cs
Normal file
45
PlexRequests.Helpers/HtmlRemover.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: HtmlRemover.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.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace PlexRequests.Helpers
|
||||||
|
{
|
||||||
|
public static class HtmlRemover
|
||||||
|
{
|
||||||
|
public static string RemoveHtml(this string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
var step1 = Regex.Replace(value, @"<[^>]+>| ", "").Trim();
|
||||||
|
var step2 = Regex.Replace(step1, @"\s{2,}", " ");
|
||||||
|
return step2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,6 +48,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AssemblyHelper.cs" />
|
<Compile Include="AssemblyHelper.cs" />
|
||||||
<Compile Include="Exceptions\ApplicationSettingsException.cs" />
|
<Compile Include="Exceptions\ApplicationSettingsException.cs" />
|
||||||
|
<Compile Include="HtmlRemover.cs" />
|
||||||
<Compile Include="ICacheProvider.cs" />
|
<Compile Include="ICacheProvider.cs" />
|
||||||
<Compile Include="LoggingHelper.cs" />
|
<Compile Include="LoggingHelper.cs" />
|
||||||
<Compile Include="MemoryCacheProvider.cs" />
|
<Compile Include="MemoryCacheProvider.cs" />
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace PlexRequests.Services.Tests
|
||||||
var plexMock = new Mock<IPlexApi>();
|
var plexMock = new Mock<IPlexApi>();
|
||||||
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
||||||
|
|
||||||
Assert.Throws<ApplicationSettingsException>(() => Checker.IsAvailable("title"), "We should be throwing an exception since we cannot talk to the services.");
|
Assert.Throws<ApplicationSettingsException>(() => Checker.IsAvailable("title", "2013"), "We should be throwing an exception since we cannot talk to the services.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -66,7 +66,7 @@ namespace PlexRequests.Services.Tests
|
||||||
var requestMock = new Mock<IRequestService>();
|
var requestMock = new Mock<IRequestService>();
|
||||||
var plexMock = new Mock<IPlexApi>();
|
var plexMock = new Mock<IPlexApi>();
|
||||||
|
|
||||||
var searchResult = new PlexSearch {Video = new List<Video> {new Video {Title = "title" } } };
|
var searchResult = new PlexSearch {Video = new List<Video> {new Video {Title = "title", Year = "2011"} } };
|
||||||
|
|
||||||
settingsMock.Setup(x => x.GetSettings()).Returns(new PlexSettings { Ip = "abc" });
|
settingsMock.Setup(x => x.GetSettings()).Returns(new PlexSettings { Ip = "abc" });
|
||||||
authMock.Setup(x => x.GetSettings()).Returns(new AuthenticationSettings { PlexAuthToken = "abc" });
|
authMock.Setup(x => x.GetSettings()).Returns(new AuthenticationSettings { PlexAuthToken = "abc" });
|
||||||
|
@ -74,7 +74,28 @@ namespace PlexRequests.Services.Tests
|
||||||
|
|
||||||
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
||||||
|
|
||||||
var result = Checker.IsAvailable("title");
|
var result = Checker.IsAvailable("title", "2011");
|
||||||
|
|
||||||
|
Assert.That(result, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void IsAvailableDirectoryTitleTest()
|
||||||
|
{
|
||||||
|
var settingsMock = new Mock<ISettingsService<PlexSettings>>();
|
||||||
|
var authMock = new Mock<ISettingsService<AuthenticationSettings>>();
|
||||||
|
var requestMock = new Mock<IRequestService>();
|
||||||
|
var plexMock = new Mock<IPlexApi>();
|
||||||
|
|
||||||
|
var searchResult = new PlexSearch { Directory = new Directory1 {Title = "title", Year = "2013"} };
|
||||||
|
|
||||||
|
settingsMock.Setup(x => x.GetSettings()).Returns(new PlexSettings { Ip = "abc" });
|
||||||
|
authMock.Setup(x => x.GetSettings()).Returns(new AuthenticationSettings { PlexAuthToken = "abc" });
|
||||||
|
plexMock.Setup(x => x.SearchContent(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns(searchResult);
|
||||||
|
|
||||||
|
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
||||||
|
|
||||||
|
var result = Checker.IsAvailable("title", "2013");
|
||||||
|
|
||||||
Assert.That(result, Is.True);
|
Assert.That(result, Is.True);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +108,7 @@ namespace PlexRequests.Services.Tests
|
||||||
var requestMock = new Mock<IRequestService>();
|
var requestMock = new Mock<IRequestService>();
|
||||||
var plexMock = new Mock<IPlexApi>();
|
var plexMock = new Mock<IPlexApi>();
|
||||||
|
|
||||||
var searchResult = new PlexSearch { Video = new List<Video> { new Video { Title = "wrong title" } } };
|
var searchResult = new PlexSearch { Video = new List<Video> { new Video { Title = "wrong tistle", Year = "2011"} } };
|
||||||
|
|
||||||
settingsMock.Setup(x => x.GetSettings()).Returns(new PlexSettings { Ip = "abc" });
|
settingsMock.Setup(x => x.GetSettings()).Returns(new PlexSettings { Ip = "abc" });
|
||||||
authMock.Setup(x => x.GetSettings()).Returns(new AuthenticationSettings { PlexAuthToken = "abc" });
|
authMock.Setup(x => x.GetSettings()).Returns(new AuthenticationSettings { PlexAuthToken = "abc" });
|
||||||
|
@ -95,7 +116,28 @@ namespace PlexRequests.Services.Tests
|
||||||
|
|
||||||
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
||||||
|
|
||||||
var result = Checker.IsAvailable("title");
|
var result = Checker.IsAvailable("title", "2011");
|
||||||
|
|
||||||
|
Assert.That(result, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void IsYearDoesNotMatchTest()
|
||||||
|
{
|
||||||
|
var settingsMock = new Mock<ISettingsService<PlexSettings>>();
|
||||||
|
var authMock = new Mock<ISettingsService<AuthenticationSettings>>();
|
||||||
|
var requestMock = new Mock<IRequestService>();
|
||||||
|
var plexMock = new Mock<IPlexApi>();
|
||||||
|
|
||||||
|
var searchResult = new PlexSearch { Video = new List<Video> { new Video { Title = "title", Year = "2019" } } };
|
||||||
|
|
||||||
|
settingsMock.Setup(x => x.GetSettings()).Returns(new PlexSettings { Ip = "abc" });
|
||||||
|
authMock.Setup(x => x.GetSettings()).Returns(new AuthenticationSettings { PlexAuthToken = "abc" });
|
||||||
|
plexMock.Setup(x => x.SearchContent(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns(searchResult);
|
||||||
|
|
||||||
|
Checker = new PlexAvailabilityChecker(settingsMock.Object, authMock.Object, requestMock.Object, plexMock.Object);
|
||||||
|
|
||||||
|
var result = Checker.IsAvailable("title", "2011");
|
||||||
|
|
||||||
Assert.That(result, Is.False);
|
Assert.That(result, Is.False);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,6 @@ namespace PlexRequests.Services.Interfaces
|
||||||
public interface IAvailabilityChecker
|
public interface IAvailabilityChecker
|
||||||
{
|
{
|
||||||
void CheckAndUpdateAll(long check);
|
void CheckAndUpdateAll(long check);
|
||||||
bool IsAvailable(string title);
|
bool IsAvailable(string title, string year);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -85,9 +85,10 @@ namespace PlexRequests.Services
|
||||||
/// Determines whether the specified search term is available.
|
/// Determines whether the specified search term is available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="title">The search term.</param>
|
/// <param name="title">The search term.</param>
|
||||||
|
/// <param name="year">The year.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="ApplicationSettingsException">The settings are not configured for Plex or Authentication</exception>
|
/// <exception cref="ApplicationSettingsException">The settings are not configured for Plex or Authentication</exception>
|
||||||
public bool IsAvailable(string title)
|
public bool IsAvailable(string title, string year)
|
||||||
{
|
{
|
||||||
var plexSettings = Plex.GetSettings();
|
var plexSettings = Plex.GetSettings();
|
||||||
var authSettings = Auth.GetSettings();
|
var authSettings = Auth.GetSettings();
|
||||||
|
@ -96,10 +97,21 @@ namespace PlexRequests.Services
|
||||||
{
|
{
|
||||||
throw new ApplicationSettingsException("The settings are not configured for Plex or Authentication");
|
throw new ApplicationSettingsException("The settings are not configured for Plex or Authentication");
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrEmpty(year))
|
||||||
|
{
|
||||||
|
var results = PlexApi.SearchContent(authSettings.PlexAuthToken, title, plexSettings.FullUri);
|
||||||
|
var result = results.Video?.FirstOrDefault(x => x.Title.Contains(title) && x.Year == year);
|
||||||
|
var directoryTitle = results.Directory?.Title == title && results.Directory?.Year == year;
|
||||||
|
return result?.Title != null || directoryTitle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var results = PlexApi.SearchContent(authSettings.PlexAuthToken, title, plexSettings.FullUri);
|
||||||
|
var result = results.Video?.FirstOrDefault(x => x.Title.Contains(title));
|
||||||
|
var directoryTitle = results.Directory?.Title == title;
|
||||||
|
return result?.Title != null || directoryTitle;
|
||||||
|
}
|
||||||
|
|
||||||
var results = PlexApi.SearchContent(authSettings.PlexAuthToken, title, plexSettings.FullUri);
|
|
||||||
var result = results.Video.FirstOrDefault(x => x.Title == title);
|
|
||||||
return result?.Title != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ValidateSettings(PlexSettings plex, AuthenticationSettings auth, IEnumerable<RequestedModel> requests)
|
private bool ValidateSettings(PlexSettings plex, AuthenticationSettings auth, IEnumerable<RequestedModel> requests)
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Dapper.Contrib, Version=1.40.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Dapper.Contrib, Version=1.40.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Dapper.Contrib.1.42\lib\net45\Dapper.Contrib.dll</HintPath>
|
<HintPath>..\packages\Dapper.Contrib.1.43\lib\net45\Dapper.Contrib.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Mono.Data.Sqlite">
|
<Reference Include="Mono.Data.Sqlite">
|
||||||
|
@ -68,7 +68,6 @@
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Repository\SettingsJsonRepository.cs" />
|
<Compile Include="Repository\SettingsJsonRepository.cs" />
|
||||||
<Compile Include="Repository\RequestJsonRepository.cs" />
|
<Compile Include="Repository\RequestJsonRepository.cs" />
|
||||||
<Compile Include="SettingsModel.cs" />
|
|
||||||
<Compile Include="GenericRepository.cs" />
|
<Compile Include="GenericRepository.cs" />
|
||||||
<Compile Include="RequestedModel.cs" />
|
<Compile Include="RequestedModel.cs" />
|
||||||
<Compile Include="UserRepository.cs" />
|
<Compile Include="UserRepository.cs" />
|
||||||
|
|
|
@ -53,7 +53,8 @@ namespace PlexRequests.Store.Repository
|
||||||
ResetCache();
|
ResetCache();
|
||||||
using (var con = Db.DbConnection())
|
using (var con = Db.DbConnection())
|
||||||
{
|
{
|
||||||
return con.Insert(entity);
|
var id = con.Insert(entity);
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ namespace PlexRequests.Store.Repository
|
||||||
|
|
||||||
public RequestBlobs Get(int id)
|
public RequestBlobs Get(int id)
|
||||||
{
|
{
|
||||||
var key = TypeName + "Get";
|
var key = TypeName + "Get" + id;
|
||||||
var item = Cache.GetOrSet(key, () =>
|
var item = Cache.GetOrSet(key, () =>
|
||||||
{
|
{
|
||||||
using (var con = Db.DbConnection())
|
using (var con = Db.DbConnection())
|
||||||
|
@ -111,8 +112,8 @@ namespace PlexRequests.Store.Repository
|
||||||
|
|
||||||
public bool UpdateAll(IEnumerable<RequestBlobs> entity)
|
public bool UpdateAll(IEnumerable<RequestBlobs> entity)
|
||||||
{
|
{
|
||||||
|
ResetCache();
|
||||||
var result = new HashSet<bool>();
|
var result = new HashSet<bool>();
|
||||||
|
|
||||||
using (var db = Db.DbConnection())
|
using (var db = Db.DbConnection())
|
||||||
{
|
{
|
||||||
db.Open();
|
db.Open();
|
||||||
|
|
|
@ -8,36 +8,6 @@ CREATE TABLE IF NOT EXISTS User
|
||||||
Password varchar(100) NOT NULL
|
Password varchar(100) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS Settings
|
|
||||||
(
|
|
||||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
Port INTEGER NOT NULL,
|
|
||||||
UserAuthentication INTEGER NOT NULL,
|
|
||||||
PlexAuthToken varchar(50)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS Requested
|
|
||||||
(
|
|
||||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
Type INTEGER NOT NULL,
|
|
||||||
ProviderId INTEGER NOT NULL,
|
|
||||||
ImdbId varchar(50),
|
|
||||||
Overview varchar(50),
|
|
||||||
Title varchar(50) NOT NULL,
|
|
||||||
PosterPath varchar(50) NOT NULL,
|
|
||||||
ReleaseDate varchar(50) NOT NULL,
|
|
||||||
Status varchar(50) NOT NULL,
|
|
||||||
AdminNote varchar(50),
|
|
||||||
Approved INTEGER NOT NULL,
|
|
||||||
LatestTv INTEGER NOT NULL,
|
|
||||||
RequestedBy varchar(50),
|
|
||||||
RequestedDate varchar(50) NOT NULL,
|
|
||||||
Available INTEGER(50),
|
|
||||||
Issues INTEGER,
|
|
||||||
OtherMessage varchar(50)
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS GlobalSettings
|
CREATE TABLE IF NOT EXISTS GlobalSettings
|
||||||
(
|
(
|
||||||
|
@ -65,4 +35,4 @@ CREATE TABLE IF NOT EXISTS Log
|
||||||
Message varchar(100) NOT NULL,
|
Message varchar(100) NOT NULL,
|
||||||
CallSite varchar(100) NOT NULL,
|
CallSite varchar(100) NOT NULL,
|
||||||
Exception varchar(100) NOT NULL
|
Exception varchar(100) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Dapper" version="1.42" targetFramework="net452" />
|
<package id="Dapper" version="1.42" targetFramework="net452" />
|
||||||
<package id="Dapper.Contrib" version="1.42" targetFramework="net452" />
|
<package id="Dapper.Contrib" version="1.43" targetFramework="net46" />
|
||||||
<package id="NLog" version="4.2.3" targetFramework="net452" />
|
<package id="NLog" version="4.2.3" targetFramework="net452" />
|
||||||
</packages>
|
</packages>
|
|
@ -52,11 +52,13 @@ namespace PlexRequests.UI.Tests
|
||||||
private Mock<ISettingsService<AuthenticationSettings>> AuthMock { get; set; }
|
private Mock<ISettingsService<AuthenticationSettings>> AuthMock { get; set; }
|
||||||
private Mock<ISettingsService<PlexSettings>> PlexSettingsMock { get; set; }
|
private Mock<ISettingsService<PlexSettings>> PlexSettingsMock { get; set; }
|
||||||
private Mock<ISettingsService<SonarrSettings>> SonarrSettingsMock { get; set; }
|
private Mock<ISettingsService<SonarrSettings>> SonarrSettingsMock { get; set; }
|
||||||
|
private Mock<ISettingsService<SickRageSettings>> SickRageSettingsMock { get; set; }
|
||||||
private Mock<ISettingsService<EmailNotificationSettings>> EmailMock { get; set; }
|
private Mock<ISettingsService<EmailNotificationSettings>> EmailMock { get; set; }
|
||||||
private Mock<ISettingsService<PushbulletNotificationSettings>> PushbulletSettings { get; set; }
|
private Mock<ISettingsService<PushbulletNotificationSettings>> PushbulletSettings { get; set; }
|
||||||
private Mock<IPlexApi> PlexMock { get; set; }
|
private Mock<IPlexApi> PlexMock { get; set; }
|
||||||
private Mock<ISonarrApi> SonarrApiMock { get; set; }
|
private Mock<ISonarrApi> SonarrApiMock { get; set; }
|
||||||
private Mock<IPushbulletApi> PushbulletApi { get; set; }
|
private Mock<IPushbulletApi> PushbulletApi { get; set; }
|
||||||
|
private Mock<ICouchPotatoApi> CpApi { get; set; }
|
||||||
|
|
||||||
private ConfigurableBootstrapper Bootstrapper { get; set; }
|
private ConfigurableBootstrapper Bootstrapper { get; set; }
|
||||||
|
|
||||||
|
@ -79,6 +81,8 @@ namespace PlexRequests.UI.Tests
|
||||||
EmailMock = new Mock<ISettingsService<EmailNotificationSettings>>();
|
EmailMock = new Mock<ISettingsService<EmailNotificationSettings>>();
|
||||||
PushbulletApi = new Mock<IPushbulletApi>();
|
PushbulletApi = new Mock<IPushbulletApi>();
|
||||||
PushbulletSettings = new Mock<ISettingsService<PushbulletNotificationSettings>>();
|
PushbulletSettings = new Mock<ISettingsService<PushbulletNotificationSettings>>();
|
||||||
|
CpApi = new Mock<ICouchPotatoApi>();
|
||||||
|
SickRageSettingsMock = new Mock<ISettingsService<SickRageSettings>>();
|
||||||
|
|
||||||
Bootstrapper = new ConfigurableBootstrapper(with =>
|
Bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
{
|
{
|
||||||
|
@ -93,6 +97,8 @@ namespace PlexRequests.UI.Tests
|
||||||
with.Dependency(EmailMock.Object);
|
with.Dependency(EmailMock.Object);
|
||||||
with.Dependency(PushbulletApi.Object);
|
with.Dependency(PushbulletApi.Object);
|
||||||
with.Dependency(PushbulletSettings.Object);
|
with.Dependency(PushbulletSettings.Object);
|
||||||
|
with.Dependency(CpApi.Object);
|
||||||
|
with.Dependency(SickRageSettingsMock.Object);
|
||||||
with.RootPathProvider<TestRootPathProvider>();
|
with.RootPathProvider<TestRootPathProvider>();
|
||||||
with.RequestStartup((container, pipelines, context) =>
|
with.RequestStartup((container, pipelines, context) =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,7 +36,6 @@ using Newtonsoft.Json;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
using PlexRequests.Api.Interfaces;
|
using PlexRequests.Api.Interfaces;
|
||||||
using PlexRequests.Api.Models;
|
|
||||||
using PlexRequests.Api.Models.Plex;
|
using PlexRequests.Api.Models.Plex;
|
||||||
using PlexRequests.Core;
|
using PlexRequests.Core;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
|
@ -81,7 +80,7 @@ namespace PlexRequests.UI.Tests
|
||||||
with.Header("Accept", "application/json");
|
with.Header("Accept", "application/json");
|
||||||
with.FormValue("Username", "abc");
|
with.FormValue("Username", "abc");
|
||||||
});
|
});
|
||||||
|
|
||||||
Assert.That(HttpStatusCode.OK, Is.EqualTo(result.StatusCode));
|
Assert.That(HttpStatusCode.OK, Is.EqualTo(result.StatusCode));
|
||||||
Assert.That(result.Context.Request.Session[SessionKeys.UsernameKey], Is.EqualTo("abc"));
|
Assert.That(result.Context.Request.Session[SessionKeys.UsernameKey], Is.EqualTo("abc"));
|
||||||
|
|
||||||
|
@ -142,6 +141,7 @@ namespace PlexRequests.UI.Tests
|
||||||
|
|
||||||
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
||||||
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
||||||
|
PlexMock.Setup(x => x.GetAccount(It.IsAny<string>())).Returns(new PlexAccount());
|
||||||
|
|
||||||
var bootstrapper = new ConfigurableBootstrapper(with =>
|
var bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
{
|
{
|
||||||
|
@ -188,6 +188,7 @@ namespace PlexRequests.UI.Tests
|
||||||
|
|
||||||
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
||||||
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
||||||
|
PlexMock.Setup(x => x.GetAccount(It.IsAny<string>())).Returns(new PlexAccount());
|
||||||
|
|
||||||
var bootstrapper = new ConfigurableBootstrapper(with =>
|
var bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
{
|
{
|
||||||
|
@ -245,6 +246,7 @@ namespace PlexRequests.UI.Tests
|
||||||
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
||||||
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
||||||
PlexMock.Setup(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>())).Returns(plexAuth);
|
PlexMock.Setup(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>())).Returns(plexAuth);
|
||||||
|
PlexMock.Setup(x => x.GetAccount(It.IsAny<string>())).Returns(new PlexAccount());
|
||||||
|
|
||||||
var bootstrapper = new ConfigurableBootstrapper(with =>
|
var bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
{
|
{
|
||||||
|
@ -376,7 +378,7 @@ namespace PlexRequests.UI.Tests
|
||||||
with.RootPathProvider<TestRootPathProvider>();
|
with.RootPathProvider<TestRootPathProvider>();
|
||||||
});
|
});
|
||||||
|
|
||||||
bootstrapper.WithSession(new Dictionary<string, object> { {SessionKeys.UsernameKey, "abc"} });
|
bootstrapper.WithSession(new Dictionary<string, object> { { SessionKeys.UsernameKey, "abc" } });
|
||||||
|
|
||||||
var browser = new Browser(bootstrapper);
|
var browser = new Browser(bootstrapper);
|
||||||
var result = browser.Get("/userlogin/logout", with =>
|
var result = browser.Get("/userlogin/logout", with =>
|
||||||
|
@ -388,5 +390,108 @@ namespace PlexRequests.UI.Tests
|
||||||
Assert.That(HttpStatusCode.SeeOther, Is.EqualTo(result.StatusCode));
|
Assert.That(HttpStatusCode.SeeOther, Is.EqualTo(result.StatusCode));
|
||||||
Assert.That(result.Context.Request.Session[SessionKeys.UsernameKey], Is.Null);
|
Assert.That(result.Context.Request.Session[SessionKeys.UsernameKey], Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void LoginWithOwnerUsernameSuccessfully()
|
||||||
|
{
|
||||||
|
var expectedSettings = new AuthenticationSettings { UserAuthentication = true, PlexAuthToken = "abc" };
|
||||||
|
var plexFriends = new PlexFriends
|
||||||
|
{
|
||||||
|
User = new[]
|
||||||
|
{
|
||||||
|
new UserFriends()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var account = new PlexAccount { Username = "Jamie" };
|
||||||
|
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
||||||
|
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
||||||
|
PlexMock.Setup(x => x.GetAccount(It.IsAny<string>())).Returns(account);
|
||||||
|
PlexMock.Setup(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>())).Returns(new PlexAuthentication { user = new User { username = "Jamie" } });
|
||||||
|
|
||||||
|
var bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
|
{
|
||||||
|
with.Module<UserLoginModule>();
|
||||||
|
with.Dependency(AuthMock.Object);
|
||||||
|
with.Dependency(PlexMock.Object);
|
||||||
|
with.RootPathProvider<TestRootPathProvider>();
|
||||||
|
});
|
||||||
|
|
||||||
|
bootstrapper.WithSession(new Dictionary<string, object>());
|
||||||
|
|
||||||
|
var browser = new Browser(bootstrapper);
|
||||||
|
var result = browser.Post("/userlogin", with =>
|
||||||
|
{
|
||||||
|
with.HttpRequest();
|
||||||
|
with.Header("Accept", "application/json");
|
||||||
|
with.FormValue("Username", "Jamie");
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(HttpStatusCode.OK, Is.EqualTo(result.StatusCode));
|
||||||
|
Assert.That(result.Context.Request.Session[SessionKeys.UsernameKey], Is.EqualTo("Jamie"));
|
||||||
|
|
||||||
|
var body = JsonConvert.DeserializeObject<JsonResponseModel>(result.Body.AsString());
|
||||||
|
Assert.That(body.Result, Is.EqualTo(true));
|
||||||
|
AuthMock.Verify(x => x.GetSettings(), Times.Once);
|
||||||
|
PlexMock.Verify(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
|
||||||
|
PlexMock.Verify(x => x.GetUsers(It.IsAny<string>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void LoginWithOwnerUsernameAndPasswordSuccessfully()
|
||||||
|
{
|
||||||
|
var expectedSettings = new AuthenticationSettings { UserAuthentication = true, UsePassword = true, PlexAuthToken = "abc" };
|
||||||
|
var plexFriends = new PlexFriends
|
||||||
|
{
|
||||||
|
User = new[]
|
||||||
|
{
|
||||||
|
new UserFriends()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var plexAuth = new PlexAuthentication
|
||||||
|
{
|
||||||
|
user = new User
|
||||||
|
{
|
||||||
|
authentication_token = "abc",
|
||||||
|
username = "Jamie"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var account = new PlexAccount { Username = "Jamie" };
|
||||||
|
|
||||||
|
AuthMock.Setup(x => x.GetSettings()).Returns(expectedSettings);
|
||||||
|
PlexMock.Setup(x => x.GetUsers(It.IsAny<string>())).Returns(plexFriends);
|
||||||
|
PlexMock.Setup(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>())).Returns(plexAuth);
|
||||||
|
PlexMock.Setup(x => x.GetAccount(It.IsAny<string>())).Returns(account);
|
||||||
|
|
||||||
|
var bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
|
{
|
||||||
|
with.Module<UserLoginModule>();
|
||||||
|
with.Dependency(AuthMock.Object);
|
||||||
|
with.Dependency(PlexMock.Object);
|
||||||
|
with.RootPathProvider<TestRootPathProvider>();
|
||||||
|
});
|
||||||
|
|
||||||
|
bootstrapper.WithSession(new Dictionary<string, object>());
|
||||||
|
|
||||||
|
var browser = new Browser(bootstrapper);
|
||||||
|
var result = browser.Post("/userlogin", with =>
|
||||||
|
{
|
||||||
|
with.HttpRequest();
|
||||||
|
with.Header("Accept", "application/json");
|
||||||
|
with.FormValue("Username", "jamie");
|
||||||
|
with.FormValue("Password", "abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Assert.That(HttpStatusCode.OK, Is.EqualTo(result.StatusCode));
|
||||||
|
Assert.That(result.Context.Request.Session[SessionKeys.UsernameKey], Is.EqualTo("jamie"));
|
||||||
|
|
||||||
|
var body = JsonConvert.DeserializeObject<JsonResponseModel>(result.Body.AsString());
|
||||||
|
Assert.That(body.Result, Is.EqualTo(true));
|
||||||
|
AuthMock.Verify(x => x.GetSettings(), Times.Once);
|
||||||
|
PlexMock.Verify(x => x.SignIn(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||||
|
PlexMock.Verify(x => x.GetUsers(It.IsAny<string>()), Times.Never);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -62,33 +62,34 @@ namespace PlexRequests.UI
|
||||||
protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
|
protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
|
||||||
{
|
{
|
||||||
container.Register<IUserMapper, UserMapper>();
|
container.Register<IUserMapper, UserMapper>();
|
||||||
|
|
||||||
container.Register<ISqliteConfiguration, DbConfiguration>(new DbConfiguration(new SqliteFactory()));
|
container.Register<ISqliteConfiguration, DbConfiguration>(new DbConfiguration(new SqliteFactory()));
|
||||||
|
|
||||||
container.Register<ISettingsRepository, SettingsJsonRepository>();
|
|
||||||
container.Register<ICacheProvider, MemoryCacheProvider>();
|
container.Register<ICacheProvider, MemoryCacheProvider>();
|
||||||
|
|
||||||
|
// Settings
|
||||||
container.Register<ISettingsService<PlexRequestSettings>, SettingsServiceV2<PlexRequestSettings>>();
|
container.Register<ISettingsService<PlexRequestSettings>, SettingsServiceV2<PlexRequestSettings>>();
|
||||||
container.Register<ISettingsService<CouchPotatoSettings>, SettingsServiceV2<CouchPotatoSettings>>();
|
container.Register<ISettingsService<CouchPotatoSettings>, SettingsServiceV2<CouchPotatoSettings>>();
|
||||||
container.Register<ISettingsService<AuthenticationSettings>, SettingsServiceV2<AuthenticationSettings>>();
|
container.Register<ISettingsService<AuthenticationSettings>, SettingsServiceV2<AuthenticationSettings>>();
|
||||||
container.Register<ISettingsService<PlexSettings>, SettingsServiceV2<PlexSettings>>();
|
container.Register<ISettingsService<PlexSettings>, SettingsServiceV2<PlexSettings>>();
|
||||||
container.Register<ISettingsService<SonarrSettings>, SettingsServiceV2<SonarrSettings>>();
|
container.Register<ISettingsService<SonarrSettings>, SettingsServiceV2<SonarrSettings>>();
|
||||||
|
container.Register<ISettingsService<SickRageSettings>, SettingsServiceV2<SickRageSettings>>();
|
||||||
container.Register<ISettingsService<EmailNotificationSettings>, SettingsServiceV2<EmailNotificationSettings>>();
|
container.Register<ISettingsService<EmailNotificationSettings>, SettingsServiceV2<EmailNotificationSettings>>();
|
||||||
container.Register<ISettingsService<PushbulletNotificationSettings>, SettingsServiceV2<PushbulletNotificationSettings>>();
|
container.Register<ISettingsService<PushbulletNotificationSettings>, SettingsServiceV2<PushbulletNotificationSettings>>();
|
||||||
container.Register<IRepository<RequestedModel>, GenericRepository<RequestedModel>>();
|
|
||||||
container.Register<IRequestService, RequestService>();
|
|
||||||
|
|
||||||
|
// Repo's
|
||||||
|
container.Register<IRepository<RequestedModel>, GenericRepository<RequestedModel>>();
|
||||||
|
container.Register<IRequestService, JsonRequestService>();
|
||||||
|
container.Register<ISettingsRepository, SettingsJsonRepository>();
|
||||||
|
|
||||||
|
// Services
|
||||||
container.Register<IAvailabilityChecker, PlexAvailabilityChecker>();
|
container.Register<IAvailabilityChecker, PlexAvailabilityChecker>();
|
||||||
container.Register<IConfigurationReader, ConfigurationReader>();
|
container.Register<IConfigurationReader, ConfigurationReader>();
|
||||||
container.Register<IIntervals, UpdateInterval>();
|
container.Register<IIntervals, UpdateInterval>();
|
||||||
|
|
||||||
|
// Api's
|
||||||
container.Register<ICouchPotatoApi, CouchPotatoApi>();
|
container.Register<ICouchPotatoApi, CouchPotatoApi>();
|
||||||
container.Register<IPushbulletApi, PushbulletApi>();
|
container.Register<IPushbulletApi, PushbulletApi>();
|
||||||
|
container.Register<ISickRageApi, SickrageApi>();
|
||||||
container.Register<ISonarrApi, SonarrApi>();
|
container.Register<ISonarrApi, SonarrApi>();
|
||||||
//container.Register<ISonarrApi, MockSonarrApi>();
|
|
||||||
|
|
||||||
|
|
||||||
container.Register<IPlexApi, PlexApi>();
|
container.Register<IPlexApi, PlexApi>();
|
||||||
|
|
||||||
SubscribeAllObservers(container);
|
SubscribeAllObservers(container);
|
||||||
|
@ -101,7 +102,7 @@ namespace PlexRequests.UI
|
||||||
TaskManager.Initialize(new PlexRegistry());
|
TaskManager.Initialize(new PlexRegistry());
|
||||||
|
|
||||||
CookieBasedSessions.Enable(pipelines, CryptographyConfiguration.Default);
|
CookieBasedSessions.Enable(pipelines, CryptographyConfiguration.Default);
|
||||||
|
|
||||||
StaticConfiguration.DisableErrorTraces = false;
|
StaticConfiguration.DisableErrorTraces = false;
|
||||||
|
|
||||||
base.ApplicationStartup(container, pipelines);
|
base.ApplicationStartup(container, pipelines);
|
||||||
|
|
|
@ -108,7 +108,7 @@ $(".theNoteSaveButton").click(function (e) {
|
||||||
if (checkJsonResponse(response)) {
|
if (checkJsonResponse(response)) {
|
||||||
generateNotify("Success! Added Note.", "success");
|
generateNotify("Success! Added Note.", "success");
|
||||||
$("#myModal").modal("hide");
|
$("#myModal").modal("hide");
|
||||||
$('#adminNotesArea').html("<div>Note from Admin: " + comment + "</div>");
|
$('#adminNotesArea' + e.target.value).html("<div>Note from Admin: " + comment + "</div>");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function (e) {
|
error: function (e) {
|
||||||
|
@ -210,7 +210,7 @@ $(document).on("click", ".clear", function (e) {
|
||||||
|
|
||||||
if (checkJsonResponse(response)) {
|
if (checkJsonResponse(response)) {
|
||||||
generateNotify("Success! Issues Cleared.", "info");
|
generateNotify("Success! Issues Cleared.", "info");
|
||||||
$('#issueArea').html("<div>Issue: None</div>");
|
$('#issueArea'+buttonId).html("<div>Issue: None</div>");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function (e) {
|
error: function (e) {
|
||||||
|
|
77
PlexRequests.UI/Helpers/TvSender.cs
Normal file
77
PlexRequests.UI/Helpers/TvSender.cs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: TvSender.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 Nancy;
|
||||||
|
using NLog;
|
||||||
|
using PlexRequests.Api.Interfaces;
|
||||||
|
using PlexRequests.Api.Models.SickRage;
|
||||||
|
using PlexRequests.Api.Models.Sonarr;
|
||||||
|
using PlexRequests.Core;
|
||||||
|
using PlexRequests.Core.SettingModels;
|
||||||
|
using PlexRequests.Helpers;
|
||||||
|
using PlexRequests.Store;
|
||||||
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
|
namespace PlexRequests.UI.Helpers
|
||||||
|
{
|
||||||
|
public class TvSender
|
||||||
|
{
|
||||||
|
public TvSender(ISonarrApi sonarrApi, ISickRageApi srApi)
|
||||||
|
{
|
||||||
|
SonarrApi = sonarrApi;
|
||||||
|
SickrageApi = srApi;
|
||||||
|
}
|
||||||
|
private ISonarrApi SonarrApi { get; }
|
||||||
|
private ISickRageApi SickrageApi { get; }
|
||||||
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
public SonarrAddSeries SendToSonarr(SonarrSettings sonarrSettings, RequestedModel model)
|
||||||
|
{
|
||||||
|
int qualityProfile;
|
||||||
|
int.TryParse(sonarrSettings.QualityProfile, out qualityProfile);
|
||||||
|
var result = SonarrApi.AddSeries(model.ProviderId, model.Title, qualityProfile,
|
||||||
|
sonarrSettings.SeasonFolders, sonarrSettings.RootPath, model.LatestTv, sonarrSettings.ApiKey,
|
||||||
|
sonarrSettings.FullUri);
|
||||||
|
|
||||||
|
Log.Trace("Sonarr Add Result: ");
|
||||||
|
Log.Trace(result.DumpJson());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SickRageTvAdd SendToSickRage(SickRageSettings sickRageSettings, RequestedModel model)
|
||||||
|
{
|
||||||
|
var result = SickrageApi.AddSeries(model.ProviderId, model.LatestTv, sickRageSettings.QualityProfile,
|
||||||
|
sickRageSettings.ApiKey, sickRageSettings.FullUri);
|
||||||
|
|
||||||
|
Log.Trace("SickRage Add Result: ");
|
||||||
|
Log.Trace(result.DumpJson());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,8 +48,6 @@ namespace PlexRequests.UI.Models
|
||||||
public string AirsTime { get; set; }
|
public string AirsTime { get; set; }
|
||||||
public string Rating { get; set; }
|
public string Rating { get; set; }
|
||||||
public string ImdbId { get; set; }
|
public string ImdbId { get; set; }
|
||||||
public string Zap2ItId { get; set; }
|
|
||||||
public string Added { get; set; }
|
|
||||||
public int SiteRating { get; set; }
|
public int SiteRating { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -54,11 +54,13 @@ namespace PlexRequests.UI.Modules
|
||||||
private ISettingsService<AuthenticationSettings> AuthService { get; }
|
private ISettingsService<AuthenticationSettings> AuthService { get; }
|
||||||
private ISettingsService<PlexSettings> PlexService { get; }
|
private ISettingsService<PlexSettings> PlexService { get; }
|
||||||
private ISettingsService<SonarrSettings> SonarrService { get; }
|
private ISettingsService<SonarrSettings> SonarrService { get; }
|
||||||
|
private ISettingsService<SickRageSettings> SickRageService { get; }
|
||||||
private ISettingsService<EmailNotificationSettings> EmailService { get; }
|
private ISettingsService<EmailNotificationSettings> EmailService { get; }
|
||||||
private ISettingsService<PushbulletNotificationSettings> PushbulletService { get; }
|
private ISettingsService<PushbulletNotificationSettings> PushbulletService { get; }
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private ISonarrApi SonarrApi { get; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
private PushbulletApi PushbulletApi { get; }
|
private PushbulletApi PushbulletApi { get; }
|
||||||
|
private ICouchPotatoApi CpApi { get; }
|
||||||
|
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
public AdminModule(ISettingsService<PlexRequestSettings> rpService,
|
public AdminModule(ISettingsService<PlexRequestSettings> rpService,
|
||||||
|
@ -66,11 +68,13 @@ namespace PlexRequests.UI.Modules
|
||||||
ISettingsService<AuthenticationSettings> auth,
|
ISettingsService<AuthenticationSettings> auth,
|
||||||
ISettingsService<PlexSettings> plex,
|
ISettingsService<PlexSettings> plex,
|
||||||
ISettingsService<SonarrSettings> sonarr,
|
ISettingsService<SonarrSettings> sonarr,
|
||||||
|
ISettingsService<SickRageSettings> sickrage,
|
||||||
ISonarrApi sonarrApi,
|
ISonarrApi sonarrApi,
|
||||||
ISettingsService<EmailNotificationSettings> email,
|
ISettingsService<EmailNotificationSettings> email,
|
||||||
IPlexApi plexApi,
|
IPlexApi plexApi,
|
||||||
ISettingsService<PushbulletNotificationSettings> pbSettings,
|
ISettingsService<PushbulletNotificationSettings> pbSettings,
|
||||||
PushbulletApi pbApi) : base("admin")
|
PushbulletApi pbApi,
|
||||||
|
ICouchPotatoApi cpApi) : base("admin")
|
||||||
{
|
{
|
||||||
RpService = rpService;
|
RpService = rpService;
|
||||||
CpService = cpService;
|
CpService = cpService;
|
||||||
|
@ -82,6 +86,8 @@ namespace PlexRequests.UI.Modules
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
PushbulletService = pbSettings;
|
PushbulletService = pbSettings;
|
||||||
PushbulletApi = pbApi;
|
PushbulletApi = pbApi;
|
||||||
|
CpApi = cpApi;
|
||||||
|
SickRageService = sickrage;
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
this.RequiresAuthentication();
|
this.RequiresAuthentication();
|
||||||
|
@ -106,7 +112,11 @@ namespace PlexRequests.UI.Modules
|
||||||
Get["/sonarr"] = _ => Sonarr();
|
Get["/sonarr"] = _ => Sonarr();
|
||||||
Post["/sonarr"] = _ => SaveSonarr();
|
Post["/sonarr"] = _ => SaveSonarr();
|
||||||
|
|
||||||
|
Get["/sickrage"] = _ => Sickrage();
|
||||||
|
Post["/sickrage"] = _ => SaveSickrage();
|
||||||
|
|
||||||
Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles();
|
Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles();
|
||||||
|
Post["/cpprofiles"] = _ => GetCpProfiles();
|
||||||
|
|
||||||
Get["/emailnotification"] = _ => EmailNotifications();
|
Get["/emailnotification"] = _ => EmailNotifications();
|
||||||
Post["/emailnotification"] = _ => SaveEmailNotifications();
|
Post["/emailnotification"] = _ => SaveEmailNotifications();
|
||||||
|
@ -279,7 +289,11 @@ namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
return Response.AsJson(valid.SendJsonError());
|
return Response.AsJson(valid.SendJsonError());
|
||||||
}
|
}
|
||||||
|
var sickRageEnabled = SickRageService.GetSettings().Enabled;
|
||||||
|
if (sickRageEnabled)
|
||||||
|
{
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = "SickRage is enabled, we cannot enable Sonarr and SickRage" });
|
||||||
|
}
|
||||||
var result = SonarrService.SaveSettings(sonarrSettings);
|
var result = SonarrService.SaveSettings(sonarrSettings);
|
||||||
|
|
||||||
return Response.AsJson(result
|
return Response.AsJson(result
|
||||||
|
@ -287,6 +301,35 @@ namespace PlexRequests.UI.Modules
|
||||||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Negotiator Sickrage()
|
||||||
|
{
|
||||||
|
var settings = SickRageService.GetSettings();
|
||||||
|
|
||||||
|
return View["Sickrage", settings];
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response SaveSickrage()
|
||||||
|
{
|
||||||
|
var sickRageSettings = this.Bind<SickRageSettings>();
|
||||||
|
|
||||||
|
var valid = this.Validate(sickRageSettings);
|
||||||
|
if (!valid.IsValid)
|
||||||
|
{
|
||||||
|
return Response.AsJson(valid.SendJsonError());
|
||||||
|
}
|
||||||
|
|
||||||
|
var sonarrEnabled = SonarrService.GetSettings().Enabled;
|
||||||
|
if (sonarrEnabled)
|
||||||
|
{
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sonarr is enabled, we cannot enable Sonarr and SickRage" });
|
||||||
|
}
|
||||||
|
var result = SickRageService.SaveSettings(sickRageSettings);
|
||||||
|
|
||||||
|
return Response.AsJson(result
|
||||||
|
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for SickRage!" }
|
||||||
|
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||||
|
}
|
||||||
|
|
||||||
private Response GetSonarrQualityProfiles()
|
private Response GetSonarrQualityProfiles()
|
||||||
{
|
{
|
||||||
var settings = this.Bind<SonarrSettings>();
|
var settings = this.Bind<SonarrSettings>();
|
||||||
|
@ -354,5 +397,13 @@ namespace PlexRequests.UI.Modules
|
||||||
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Pushbullet Notifications!" }
|
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Pushbullet Notifications!" }
|
||||||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response GetCpProfiles()
|
||||||
|
{
|
||||||
|
var settings = this.Bind<CouchPotatoSettings>();
|
||||||
|
var profiles = CpApi.GetProfiles(settings.FullUri, settings.ApiKey);
|
||||||
|
|
||||||
|
return Response.AsJson(profiles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -43,7 +43,7 @@ namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
|
|
||||||
public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi,
|
public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi,
|
||||||
ISettingsService<AuthenticationSettings> authSettings) : base("test")
|
ISettingsService<AuthenticationSettings> authSettings, ISickRageApi srApi) : base("test")
|
||||||
{
|
{
|
||||||
this.RequiresAuthentication();
|
this.RequiresAuthentication();
|
||||||
|
|
||||||
|
@ -51,10 +51,12 @@ namespace PlexRequests.UI.Modules
|
||||||
SonarrApi = sonarrApi;
|
SonarrApi = sonarrApi;
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
AuthSettings = authSettings;
|
AuthSettings = authSettings;
|
||||||
|
SickRageApi = srApi;
|
||||||
|
|
||||||
Post["/cp"] = _ => CouchPotatoTest();
|
Post["/cp"] = _ => CouchPotatoTest();
|
||||||
Post["/sonarr"] = _ => SonarrTest();
|
Post["/sonarr"] = _ => SonarrTest();
|
||||||
Post["/plex"] = _ => PlexTest();
|
Post["/plex"] = _ => PlexTest();
|
||||||
|
Post["/sickrage"] = _ => SickRageTest();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ namespace PlexRequests.UI.Modules
|
||||||
private ISonarrApi SonarrApi { get; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
private ICouchPotatoApi CpApi { get; }
|
private ICouchPotatoApi CpApi { get; }
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
|
private ISickRageApi SickRageApi { get; }
|
||||||
private ISettingsService<AuthenticationSettings> AuthSettings { get; }
|
private ISettingsService<AuthenticationSettings> AuthSettings { get; }
|
||||||
|
|
||||||
private Response CouchPotatoTest()
|
private Response CouchPotatoTest()
|
||||||
|
@ -99,7 +102,7 @@ namespace PlexRequests.UI.Modules
|
||||||
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Sonarr, please check your settings." });
|
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Sonarr, please check your settings." });
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (ApplicationException e) // Exceptions are expected if we cannot connect so we will just log and swallow them.
|
catch (ApplicationException e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
|
||||||
{
|
{
|
||||||
Log.Warn("Exception thrown when attempting to get Sonarr's status: ");
|
Log.Warn("Exception thrown when attempting to get Sonarr's status: ");
|
||||||
Log.Warn(e);
|
Log.Warn(e);
|
||||||
|
@ -128,7 +131,7 @@ namespace PlexRequests.UI.Modules
|
||||||
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Plex, please check your settings." });
|
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Plex, please check your settings." });
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (ApplicationException e) // Exceptions are expected if we cannot connect so we will just log and swallow them.
|
catch (ApplicationException e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
|
||||||
{
|
{
|
||||||
Log.Warn("Exception thrown when attempting to get Plex's status: ");
|
Log.Warn("Exception thrown when attempting to get Plex's status: ");
|
||||||
Log.Warn(e);
|
Log.Warn(e);
|
||||||
|
@ -140,5 +143,30 @@ namespace PlexRequests.UI.Modules
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response SickRageTest()
|
||||||
|
{
|
||||||
|
var sickRageSettings = this.Bind<SickRageSettings>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var status = SickRageApi.Ping(sickRageSettings.ApiKey, sickRageSettings.FullUri);
|
||||||
|
return status?.result == "success"
|
||||||
|
? Response.AsJson(new JsonResponseModel { Result = true, Message = "Connected to SickRage successfully!" })
|
||||||
|
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to SickRage, please check your settings." });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (ApplicationException e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
|
||||||
|
{
|
||||||
|
Log.Warn("Exception thrown when attempting to get SickRage's status: ");
|
||||||
|
Log.Warn(e);
|
||||||
|
var message = $"Could not connect to SickRage, please check your settings. <strong>Exception Message:</strong> {e.Message}";
|
||||||
|
if (e.InnerException != null)
|
||||||
|
{
|
||||||
|
message = $"Could not connect to SickRage, please check your settings. <strong>Exception Message:</strong> {e.InnerException.Message}";
|
||||||
|
}
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,7 +27,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using Nancy.Security;
|
using Nancy.Security;
|
||||||
|
|
||||||
|
@ -36,7 +36,9 @@ using PlexRequests.Api;
|
||||||
using PlexRequests.Api.Interfaces;
|
using PlexRequests.Api.Interfaces;
|
||||||
using PlexRequests.Core;
|
using PlexRequests.Core;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
|
using PlexRequests.Helpers;
|
||||||
using PlexRequests.Store;
|
using PlexRequests.Store;
|
||||||
|
using PlexRequests.UI.Helpers;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
namespace PlexRequests.UI.Modules
|
namespace PlexRequests.UI.Modules
|
||||||
|
@ -44,8 +46,8 @@ namespace PlexRequests.UI.Modules
|
||||||
public class ApprovalModule : BaseModule
|
public class ApprovalModule : BaseModule
|
||||||
{
|
{
|
||||||
|
|
||||||
public ApprovalModule(IRepository<RequestedModel> service, ISettingsService<CouchPotatoSettings> cpService, ICouchPotatoApi cpApi, ISonarrApi sonarrApi,
|
public ApprovalModule(IRequestService service, ISettingsService<CouchPotatoSettings> cpService, ICouchPotatoApi cpApi, ISonarrApi sonarrApi,
|
||||||
ISettingsService<SonarrSettings> sonarrSettings) : base("approval")
|
ISettingsService<SonarrSettings> sonarrSettings, ISickRageApi srApi, ISettingsService<SickRageSettings> srSettings) : base("approval")
|
||||||
{
|
{
|
||||||
this.RequiresAuthentication();
|
this.RequiresAuthentication();
|
||||||
|
|
||||||
|
@ -54,17 +56,21 @@ namespace PlexRequests.UI.Modules
|
||||||
CpApi = cpApi;
|
CpApi = cpApi;
|
||||||
SonarrApi = sonarrApi;
|
SonarrApi = sonarrApi;
|
||||||
SonarrSettings = sonarrSettings;
|
SonarrSettings = sonarrSettings;
|
||||||
|
SickRageApi = srApi;
|
||||||
|
SickRageSettings = srSettings;
|
||||||
|
|
||||||
Post["/approve"] = parameters => Approve((int)Request.Form.requestid);
|
Post["/approve"] = parameters => Approve((int)Request.Form.requestid);
|
||||||
Post["/approveall"] = x => ApproveAll();
|
Post["/approveall"] = x => ApproveAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IRepository<RequestedModel> Service { get; set; }
|
private IRequestService Service { get; }
|
||||||
|
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
private ISettingsService<SonarrSettings> SonarrSettings { get; set; }
|
private ISettingsService<SonarrSettings> SonarrSettings { get; }
|
||||||
|
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
||||||
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
||||||
private ISonarrApi SonarrApi { get; set; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
|
private ISickRageApi SickRageApi { get; }
|
||||||
private ICouchPotatoApi CpApi { get; }
|
private ICouchPotatoApi CpApi { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -74,6 +80,7 @@ namespace PlexRequests.UI.Modules
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private Response Approve(int requestId)
|
private Response Approve(int requestId)
|
||||||
{
|
{
|
||||||
|
Log.Info("approving request {0}", requestId);
|
||||||
if (!Context.CurrentUser.IsAuthenticated())
|
if (!Context.CurrentUser.IsAuthenticated())
|
||||||
{
|
{
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." });
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." });
|
||||||
|
@ -100,20 +107,63 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
private Response RequestTvAndUpdateStatus(RequestedModel request)
|
private Response RequestTvAndUpdateStatus(RequestedModel request)
|
||||||
{
|
{
|
||||||
var sonarrSettings = SonarrSettings.GetSettings();
|
var sender = new TvSender(SonarrApi, SickRageApi);
|
||||||
int qualityProfile;
|
|
||||||
int.TryParse(sonarrSettings.QualityProfile, out qualityProfile);
|
|
||||||
var result = SonarrApi.AddSeries(request.ProviderId, request.Title, qualityProfile,
|
|
||||||
sonarrSettings.SeasonFolders, sonarrSettings.RootPath, request.LatestTv, sonarrSettings.ApiKey,
|
|
||||||
sonarrSettings.FullUri);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(result.title))
|
var sonarrSettings = SonarrSettings.GetSettings();
|
||||||
|
if (sonarrSettings.Enabled)
|
||||||
{
|
{
|
||||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
Log.Trace("Sending to Sonarr");
|
||||||
|
var result = sender.SendToSonarr(sonarrSettings, request);
|
||||||
|
Log.Trace("Sonarr Result: ");
|
||||||
|
Log.Trace(result.DumpJson());
|
||||||
|
if (!string.IsNullOrEmpty(result.title))
|
||||||
|
{
|
||||||
|
Log.Info("Sent successfully, Approving request now.");
|
||||||
|
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 Sonarr but could not approve it in PlexRequests :("});
|
||||||
|
}
|
||||||
|
return Response.AsJson(new JsonResponseModel
|
||||||
|
{
|
||||||
|
Result = false,
|
||||||
|
Message = "Could not add the series to Sonarr"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var srSettings = SickRageSettings.GetSettings();
|
||||||
|
if (srSettings.Enabled)
|
||||||
|
{
|
||||||
|
Log.Trace("Sending to SickRage");
|
||||||
|
var result = sender.SendToSickRage(srSettings, request);
|
||||||
|
Log.Trace("SickRage Result: ");
|
||||||
|
Log.Trace(result.DumpJson());
|
||||||
|
if (result?.result == "success")
|
||||||
|
{
|
||||||
|
Log.Info("Sent successfully, Approving request now.");
|
||||||
|
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(new JsonResponseModel
|
||||||
|
{
|
||||||
|
Result = false,
|
||||||
|
Message = result?.message != null ? "<b>Message From SickRage: </b>" + result.message : "Could not add the series to SickRage"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return Response.AsJson(new JsonResponseModel
|
return Response.AsJson(new JsonResponseModel
|
||||||
{
|
{
|
||||||
Result = false, Message = "Could not add the series to Sonarr"
|
Result = false,
|
||||||
|
Message = "SickRage or Sonarr are not set up!"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +177,7 @@ namespace PlexRequests.UI.Modules
|
||||||
var cpSettings = CpService.GetSettings();
|
var cpSettings = CpService.GetSettings();
|
||||||
var cp = new CouchPotatoApi();
|
var cp = new CouchPotatoApi();
|
||||||
Log.Info("Adding movie to CP : {0}", request.Title);
|
Log.Info("Adding movie to CP : {0}", request.Title);
|
||||||
var result = cp.AddMovie(request.ImdbId, cpSettings.ApiKey, request.Title, cpSettings.FullUri);
|
var result = cp.AddMovie(request.ImdbId, cpSettings.ApiKey, request.Title, cpSettings.FullUri, cpSettings.ProfileId);
|
||||||
Log.Trace("Adding movie to CP result {0}", result);
|
Log.Trace("Adding movie to CP result {0}", result);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +185,7 @@ namespace PlexRequests.UI.Modules
|
||||||
request.Approved = true;
|
request.Approved = true;
|
||||||
|
|
||||||
// Update the record
|
// Update the record
|
||||||
var inserted = Service.Update(request);
|
var inserted = Service.UpdateRequest(request);
|
||||||
|
|
||||||
return Response.AsJson(inserted
|
return Response.AsJson(inserted
|
||||||
? new JsonResponseModel {Result = true}
|
? new JsonResponseModel {Result = true}
|
||||||
|
@ -184,18 +234,48 @@ namespace PlexRequests.UI.Modules
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Error("Could not approve send the movie {0} to couch potato!", r.Title);
|
Log.Error("Could not approve and send the movie {0} to couch potato!", r.Title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r.Type == RequestType.TvShow)
|
if (r.Type == RequestType.TvShow)
|
||||||
{
|
{
|
||||||
// TODO
|
var sender = new TvSender(SonarrApi,SickRageApi);
|
||||||
|
var sr = SickRageSettings.GetSettings();
|
||||||
|
var sonarr = SonarrSettings.GetSettings();
|
||||||
|
if (sr.Enabled)
|
||||||
|
{
|
||||||
|
var result = sender.SendToSickRage(sr, r);
|
||||||
|
if (result?.result == "success")
|
||||||
|
{
|
||||||
|
r.Approved = true;
|
||||||
|
updatedRequests.Add(r);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Error("Could not approve and send the TV {0} to SickRage!", r.Title);
|
||||||
|
Log.Error("SickRage Message: {0}", result?.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sonarr.Enabled)
|
||||||
|
{
|
||||||
|
var result = sender.SendToSonarr(sonarr, r);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
r.Approved = true;
|
||||||
|
updatedRequests.Add(r);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Error("Could not approve and send the TV {0} to Sonarr!", r.Title);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
var result = Service.UpdateAll(updatedRequests); return Response.AsJson(result
|
var result = Service.BatchUpdate(updatedRequests); return Response.AsJson(result
|
||||||
? new JsonResponseModel { Result = true }
|
? new JsonResponseModel { Result = true }
|
||||||
: new JsonResponseModel { Result = false, Message = "We could not approve all of the requests. Please try again or check the logs." });
|
: new JsonResponseModel { Result = false, Message = "We could not approve all of the requests. Please try again or check the logs." });
|
||||||
|
|
||||||
|
@ -208,11 +288,10 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool SendMovie(CouchPotatoSettings settings, RequestedModel r, ICouchPotatoApi cp)
|
private bool SendMovie(CouchPotatoSettings settings, RequestedModel r, ICouchPotatoApi cp)
|
||||||
{
|
{
|
||||||
Log.Info("Adding movie to CP : {0}", r.Title);
|
Log.Info("Adding movie to CP : {0}", r.Title);
|
||||||
var result = cp.AddMovie(r.ImdbId, settings.ApiKey, r.Title, settings.FullUri);
|
var result = cp.AddMovie(r.ImdbId, settings.ApiKey, r.Title, settings.FullUri, settings.ProfileId);
|
||||||
Log.Trace("Adding movie to CP result {0}", result);
|
Log.Trace("Adding movie to CP result {0}", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace PlexRequests.UI.Modules
|
||||||
public class RequestsModule : BaseModule
|
public class RequestsModule : BaseModule
|
||||||
{
|
{
|
||||||
|
|
||||||
public RequestsModule(IRepository<RequestedModel> service, ISettingsService<PlexRequestSettings> prSettings, ISettingsService<PlexSettings> plex) : base("requests")
|
public RequestsModule(IRequestService service, ISettingsService<PlexRequestSettings> prSettings, ISettingsService<PlexSettings> plex) : base("requests")
|
||||||
{
|
{
|
||||||
Service = service;
|
Service = service;
|
||||||
PrSettings = prSettings;
|
PrSettings = prSettings;
|
||||||
|
@ -64,7 +64,7 @@ namespace PlexRequests.UI.Modules
|
||||||
Post["/addnote"] = _ => AddNote((int)Request.Form.requestId, (string)Request.Form.noteArea);
|
Post["/addnote"] = _ => AddNote((int)Request.Form.requestId, (string)Request.Form.noteArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IRepository<RequestedModel> Service { get; }
|
private IRequestService Service { get; }
|
||||||
private ISettingsService<PlexRequestSettings> PrSettings { get; }
|
private ISettingsService<PlexRequestSettings> PrSettings { get; }
|
||||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ namespace PlexRequests.UI.Modules
|
||||||
Status = tv.Status,
|
Status = tv.Status,
|
||||||
ImdbId = tv.ImdbId,
|
ImdbId = tv.ImdbId,
|
||||||
Id = tv.Id,
|
Id = tv.Id,
|
||||||
PosterPath = tv.ProviderId.ToString(),
|
PosterPath = tv.PosterPath,
|
||||||
ReleaseDate = tv.ReleaseDate.Humanize(),
|
ReleaseDate = tv.ReleaseDate.Humanize(),
|
||||||
RequestedDate = tv.RequestedDate.Humanize(),
|
RequestedDate = tv.RequestedDate.Humanize(),
|
||||||
Approved = tv.Approved,
|
Approved = tv.Approved,
|
||||||
|
@ -140,7 +140,7 @@ namespace PlexRequests.UI.Modules
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentEntity = Service.Get(requestid);
|
var currentEntity = Service.Get(requestid);
|
||||||
Service.Delete(currentEntity);
|
Service.DeleteRequest(currentEntity);
|
||||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ namespace PlexRequests.UI.Modules
|
||||||
: string.Empty;
|
: string.Empty;
|
||||||
|
|
||||||
|
|
||||||
var result = Service.Update(originalRequest);
|
var result = Service.UpdateRequest(originalRequest);
|
||||||
return Response.AsJson(result
|
return Response.AsJson(result
|
||||||
? new JsonResponseModel { Result = true }
|
? new JsonResponseModel { Result = true }
|
||||||
: new JsonResponseModel { Result = false, Message = "Could not add issue, please try again or contact the administrator!" });
|
: new JsonResponseModel { Result = false, Message = "Could not add issue, please try again or contact the administrator!" });
|
||||||
|
@ -186,7 +186,7 @@ namespace PlexRequests.UI.Modules
|
||||||
originalRequest.Issues = IssueState.None;
|
originalRequest.Issues = IssueState.None;
|
||||||
originalRequest.OtherMessage = string.Empty;
|
originalRequest.OtherMessage = string.Empty;
|
||||||
|
|
||||||
var result = Service.Update(originalRequest);
|
var result = Service.UpdateRequest(originalRequest);
|
||||||
return Response.AsJson(result
|
return Response.AsJson(result
|
||||||
? new JsonResponseModel { Result = true }
|
? new JsonResponseModel { Result = true }
|
||||||
: new JsonResponseModel { Result = false, Message = "Could not clear issue, please try again or check the logs" });
|
: new JsonResponseModel { Result = false, Message = "Could not clear issue, please try again or check the logs" });
|
||||||
|
@ -202,7 +202,7 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
originalRequest.Available = available;
|
originalRequest.Available = available;
|
||||||
|
|
||||||
var result = Service.Update(originalRequest);
|
var result = Service.UpdateRequest(originalRequest);
|
||||||
return Response.AsJson(result
|
return Response.AsJson(result
|
||||||
? new { Result = true, Available = available, Message = string.Empty }
|
? new { Result = true, Available = available, Message = string.Empty }
|
||||||
: new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" });
|
: new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" });
|
||||||
|
@ -218,7 +218,7 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
originalRequest.AdminNote = noteArea;
|
originalRequest.AdminNote = noteArea;
|
||||||
|
|
||||||
var result = Service.Update(originalRequest);
|
var result = Service.UpdateRequest(originalRequest);
|
||||||
return Response.AsJson(result
|
return Response.AsJson(result
|
||||||
? new JsonResponseModel { Result = true }
|
? new JsonResponseModel { Result = true }
|
||||||
: new JsonResponseModel { Result = false, Message = "Could not update the notes, please try again or check the logs" });
|
: new JsonResponseModel { Result = false, Message = "Could not update the notes, please try again or check the logs" });
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#endregion
|
#endregion
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using Nancy.Responses.Negotiation;
|
using Nancy.Responses.Negotiation;
|
||||||
|
|
||||||
|
@ -39,6 +42,7 @@ using PlexRequests.Helpers;
|
||||||
using PlexRequests.Services.Interfaces;
|
using PlexRequests.Services.Interfaces;
|
||||||
using PlexRequests.Services.Notification;
|
using PlexRequests.Services.Notification;
|
||||||
using PlexRequests.Store;
|
using PlexRequests.Store;
|
||||||
|
using PlexRequests.UI.Helpers;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
namespace PlexRequests.UI.Modules
|
namespace PlexRequests.UI.Modules
|
||||||
|
@ -48,7 +52,7 @@ namespace PlexRequests.UI.Modules
|
||||||
public SearchModule(ICacheProvider cache, ISettingsService<CouchPotatoSettings> cpSettings,
|
public SearchModule(ICacheProvider cache, ISettingsService<CouchPotatoSettings> cpSettings,
|
||||||
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
|
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
|
||||||
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings,
|
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings,
|
||||||
ICouchPotatoApi cpApi) : base("search")
|
ISettingsService<SickRageSettings> sickRageService, ICouchPotatoApi cpApi, ISickRageApi srApi) : base("search")
|
||||||
{
|
{
|
||||||
CpService = cpSettings;
|
CpService = cpSettings;
|
||||||
PrService = prSettings;
|
PrService = prSettings;
|
||||||
|
@ -60,6 +64,8 @@ namespace PlexRequests.UI.Modules
|
||||||
SonarrApi = sonarrApi;
|
SonarrApi = sonarrApi;
|
||||||
SonarrService = sonarrSettings;
|
SonarrService = sonarrSettings;
|
||||||
CouchPotatoApi = cpApi;
|
CouchPotatoApi = cpApi;
|
||||||
|
SickRageService = sickRageService;
|
||||||
|
SickrageApi = srApi;
|
||||||
|
|
||||||
Get["/"] = parameters => RequestLoad();
|
Get["/"] = parameters => RequestLoad();
|
||||||
|
|
||||||
|
@ -76,11 +82,13 @@ namespace PlexRequests.UI.Modules
|
||||||
private ICouchPotatoApi CouchPotatoApi { get; }
|
private ICouchPotatoApi CouchPotatoApi { get; }
|
||||||
private ISonarrApi SonarrApi { get; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
private TheTvDbApi TvApi { get; }
|
private TheTvDbApi TvApi { get; }
|
||||||
|
private ISickRageApi SickrageApi { get; }
|
||||||
private IRequestService RequestService { get; }
|
private IRequestService RequestService { get; }
|
||||||
private ICacheProvider Cache { get; }
|
private ICacheProvider Cache { get; }
|
||||||
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
||||||
private ISettingsService<PlexRequestSettings> PrService { get; }
|
private ISettingsService<PlexRequestSettings> PrService { get; }
|
||||||
private ISettingsService<SonarrSettings> SonarrService { get; }
|
private ISettingsService<SonarrSettings> SonarrService { get; }
|
||||||
|
private ISettingsService<SickRageSettings> SickRageService { get; }
|
||||||
private IAvailabilityChecker Checker { get; }
|
private IAvailabilityChecker Checker { get; }
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
private string AuthToken => Cache.GetOrSet(CacheKeys.TvDbToken, TvApi.Authenticate, 50);
|
private string AuthToken => Cache.GetOrSet(CacheKeys.TvDbToken, TvApi.Authenticate, 50);
|
||||||
|
@ -104,41 +112,34 @@ namespace PlexRequests.UI.Modules
|
||||||
private Response SearchTvShow(string searchTerm)
|
private Response SearchTvShow(string searchTerm)
|
||||||
{
|
{
|
||||||
Log.Trace("Searching for TV Show {0}", searchTerm);
|
Log.Trace("Searching for TV Show {0}", searchTerm);
|
||||||
var tvShow = TvApi.SearchTv(searchTerm, AuthToken);
|
//var tvShow = TvApi.SearchTv(searchTerm, AuthToken);
|
||||||
|
var tvShow = new TvMazeApi().Search(searchTerm);
|
||||||
if (tvShow?.data == null)
|
if (!tvShow.Any())
|
||||||
{
|
{
|
||||||
Log.Trace("TV Show data is null");
|
Log.Trace("TV Show data is null");
|
||||||
return Response.AsJson("");
|
return Response.AsJson("");
|
||||||
}
|
}
|
||||||
var model = new List<SearchTvShowViewModel>();
|
var model = new List<SearchTvShowViewModel>();
|
||||||
|
|
||||||
foreach (var t in tvShow.data)
|
foreach (var t in tvShow)
|
||||||
{
|
{
|
||||||
model.Add(new SearchTvShowViewModel
|
model.Add(new SearchTvShowViewModel
|
||||||
{
|
{
|
||||||
Added = t.added,
|
|
||||||
AirsDayOfWeek = t.airsDayOfWeek,
|
|
||||||
AirsTime = t.airsTime,
|
|
||||||
Aliases = t.aliases,
|
|
||||||
// We are constructing the banner with the id:
|
// We are constructing the banner with the id:
|
||||||
// http://thetvdb.com/banners/_cache/posters/ID-1.jpg
|
// http://thetvdb.com/banners/_cache/posters/ID-1.jpg
|
||||||
Banner = t.id.ToString(),
|
Banner = t.show.image?.medium,
|
||||||
FirstAired = t.firstAired,
|
FirstAired = t.show.premiered,
|
||||||
Genre = t.genre,
|
Id = t.show.externals?.thetvdb ?? 0,
|
||||||
Id = t.id,
|
ImdbId = t.show.externals?.imdb,
|
||||||
ImdbId = t.imdbId,
|
Network = t.show.network?.name,
|
||||||
LastUpdated = t.lastUpdated,
|
NetworkId = t.show.network?.id.ToString(),
|
||||||
Network = t.network,
|
Overview = t.show.summary.RemoveHtml(),
|
||||||
NetworkId = t.networkId,
|
Rating = t.score.ToString(CultureInfo.CurrentUICulture),
|
||||||
Overview = t.overview,
|
Runtime = t.show.runtime.ToString(),
|
||||||
Rating = t.rating,
|
SeriesId = t.show.id,
|
||||||
Runtime = t.runtime,
|
SeriesName = t.show.name,
|
||||||
SeriesId = t.id,
|
|
||||||
SeriesName = t.seriesName,
|
Status = t.show.status,
|
||||||
SiteRating = t.siteRating,
|
|
||||||
Status = t.status,
|
|
||||||
Zap2ItId = t.zap2itId
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,12 +191,12 @@ namespace PlexRequests.UI.Modules
|
||||||
Log.Trace("Getting movie info from TheMovieDb");
|
Log.Trace("Getting movie info from TheMovieDb");
|
||||||
Log.Trace(movieInfo.DumpJson);
|
Log.Trace(movieInfo.DumpJson);
|
||||||
|
|
||||||
#if !DEBUG
|
//#if !DEBUG
|
||||||
if (CheckIfTitleExistsInPlex(movieInfo.Title))
|
if (CheckIfTitleExistsInPlex(movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
|
||||||
{
|
{
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{movieInfo.Title} is already in Plex!" });
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{movieInfo.Title} is already in Plex!" });
|
||||||
}
|
}
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
var model = new RequestedModel
|
var model = new RequestedModel
|
||||||
{
|
{
|
||||||
|
@ -219,13 +220,13 @@ namespace PlexRequests.UI.Modules
|
||||||
if (!settings.RequireApproval)
|
if (!settings.RequireApproval)
|
||||||
{
|
{
|
||||||
Log.Info("Adding movie to CP (No approval required)");
|
Log.Info("Adding movie to CP (No approval required)");
|
||||||
var result = CouchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title, cpSettings.FullUri);
|
var result = CouchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title, cpSettings.FullUri, cpSettings.ProfileId);
|
||||||
Log.Debug("Adding movie to CP result {0}", result);
|
Log.Debug("Adding movie to CP result {0}", result);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
model.Approved = true;
|
model.Approved = true;
|
||||||
Log.Debug("Adding movie to database requests (No approval required)");
|
Log.Debug("Adding movie to database requests (No approval required)");
|
||||||
RequestService.AddRequest(movieId, model);
|
RequestService.AddRequest(model);
|
||||||
|
|
||||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||||
}
|
}
|
||||||
|
@ -235,7 +236,7 @@ namespace PlexRequests.UI.Modules
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Log.Debug("Adding movie to database requests");
|
Log.Debug("Adding movie to database requests");
|
||||||
var id = RequestService.AddRequest(movieId, model);
|
var id = RequestService.AddRequest(model);
|
||||||
|
|
||||||
NotificationService.Publish(model.Title, model.RequestedBy);
|
NotificationService.Publish(model.Title, model.RequestedBy);
|
||||||
|
|
||||||
|
@ -262,28 +263,27 @@ namespace PlexRequests.UI.Modules
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "TV Show has already been requested!" });
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = "TV Show has already been requested!" });
|
||||||
}
|
}
|
||||||
|
|
||||||
var tvApi = new TheTvDbApi();
|
var tvApi = new TvMazeApi();
|
||||||
var token = GetTvDbAuthToken(tvApi);
|
|
||||||
|
|
||||||
var showInfo = tvApi.GetInformation(showId, token).data;
|
var showInfo = tvApi.ShowLookupByTheTvDbId(showId);
|
||||||
|
|
||||||
#if !DEBUG
|
//#if !DEBUG
|
||||||
if (CheckIfTitleExistsInPlex(showInfo.seriesName))
|
if (CheckIfTitleExistsInPlex(showInfo.name, showInfo.premiered?.Substring(0, 4))) // Take only the year Format = 2014-01-01
|
||||||
{
|
{
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{showInfo.seriesName} is already in Plex!" });
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{showInfo.name} is already in Plex!" });
|
||||||
}
|
}
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
DateTime firstAir;
|
DateTime firstAir;
|
||||||
DateTime.TryParse(showInfo.firstAired, out firstAir);
|
DateTime.TryParse(showInfo.premiered, out firstAir);
|
||||||
|
|
||||||
var model = new RequestedModel
|
var model = new RequestedModel
|
||||||
{
|
{
|
||||||
ProviderId = showInfo.id,
|
ProviderId = showInfo.externals?.thetvdb ?? 0,
|
||||||
Type = RequestType.TvShow,
|
Type = RequestType.TvShow,
|
||||||
Overview = showInfo.overview,
|
Overview = showInfo.summary.RemoveHtml(),
|
||||||
PosterPath = "http://image.tmdb.org/t/p/w150/" + showInfo.banner, // This is incorrect
|
PosterPath = showInfo.image?.medium,
|
||||||
Title = showInfo.seriesName,
|
Title = showInfo.name,
|
||||||
ReleaseDate = firstAir,
|
ReleaseDate = firstAir,
|
||||||
Status = showInfo.status,
|
Status = showInfo.status,
|
||||||
RequestedDate = DateTime.Now,
|
RequestedDate = DateTime.Now,
|
||||||
|
@ -298,36 +298,70 @@ namespace PlexRequests.UI.Modules
|
||||||
if (!settings.RequireApproval)
|
if (!settings.RequireApproval)
|
||||||
{
|
{
|
||||||
var sonarrSettings = SonarrService.GetSettings();
|
var sonarrSettings = SonarrService.GetSettings();
|
||||||
int qualityProfile;
|
var sender = new TvSender(SonarrApi, SickrageApi);
|
||||||
int.TryParse(sonarrSettings.QualityProfile, out qualityProfile);
|
if (sonarrSettings.Enabled)
|
||||||
var result = SonarrApi.AddSeries(model.ProviderId, model.Title, qualityProfile,
|
|
||||||
sonarrSettings.SeasonFolders, sonarrSettings.RootPath, model.LatestTv, sonarrSettings.ApiKey,
|
|
||||||
sonarrSettings.FullUri);
|
|
||||||
if (result != null)
|
|
||||||
{
|
{
|
||||||
model.Approved = true;
|
var result = sender.SendToSonarr(sonarrSettings, model);
|
||||||
Log.Debug("Adding tv to database requests (No approval required)");
|
if (result != null)
|
||||||
RequestService.AddRequest(showId, model);
|
{
|
||||||
|
model.Approved = true;
|
||||||
|
Log.Debug("Adding tv to database requests (No approval required & Sonarr)");
|
||||||
|
RequestService.AddRequest(model);
|
||||||
|
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||||
|
}
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something went wrong adding the movie to Sonarr! Please check your settings." });
|
||||||
|
|
||||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
|
||||||
}
|
}
|
||||||
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something went wrong adding the movie to CouchPotato! Please check your settings." });
|
|
||||||
|
var srSettings = SickRageService.GetSettings();
|
||||||
|
if (srSettings.Enabled)
|
||||||
|
{
|
||||||
|
var result = sender.SendToSickRage(srSettings, model);
|
||||||
|
if (result?.result == "success")
|
||||||
|
{
|
||||||
|
model.Approved = true;
|
||||||
|
Log.Debug("Adding tv to database requests (No approval required & SickRage)");
|
||||||
|
RequestService.AddRequest(model);
|
||||||
|
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||||
|
}
|
||||||
|
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." });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.AsJson("The request of TV Shows is not correctly set up. Please contact your admin.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestService.AddRequest(showId, model);
|
RequestService.AddRequest(model);
|
||||||
NotificationService.Publish(model.Title, model.RequestedBy);
|
NotificationService.Publish(model.Title, model.RequestedBy);
|
||||||
|
|
||||||
return Response.AsJson(new { Result = true });
|
return Response.AsJson(new { Result = true });
|
||||||
}
|
}
|
||||||
private string GetTvDbAuthToken(TheTvDbApi api)
|
|
||||||
|
private bool CheckIfTitleExistsInPlex(string title, string year)
|
||||||
{
|
{
|
||||||
return Cache.GetOrSet(CacheKeys.TvDbToken, api.Authenticate, 50);
|
var result = Checker.IsAvailable(title, year);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CheckIfTitleExistsInPlex(string title)
|
private Response SendToSickRage(SickRageSettings sickRageSettings, RequestedModel model)
|
||||||
{
|
{
|
||||||
var result = Checker.IsAvailable(title);
|
var result = SickrageApi.AddSeries(model.ProviderId, model.LatestTv, sickRageSettings.QualityProfile,
|
||||||
return result;
|
sickRageSettings.ApiKey, sickRageSettings.FullUri);
|
||||||
|
|
||||||
|
Log.Trace("SickRage Result: ");
|
||||||
|
Log.Trace(result.DumpJson());
|
||||||
|
|
||||||
|
if (result?.result == "success")
|
||||||
|
{
|
||||||
|
model.Approved = true;
|
||||||
|
Log.Debug("Adding tv to database requests (No approval required & SickRage)");
|
||||||
|
RequestService.AddRequest(model);
|
||||||
|
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||||
|
}
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something went wrong adding the movie to SickRage! Please check your settings." });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,6 +24,9 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
@ -98,15 +101,28 @@ namespace PlexRequests.UI.Modules
|
||||||
var signedIn = (PlexAuthentication)Api.SignIn(username, password);
|
var signedIn = (PlexAuthentication)Api.SignIn(username, password);
|
||||||
if (signedIn.user?.authentication_token != null)
|
if (signedIn.user?.authentication_token != null)
|
||||||
{
|
{
|
||||||
Log.Debug("Correct credentials, checking if the user is in the friends list");
|
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
|
||||||
authenticated = CheckIfUserIsInPlexFriends(username, settings.PlexAuthToken);
|
if (CheckIfUserIsOwner(settings.PlexAuthToken, signedIn.user?.username))
|
||||||
Log.Debug("Friends list result = {0}", authenticated);
|
{
|
||||||
|
Log.Debug("User is the account owner");
|
||||||
|
authenticated = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
authenticated = CheckIfUserIsInPlexFriends(username, settings.PlexAuthToken);
|
||||||
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(settings.UserAuthentication) // Check against the users in Plex
|
else if(settings.UserAuthentication) // Check against the users in Plex
|
||||||
{
|
{
|
||||||
Log.Debug("Need to auth");
|
Log.Debug("Need to auth");
|
||||||
authenticated = CheckIfUserIsInPlexFriends(username, settings.PlexAuthToken);
|
authenticated = CheckIfUserIsInPlexFriends(username, settings.PlexAuthToken);
|
||||||
|
if (CheckIfUserIsOwner(settings.PlexAuthToken, username))
|
||||||
|
{
|
||||||
|
Log.Debug("User is the account owner");
|
||||||
|
authenticated = true;
|
||||||
|
}
|
||||||
Log.Debug("Friends list result = {0}", authenticated);
|
Log.Debug("Friends list result = {0}", authenticated);
|
||||||
}
|
}
|
||||||
else if(!settings.UserAuthentication) // No auth, let them pass!
|
else if(!settings.UserAuthentication) // No auth, let them pass!
|
||||||
|
@ -127,6 +143,8 @@ namespace PlexRequests.UI.Modules
|
||||||
: new JsonResponseModel { Result = false, Message = "Incorrect User or Password"});
|
: new JsonResponseModel { Result = false, Message = "Incorrect User or Password"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Response Logout()
|
private Response Logout()
|
||||||
{
|
{
|
||||||
Log.Debug("Logging Out");
|
Log.Debug("Logging Out");
|
||||||
|
@ -137,12 +155,23 @@ namespace PlexRequests.UI.Modules
|
||||||
return Context.GetRedirect("~/userlogin");
|
return Context.GetRedirect("~/userlogin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckIfUserIsOwner(string authToken, string userName)
|
||||||
|
{
|
||||||
|
var userAccount = Api.GetAccount(authToken);
|
||||||
|
if (userAccount == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return userAccount.Username != null && userAccount.Username.Equals(userName, StringComparison.CurrentCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
private bool CheckIfUserIsInPlexFriends(string username, string authToken)
|
private bool CheckIfUserIsInPlexFriends(string username, string authToken)
|
||||||
{
|
{
|
||||||
var users = Api.GetUsers(authToken);
|
var users = Api.GetUsers(authToken);
|
||||||
Log.Debug("Plex Users: ");
|
Log.Debug("Plex Users: ");
|
||||||
Log.Debug(users.DumpJson());
|
Log.Debug(users.DumpJson());
|
||||||
return users.User.Any(x => x.Username == username);
|
var allUsers = users.User?.Where(x => !string.IsNullOrEmpty(x.Username));
|
||||||
|
return allUsers != null && allUsers.Any(x => x.Username.Equals(username, StringComparison.CurrentCultureIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsUserInDeniedList(string username, AuthenticationSettings settings)
|
private bool IsUserInDeniedList(string username, AuthenticationSettings settings)
|
||||||
|
|
|
@ -160,11 +160,13 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Bootstrapper.cs" />
|
<Compile Include="Bootstrapper.cs" />
|
||||||
|
<Compile Include="Helpers\TvSender.cs" />
|
||||||
<Compile Include="Helpers\ValidationHelper.cs" />
|
<Compile Include="Helpers\ValidationHelper.cs" />
|
||||||
<Compile Include="Validators\PushbulletSettingsValidator.cs" />
|
<Compile Include="Validators\PushbulletSettingsValidator.cs" />
|
||||||
<Compile Include="Validators\EmailNotificationSettingsValidator.cs" />
|
<Compile Include="Validators\EmailNotificationSettingsValidator.cs" />
|
||||||
<Compile Include="Validators\CouchPotatoValidator.cs" />
|
<Compile Include="Validators\CouchPotatoValidator.cs" />
|
||||||
<Compile Include="Validators\PlexValidator.cs" />
|
<Compile Include="Validators\PlexValidator.cs" />
|
||||||
|
<Compile Include="Validators\SickRageValidator.cs" />
|
||||||
<Compile Include="Validators\SonarrValidator.cs" />
|
<Compile Include="Validators\SonarrValidator.cs" />
|
||||||
<Content Include="Content\bootstrap-notify.min.js">
|
<Content Include="Content\bootstrap-notify.min.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
@ -320,6 +322,9 @@
|
||||||
<Content Include="Views\Admin\PushbulletNotifications.cshtml">
|
<Content Include="Views\Admin\PushbulletNotifications.cshtml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Views\Admin\Sickrage.cshtml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<None Include="Web.Debug.config">
|
<None Include="Web.Debug.config">
|
||||||
<DependentUpon>web.config</DependentUpon>
|
<DependentUpon>web.config</DependentUpon>
|
||||||
</None>
|
</None>
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace PlexRequests.UI
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var uri = string.Empty;
|
var port = -1;
|
||||||
if (args.Length > 0)
|
if (args.Length > 0)
|
||||||
{
|
{
|
||||||
Log.Info("We are going to use port {0} that was passed in", args[0]);
|
Log.Info("We are going to use port {0} that was passed in", args[0]);
|
||||||
|
@ -59,7 +59,7 @@ namespace PlexRequests.UI
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
uri = $"http://*:{portResult}";
|
port = portResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Trace("Getting product version");
|
Log.Trace("Getting product version");
|
||||||
|
@ -68,11 +68,10 @@ namespace PlexRequests.UI
|
||||||
var s = new Setup();
|
var s = new Setup();
|
||||||
s.SetupDb();
|
s.SetupDb();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(uri))
|
if (port == -1)
|
||||||
uri = GetStartupUri();
|
port = GetStartupPort();
|
||||||
|
|
||||||
;
|
var options = new StartOptions($"http://+:{port}")
|
||||||
var options = new StartOptions(uri)
|
|
||||||
{
|
{
|
||||||
ServerFactory = "Microsoft.Owin.Host.HttpListener"
|
ServerFactory = "Microsoft.Owin.Host.HttpListener"
|
||||||
};
|
};
|
||||||
|
@ -81,7 +80,7 @@ namespace PlexRequests.UI
|
||||||
|
|
||||||
using (WebApp.Start<Startup>(options))
|
using (WebApp.Start<Startup>(options))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Request Plex is running on {uri}");
|
Console.WriteLine($"Request Plex is running on the following port: {port}");
|
||||||
Console.WriteLine("Press any key to exit");
|
Console.WriteLine("Press any key to exit");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
}
|
}
|
||||||
|
@ -101,19 +100,19 @@ namespace PlexRequests.UI
|
||||||
Console.WriteLine($"Version: {assemblyVer}");
|
Console.WriteLine($"Version: {assemblyVer}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetStartupUri()
|
private static int GetStartupPort()
|
||||||
{
|
{
|
||||||
Log.Trace("Getting startup URI");
|
Log.Trace("Getting startup Port");
|
||||||
var uri = "http://*:3579/";
|
var port = 3579;
|
||||||
var service = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
|
var service = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
|
||||||
var settings = service.GetSettings();
|
var settings = service.GetSettings();
|
||||||
Log.Trace("Port: {0}", settings.Port);
|
Log.Trace("Port: {0}", settings.Port);
|
||||||
if (settings.Port != 0)
|
if (settings.Port != 0)
|
||||||
{
|
{
|
||||||
uri = $"http://*:{settings.Port}";
|
port = settings.Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
return uri;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ConfigureTargets(string connectionString)
|
private static void ConfigureTargets(string connectionString)
|
||||||
|
|
43
PlexRequests.UI/Validators/SickRageValidator.cs
Normal file
43
PlexRequests.UI/Validators/SickRageValidator.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: SonarrValidator.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 FluentValidation;
|
||||||
|
|
||||||
|
using PlexRequests.Core.SettingModels;
|
||||||
|
|
||||||
|
namespace PlexRequests.UI.Validators
|
||||||
|
{
|
||||||
|
public class SickRageValidator : AbstractValidator<SickRageSettings>
|
||||||
|
{
|
||||||
|
public SickRageValidator()
|
||||||
|
{
|
||||||
|
RuleFor(request => request.ApiKey).NotEmpty().WithMessage("You must specify a Api Key.");
|
||||||
|
RuleFor(request => request.Ip).NotEmpty().WithMessage("You must specify a IP/Host name.");
|
||||||
|
RuleFor(request => request.Port).NotEmpty().WithMessage("You must specify a Port.");
|
||||||
|
RuleFor(request => request.QualityProfile).NotEmpty().WithMessage("You must specify a Quality Profile.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,8 +37,35 @@
|
||||||
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" value="@Model.ApiKey">
|
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" value="@Model.ApiKey">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
@if (Model.Ssl)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Ssl" name="Ssl" checked="checked"><text>SSL</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Ssl" name="Ssl"><text>SSL</text>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button type="submit" id="getProfiles" class="btn btn-primary-outline">Get Quality Profiles</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="select" class="control-label">Quality Profiles</label>
|
||||||
|
<div id="profiles">
|
||||||
|
<select class="form-control" id="select"></select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div>
|
||||||
<button id="testCp" type="submit" class="btn btn-primary-outline">Test Connectivity</button>
|
<button id="testCp" type="submit" class="btn btn-primary-outline">Test Connectivity</button>
|
||||||
|
@ -62,9 +89,58 @@
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(Model.ProfileId))
|
||||||
|
{
|
||||||
|
<text>
|
||||||
|
var qualitySelected = '@Model.ProfileId';
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
data: $form.serialize(),
|
||||||
|
url: "cpprofiles",
|
||||||
|
dataType: "json",
|
||||||
|
success: function(response) {
|
||||||
|
response.list.forEach(function(result) {
|
||||||
|
if (result._id == qualitySelected) {
|
||||||
|
|
||||||
|
$("#select").append("<option selected='selected' value='" + result._id + "'>" + result.label + "</option>");
|
||||||
|
} else {
|
||||||
|
$("#select").append("<option value='" + result._id + "'>" + result.label + "</option>");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function(e) {
|
||||||
|
console.log(e);
|
||||||
|
generateNotify("Something went wrong!", "danger");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</text>
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#getProfiles').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
data: $form.serialize(),
|
||||||
|
url: "cpprofiles",
|
||||||
|
dataType: "json",
|
||||||
|
success: function (response) {
|
||||||
|
response.list.forEach(function (result) {
|
||||||
|
$("#select").append("<option value='" + result._id + "'>" + result.label + "</option>");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function (e) {
|
||||||
|
console.log(e);
|
||||||
|
generateNotify("Something went wrong!", "danger");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$('#testCp').click(function (e) {
|
$('#testCp').click(function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var $form = $("#mainForm");
|
var $form = $("#mainForm");
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: $form.prop("method"),
|
type: $form.prop("method"),
|
||||||
url: "/test/cp",
|
url: "/test/cp",
|
||||||
|
@ -94,9 +170,13 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var $form = $("#mainForm");
|
var $form = $("#mainForm");
|
||||||
|
var qualityProfile = $("#profiles option:selected").val();
|
||||||
|
var data = $form.serialize();
|
||||||
|
data = data + "&profileId=" + qualityProfile;
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: $form.prop("method"),
|
type: $form.prop("method"),
|
||||||
data: $form.serialize(),
|
data: data,
|
||||||
url: $form.prop("action"),
|
url: $form.prop("action"),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
|
@ -112,6 +192,6 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
172
PlexRequests.UI/Views/Admin/Sickrage.cshtml
Normal file
172
PlexRequests.UI/Views/Admin/Sickrage.cshtml
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
@Html.Partial("_Sidebar")
|
||||||
|
@{
|
||||||
|
int port;
|
||||||
|
if (Model.Port == 0)
|
||||||
|
{
|
||||||
|
port = 8081;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
port = Model.Port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<div class="col-sm-8 col-sm-push-1">
|
||||||
|
<form class="form-horizontal" method="POST" id="mainForm">
|
||||||
|
<fieldset>
|
||||||
|
<legend>SickRage Settings</legend>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
@if (Model.Enabled)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Enabled" name="Enabled" checked="checked"><text>Enabled</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Enabled" name="Enabled"><text>Enabled</text>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="Ip" class="control-label">SickRage Hostname or IP</label>
|
||||||
|
<div class="">
|
||||||
|
<input type="text" class="form-control form-control-custom " id="Ip" name="Ip" placeholder="localhost" value="@Model.Ip">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="portNumber" class="control-label">Port</label>
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" value="@port">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="ApiKey" class="control-label">SickRage API Key</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" value="@Model.ApiKey">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
@if (Model.Ssl)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Ssl" name="Ssl" checked="checked"><text>SSL</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Ssl" name="Ssl"><text>SSL</text>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="profiles" class="control-label">Quality Profiles</label>
|
||||||
|
<div id="profiles">
|
||||||
|
<select class="form-control" value="selected">
|
||||||
|
<option id="default" value="default">Use Deafult</option>
|
||||||
|
<option id="sdtv" value="sdtv">SD TV</option>
|
||||||
|
<option id="sddvd" value="sddvd">SD DVD</option>
|
||||||
|
<option id="hdtv" value="hdtv">HD TV</option>
|
||||||
|
<option id="rawhdtv" value="rawhdtv">Raw HD TV</option>
|
||||||
|
<option id="hdwebdl" value="hdwebdl">HD Web DL</option>
|
||||||
|
<option id="fullhdwebdl" value="fullhdwebdl">Full HD Web DL</option>
|
||||||
|
<option id="hdbluray" value="hdbluray">HD Bluray</option>
|
||||||
|
<option id="fullhdbluray" value="fullhdbluray">Full HD Bluray</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button id="testSickRage" type="submit" class="btn btn-primary-outline">Test Connectivity</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button id="save" type="submit" class="btn btn-primary-outline ">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(Model.QualityProfile))
|
||||||
|
{
|
||||||
|
<text>
|
||||||
|
var qualitySelected = '@Model.QualityProfile';
|
||||||
|
$('#' + qualitySelected).prop("selected", "selected");
|
||||||
|
</text>
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#save').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var port = $('#portNumber').val();
|
||||||
|
if (isNaN(port)) {
|
||||||
|
generateNotify("You must specify a Port.", "warning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var qualityProfile = $("#profiles option:selected").val();
|
||||||
|
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
|
||||||
|
var data = $form.serialize();
|
||||||
|
data = data + "&qualityProfile=" + qualityProfile;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
data: data,
|
||||||
|
url: $form.prop("action"),
|
||||||
|
dataType: "json",
|
||||||
|
success: function (response) {
|
||||||
|
if (response.result === true) {
|
||||||
|
generateNotify("Success!", "success");
|
||||||
|
} else {
|
||||||
|
generateNotify(response.message, "warning");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (e) {
|
||||||
|
console.log(e);
|
||||||
|
generateNotify("Something went wrong!", "danger");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#testSickRage').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
url: "/test/sickrage",
|
||||||
|
data: $form.serialize(),
|
||||||
|
dataType: "json",
|
||||||
|
success: function (response) {
|
||||||
|
console.log(response);
|
||||||
|
if (response.result === true) {
|
||||||
|
generateNotify(response.message, "success");
|
||||||
|
} else {
|
||||||
|
generateNotify(response.message, "warning");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (e) {
|
||||||
|
console.log(e);
|
||||||
|
generateNotify("Something went wrong!", "danger");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -14,7 +14,20 @@
|
||||||
<form class="form-horizontal" method="POST" id="mainForm">
|
<form class="form-horizontal" method="POST" id="mainForm">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Sonarr Settings</legend>
|
<legend>Sonarr Settings</legend>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
@if (Model.Enabled)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Enabled" name="Enabled" checked="checked"><text>Enabled</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Enabled" name="Enabled"><text>Enabled</text>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="Ip" class="control-label">Sonarr Hostname or IP</label>
|
<label for="Ip" class="control-label">Sonarr Hostname or IP</label>
|
||||||
<div class="">
|
<div class="">
|
||||||
|
@ -37,7 +50,20 @@
|
||||||
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" value="@Model.ApiKey">
|
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" value="@Model.ApiKey">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
@if (Model.Ssl)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Ssl" name="Ssl" checked="checked"><text>SSL</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Ssl" name="Ssl"><text>SSL</text>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div>
|
||||||
<button type="submit" id="getProfiles" class="btn btn-primary-outline">Get Quality Profiles</button>
|
<button type="submit" id="getProfiles" class="btn btn-primary-outline">Get Quality Profiles</button>
|
||||||
|
@ -108,7 +134,7 @@
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
response.forEach(function(result) {
|
response.forEach(function(result) {
|
||||||
if (result.id == qualitySelected) {
|
if (result.id == qualitySelected) {
|
||||||
|
|
||||||
$("#select").append("<option selected='selected' value='" + result.id + "'>" + result.name + "</option>");
|
$("#select").append("<option selected='selected' value='" + result.id + "'>" + result.name + "</option>");
|
||||||
} else {
|
} else {
|
||||||
$("#select").append("<option value='" + result.id + "'>" + result.name + "</option>");
|
$("#select").append("<option value='" + result.id + "'>" + result.name + "</option>");
|
||||||
|
@ -120,11 +146,6 @@
|
||||||
generateNotify("Something went wrong!", "danger");
|
generateNotify("Something went wrong!", "danger");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</text>
|
</text>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,14 @@
|
||||||
{
|
{
|
||||||
<a class="list-group-item" href="/admin/sonarr">Sonarr</a>
|
<a class="list-group-item" href="/admin/sonarr">Sonarr</a>
|
||||||
}
|
}
|
||||||
@*<a class="list-group-item" href="/admin/sickbeard">Sickbeard Settings</a>*@
|
@if (Context.Request.Path == "/admin/sickrage")
|
||||||
|
{
|
||||||
|
<a class="list-group-item active" href="/admin/sickrage">SickRage</a>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<a class="list-group-item" href="/admin/sickrage">SickRage</a>
|
||||||
|
}
|
||||||
|
|
||||||
@if (Context.Request.Path == "/admin/emailnotification")
|
@if (Context.Request.Path == "/admin/emailnotification")
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
{{/if_eq}}
|
{{/if_eq}}
|
||||||
{{#if_eq type "tv"}}
|
{{#if_eq type "tv"}}
|
||||||
{{#if posterPath}}
|
{{#if posterPath}}
|
||||||
<img class="img-responsive" width="150" src="http://thetvdb.com/banners/_cache/posters/{{posterPath}}-1.jpg" alt="poster">
|
<img class="img-responsive" width="150" src="{{posterPath}}" alt="poster">
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if_eq}}
|
{{/if_eq}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -95,14 +95,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div>Requested By: {{requestedBy}}</div>
|
<div>Requested By: {{requestedBy}}</div>
|
||||||
<div>Requested Date: {{requestedDate}}</div>
|
<div>Requested Date: {{requestedDate}}</div>
|
||||||
<div id="issueArea">
|
<div id="issueArea{{requestId}}">
|
||||||
{{#if otherMessage}}
|
{{#if otherMessage}}
|
||||||
<div>Message: {{otherMessage}}</div>
|
<div>Message: {{otherMessage}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div>Issue: {{issues}}</div>
|
<div>Issue: {{issues}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div id="adminNotesArea">
|
<div id="adminNotesArea{{requestId}}">
|
||||||
{{#if adminNote}}
|
{{#if adminNote}}
|
||||||
<div>Note from Admin: {{adminNote}}</div>
|
<div>Note from Admin: {{adminNote}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
{{/if_eq}}
|
{{/if_eq}}
|
||||||
{{#if_eq type "tv"}}
|
{{#if_eq type "tv"}}
|
||||||
{{#if posterPath}}
|
{{#if posterPath}}
|
||||||
<img class="img-responsive" width="150" src="http://thetvdb.com/banners/_cache/posters/{{posterPath}}-1.jpg" alt="poster">
|
<img class="img-responsive" width="150" src="{{posterPath}}" alt="poster">
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if_eq}}
|
{{/if_eq}}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<head>
|
<head>
|
||||||
<title>Plex Requests</title>
|
<title>Plex Requests</title>
|
||||||
<!-- Styles -->
|
<!-- Styles -->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="~/Content/custom.min.css" type="text/css"/>
|
<link rel="stylesheet" href="~/Content/custom.min.css" type="text/css"/>
|
||||||
<link rel="stylesheet" href="~/Content/bootstrap.css" type="text/css"/>
|
<link rel="stylesheet" href="~/Content/bootstrap.css" type="text/css"/>
|
||||||
<link rel="stylesheet" href="~/Content/font-awesome.css" type="text/css"/>
|
<link rel="stylesheet" href="~/Content/font-awesome.css" type="text/css"/>
|
||||||
|
@ -89,4 +90,4 @@
|
||||||
@RenderBody()
|
@RenderBody()
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,7 +12,8 @@ I wanted to write a similar application in .Net!
|
||||||
|
|
||||||
#Features
|
#Features
|
||||||
|
|
||||||
* Integration with [TheMovieDB](https://www.themoviedb.org/) for all Movies and TV shows
|
* Integration with [TheMovieDB](https://www.themoviedb.org/) for all Movies
|
||||||
|
* Integration with [TVMaze](www.tvmaze.com) for all TV shows!
|
||||||
* Secure authentication
|
* Secure authentication
|
||||||
* [Sonarr](https://sonarr.tv/) integration (SickRage/Sickbeard TBD)
|
* [Sonarr](https://sonarr.tv/) integration (SickRage/Sickbeard TBD)
|
||||||
* [CouchPotato](https://couchpota.to/) integration
|
* [CouchPotato](https://couchpota.to/) integration
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
version: 1.3.{build}
|
version: 1.4.{build}
|
||||||
configuration: Release
|
configuration: Release
|
||||||
assembly_info:
|
assembly_info:
|
||||||
patch: true
|
patch: true
|
||||||
file: '**\AssemblyInfo.*'
|
file: '**\AssemblyInfo.*'
|
||||||
assembly_version: '1.3.0'
|
assembly_version: '1.4.0'
|
||||||
assembly_file_version: '{version}'
|
assembly_file_version: '{version}'
|
||||||
assembly_informational_version: '1.3.0'
|
assembly_informational_version: '1.4.0'
|
||||||
before_build:
|
before_build:
|
||||||
- cmd: appveyor-retry nuget restore
|
- cmd: appveyor-retry nuget restore
|
||||||
build:
|
build:
|
||||||
|
@ -18,7 +18,7 @@ after_build:
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
- provider: GitHub
|
- provider: GitHub
|
||||||
release: PlexRequests $(appveyor_build_version)
|
release: PlexRequests v$(appveyor_build_version)
|
||||||
auth_token:
|
auth_token:
|
||||||
secure: jDpp1/WUQl3uN41fNI3VeZoRZbDiDfs3GPQ1v+C5ZNE3cWdnUvuJfCCfUbYUV1Rp
|
secure: jDpp1/WUQl3uN41fNI3VeZoRZbDiDfs3GPQ1v+C5ZNE3cWdnUvuJfCCfUbYUV1Rp
|
||||||
draft: true
|
draft: true
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue