mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-20 13:23:20 -07:00
The move!
This commit is contained in:
parent
1daf480b1b
commit
25526cc4d9
1147 changed files with 85 additions and 8524 deletions
16
src/.gitignore
vendored
Normal file
16
src/.gitignore
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
../app/**/*.js
|
||||
../app/**/*.js.map
|
||||
../wwwroot/**
|
||||
|
||||
# dependencies
|
||||
../node_modules
|
||||
../bower_components
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage/*
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/typings
|
6
src/Build/publish windows.bat
Normal file
6
src/Build/publish windows.bat
Normal file
|
@ -0,0 +1,6 @@
|
|||
;https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/
|
||||
cd ..
|
||||
dotnet restore
|
||||
dotnet publish -c Release /p:AppRuntimeIdentifier=win10-x64
|
||||
|
||||
exit
|
9
src/Build/publish.bat
Normal file
9
src/Build/publish.bat
Normal file
|
@ -0,0 +1,9 @@
|
|||
;https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/
|
||||
cd ..
|
||||
dotnet restore
|
||||
dotnet publish -c Release /p:AppRuntimeIdentifier=win10-x64
|
||||
dotnet publish -c Release /p:AppRuntimeIdentifier=osx.10.12-x64
|
||||
dotnet publish -c Release /p:AppRuntimeIdentifier=ubuntu.16.10-x64
|
||||
dotnet publish -c Release /p:AppRuntimeIdentifier=debian.8-x64
|
||||
|
||||
exit
|
78
src/Ombi.Api.Emby/EmbyApi.cs
Normal file
78
src/Ombi.Api.Emby/EmbyApi.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Api.Emby.Models;
|
||||
using Ombi.Helpers;
|
||||
|
||||
namespace Ombi.Api.Emby
|
||||
{
|
||||
public class EmbyApi : IEmbyApi
|
||||
{
|
||||
public EmbyApi()
|
||||
{
|
||||
Api = new Api();
|
||||
}
|
||||
|
||||
private Api Api { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all users from the Emby Instance
|
||||
/// </summary>
|
||||
/// <param name="baseUri"></param>
|
||||
/// <param name="apiKey"></param>
|
||||
public async Task<List<EmbyUser>> GetUsers(string baseUri, string apiKey)
|
||||
{
|
||||
var request = new Request("emby/users", baseUri, HttpMethod.Get);
|
||||
|
||||
AddHeaders(request, apiKey);
|
||||
var obj = await Api.Request<List<EmbyUser>>(request);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public async Task<EmbySystemInfo> GetSystemInformation(string apiKey, string baseUrl)
|
||||
{
|
||||
var request = new Request("emby/System/Info", baseUrl, HttpMethod.Get);
|
||||
|
||||
AddHeaders(request, apiKey);
|
||||
|
||||
var obj = await Api.Request<EmbySystemInfo>(request);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public async Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri)
|
||||
{
|
||||
var request = new Request("emby/users/authenticatebyname", baseUri, HttpMethod.Post);
|
||||
|
||||
|
||||
var body = new
|
||||
{
|
||||
username,
|
||||
password = password.GetSha1Hash().ToLower(),
|
||||
passwordMd5 = password.CalcuateMd5Hash()
|
||||
};
|
||||
|
||||
request.AddJsonBody(body);
|
||||
|
||||
request.AddHeader("X-Emby-Authorization",
|
||||
$"MediaBrowser Client=\"Ombi\", Device=\"Ombi\", DeviceId=\"v3\", Version=\"v3\"");
|
||||
AddHeaders(request, apiKey);
|
||||
|
||||
var obj = await Api.Request<EmbyUser>(request);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static void AddHeaders(Request req, string apiKey)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(apiKey))
|
||||
{
|
||||
req.AddHeader("X-MediaBrowser-Token", apiKey);
|
||||
}
|
||||
req.AddHeader("Accept", "application/json");
|
||||
req.AddContentHeader("Content-Type", "application/json");
|
||||
req.AddHeader("Device", "Ombi");
|
||||
}
|
||||
}
|
||||
}
|
14
src/Ombi.Api.Emby/IEmbyApi.cs
Normal file
14
src/Ombi.Api.Emby/IEmbyApi.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Api.Emby.Models;
|
||||
|
||||
namespace Ombi.Api.Emby
|
||||
{
|
||||
public interface IEmbyApi
|
||||
{
|
||||
Task<EmbySystemInfo> GetSystemInformation(string apiKey, string baseUrl);
|
||||
Task<List<EmbyUser>> GetUsers(string baseUri, string apiKey);
|
||||
Task<EmbyUser> LogIn(string username, string password, string apiKey, string baseUri);
|
||||
}
|
||||
}
|
45
src/Ombi.Api.Emby/Models/EmbyConfiguration.cs
Normal file
45
src/Ombi.Api.Emby/Models/EmbyConfiguration.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: EmbyConfiguration.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Api.Emby.Models
|
||||
{
|
||||
public class EmbyConfiguration
|
||||
{
|
||||
public bool PlayDefaultAudioTrack { get; set; }
|
||||
public bool DisplayMissingEpisodes { get; set; }
|
||||
public bool DisplayUnairedEpisodes { get; set; }
|
||||
public object[] GroupedFolders { get; set; }
|
||||
public string SubtitleMode { get; set; }
|
||||
public bool DisplayCollectionsView { get; set; }
|
||||
public bool EnableLocalPassword { get; set; }
|
||||
public object[] OrderedViews { get; set; }
|
||||
public object[] LatestItemsExcludes { get; set; }
|
||||
public bool HidePlayedInLatest { get; set; }
|
||||
public bool RememberAudioSelections { get; set; }
|
||||
public bool RememberSubtitleSelections { get; set; }
|
||||
public bool EnableNextEpisodeAutoPlay { get; set; }
|
||||
}
|
||||
}
|
59
src/Ombi.Api.Emby/Models/EmbyPolicy.cs
Normal file
59
src/Ombi.Api.Emby/Models/EmbyPolicy.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: EmbyPolicy.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Api.Emby.Models
|
||||
{
|
||||
public class EmbyPolicy
|
||||
{
|
||||
public bool IsAdministrator { get; set; }
|
||||
public bool IsHidden { get; set; }
|
||||
public bool IsDisabled { get; set; }
|
||||
public object[] BlockedTags { get; set; }
|
||||
public bool EnableUserPreferenceAccess { get; set; }
|
||||
public object[] AccessSchedules { get; set; }
|
||||
public object[] BlockUnratedItems { get; set; }
|
||||
public bool EnableRemoteControlOfOtherUsers { get; set; }
|
||||
public bool EnableSharedDeviceControl { get; set; }
|
||||
public bool EnableLiveTvManagement { get; set; }
|
||||
public bool EnableLiveTvAccess { get; set; }
|
||||
public bool EnableMediaPlayback { get; set; }
|
||||
public bool EnableAudioPlaybackTranscoding { get; set; }
|
||||
public bool EnableVideoPlaybackTranscoding { get; set; }
|
||||
public bool EnablePlaybackRemuxing { get; set; }
|
||||
public bool EnableContentDeletion { get; set; }
|
||||
public bool EnableContentDownloading { get; set; }
|
||||
public bool EnableSync { get; set; }
|
||||
public bool EnableSyncTranscoding { get; set; }
|
||||
public object[] EnabledDevices { get; set; }
|
||||
public bool EnableAllDevices { get; set; }
|
||||
public object[] EnabledChannels { get; set; }
|
||||
public bool EnableAllChannels { get; set; }
|
||||
public object[] EnabledFolders { get; set; }
|
||||
public bool EnableAllFolders { get; set; }
|
||||
public int InvalidLoginAttemptCount { get; set; }
|
||||
public bool EnablePublicSharing { get; set; }
|
||||
}
|
||||
}
|
63
src/Ombi.Api.Emby/Models/EmbySystemInfo.cs
Normal file
63
src/Ombi.Api.Emby/Models/EmbySystemInfo.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: EmbySystemInfo.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Api.Emby.Models
|
||||
{
|
||||
public class EmbySystemInfo
|
||||
{
|
||||
public string SystemUpdateLevel { get; set; }
|
||||
public string OperatingSystemDisplayName { get; set; }
|
||||
public bool SupportsRunningAsService { get; set; }
|
||||
public string MacAddress { get; set; }
|
||||
public bool HasPendingRestart { get; set; }
|
||||
public bool SupportsLibraryMonitor { get; set; }
|
||||
public object[] InProgressInstallations { get; set; }
|
||||
public int WebSocketPortNumber { get; set; }
|
||||
public object[] CompletedInstallations { get; set; }
|
||||
public bool CanSelfRestart { get; set; }
|
||||
public bool CanSelfUpdate { get; set; }
|
||||
public object[] FailedPluginAssemblies { get; set; }
|
||||
public string ProgramDataPath { get; set; }
|
||||
public string ItemsByNamePath { get; set; }
|
||||
public string CachePath { get; set; }
|
||||
public string LogPath { get; set; }
|
||||
public string InternalMetadataPath { get; set; }
|
||||
public string TranscodingTempPath { get; set; }
|
||||
public int HttpServerPortNumber { get; set; }
|
||||
public bool SupportsHttps { get; set; }
|
||||
public int HttpsPortNumber { get; set; }
|
||||
public bool HasUpdateAvailable { get; set; }
|
||||
public bool SupportsAutoRunAtStartup { get; set; }
|
||||
public string EncoderLocationType { get; set; }
|
||||
public string SystemArchitecture { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
public string WanAddress { get; set; }
|
||||
public string ServerName { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string OperatingSystem { get; set; }
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
48
src/Ombi.Api.Emby/Models/EmbyUser.cs
Normal file
48
src/Ombi.Api.Emby/Models/EmbyUser.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: EmbyUser.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;
|
||||
|
||||
namespace Ombi.Api.Emby.Models
|
||||
{
|
||||
public class EmbyUser
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string ServerId { get; set; }
|
||||
public string ConnectUserName { get; set; }
|
||||
public string ConnectUserId { get; set; }
|
||||
public string ConnectLinkType { get; set; }
|
||||
public string Id { get; set; }
|
||||
public bool HasPassword { get; set; }
|
||||
public bool HasConfiguredPassword { get; set; }
|
||||
public bool HasConfiguredEasyPassword { get; set; }
|
||||
public DateTime LastLoginDate { get; set; }
|
||||
public DateTime LastActivityDate { get; set; }
|
||||
public EmbyConfiguration Configuration { get; set; }
|
||||
public EmbyPolicy Policy { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.Emby/Models/EmbyUserLogin.cs
Normal file
7
src/Ombi.Api.Emby/Models/EmbyUserLogin.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.Emby.Models
|
||||
{
|
||||
public class EmbyUserLogin
|
||||
{
|
||||
public EmbyUser User { get; set; }
|
||||
}
|
||||
}
|
12
src/Ombi.Api.Emby/Ombi.Api.Emby.csproj
Normal file
12
src/Ombi.Api.Emby/Ombi.Api.Emby.csproj
Normal file
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.6</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
19
src/Ombi.Api.Plex/IPlexApi.cs
Normal file
19
src/Ombi.Api.Plex/IPlexApi.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System.Threading.Tasks;
|
||||
using Ombi.Api.Plex.Models;
|
||||
using Ombi.Api.Plex.Models.Server;
|
||||
using Ombi.Api.Plex.Models.Status;
|
||||
|
||||
namespace Ombi.Api.Plex
|
||||
{
|
||||
public interface IPlexApi
|
||||
{
|
||||
Task<PlexStatus> GetStatus(string authToken, string uri);
|
||||
Task<PlexAuthentication> SignIn(UserRequest user);
|
||||
Task<PlexServer> GetServer(string authToken);
|
||||
Task<PlexLibraries> GetLibrarySections(string authToken, string plexFullHost);
|
||||
Task<PlexLibraries> GetLibrary(string authToken, string plexFullHost, string libraryId);
|
||||
Task<PlexMetadata> GetEpisodeMetaData(string authToken, string host, string ratingKey);
|
||||
Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId);
|
||||
Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey);
|
||||
}
|
||||
}
|
9
src/Ombi.Api.Plex/Models/Director.cs
Normal file
9
src/Ombi.Api.Plex/Models/Director.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Director
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string filter { get; set; }
|
||||
public string tag { get; set; }
|
||||
}
|
||||
}
|
41
src/Ombi.Api.Plex/Models/Directory.cs
Normal file
41
src/Ombi.Api.Plex/Models/Directory.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Directory
|
||||
{
|
||||
public Directory()
|
||||
{
|
||||
seasons = new List<Directory>();
|
||||
}
|
||||
public bool allowSync { get; set; }
|
||||
public string art { get; set; }
|
||||
public string composite { get; set; }
|
||||
public bool filters { get; set; }
|
||||
public bool refreshing { get; set; }
|
||||
public string thumb { get; set; }
|
||||
public string key { get; set; }
|
||||
public string type { get; set; }
|
||||
public string title { get; set; }
|
||||
public string agent { get; set; }
|
||||
public string scanner { get; set; }
|
||||
public string language { get; set; }
|
||||
public string uuid { get; set; }
|
||||
public int updatedAt { get; set; }
|
||||
public int createdAt { get; set; }
|
||||
public Location[] Location { get; set; }
|
||||
public string providerId { get; set; }
|
||||
public string guid { get; set; }
|
||||
public List<Genre> genre { get; set; }
|
||||
public List<Role> role { get; set; }
|
||||
public string librarySectionID { get; set; }
|
||||
public string librarySectionTitle { get; set; }
|
||||
public string librarySectionUUID { get; set; }
|
||||
public string personal { get; set; }
|
||||
public string sourceTitle { get; set; }
|
||||
public string ratingKey { get; set; }
|
||||
public string studio { get; set; }
|
||||
public List<Directory> seasons { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.Plex/Models/Genre.cs
Normal file
7
src/Ombi.Api.Plex/Models/Genre.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Genre
|
||||
{
|
||||
public string tag { get; set; }
|
||||
}
|
||||
}
|
8
src/Ombi.Api.Plex/Models/Location.cs
Normal file
8
src/Ombi.Api.Plex/Models/Location.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Location
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string path { get; set; }
|
||||
}
|
||||
}
|
26
src/Ombi.Api.Plex/Models/Mediacontainer.cs
Normal file
26
src/Ombi.Api.Plex/Models/Mediacontainer.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Mediacontainer
|
||||
{
|
||||
public int size { get; set; }
|
||||
public bool allowSync { get; set; }
|
||||
public string identifier { get; set; }
|
||||
public string mediaTagPrefix { get; set; }
|
||||
public int mediaTagVersion { get; set; }
|
||||
public string title1 { get; set; }
|
||||
public List<Directory> Directory { get; set; }
|
||||
public string art { get; set; }
|
||||
public int librarySectionID { get; set; }
|
||||
public string librarySectionTitle { get; set; }
|
||||
public string librarySectionUUID { get; set; }
|
||||
public bool nocache { get; set; }
|
||||
public string thumb { get; set; }
|
||||
public string title2 { get; set; }
|
||||
public string viewGroup { get; set; }
|
||||
public int viewMode { get; set; }
|
||||
public Metadata[] Metadata { get; set; }
|
||||
|
||||
}
|
||||
}
|
21
src/Ombi.Api.Plex/Models/Medium.cs
Normal file
21
src/Ombi.Api.Plex/Models/Medium.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Medium
|
||||
{
|
||||
public string videoResolution { get; set; }
|
||||
public int id { get; set; }
|
||||
public int duration { get; set; }
|
||||
public int bitrate { get; set; }
|
||||
public int width { get; set; }
|
||||
public int height { get; set; }
|
||||
public float aspectRatio { get; set; }
|
||||
public int audioChannels { get; set; }
|
||||
public string audioCodec { get; set; }
|
||||
public string videoCodec { get; set; }
|
||||
public string container { get; set; }
|
||||
public string videoFrameRate { get; set; }
|
||||
public string audioProfile { get; set; }
|
||||
public string videoProfile { get; set; }
|
||||
public Part[] Part { get; set; }
|
||||
}
|
||||
}
|
50
src/Ombi.Api.Plex/Models/Metadata.cs
Normal file
50
src/Ombi.Api.Plex/Models/Metadata.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Metadata
|
||||
{
|
||||
public string ratingKey { get; set; }
|
||||
public string key { get; set; }
|
||||
public string studio { get; set; }
|
||||
public string type { get; set; }
|
||||
public string title { get; set; }
|
||||
public string contentRating { get; set; }
|
||||
public string summary { get; set; }
|
||||
public int index { get; set; }
|
||||
public float rating { get; set; }
|
||||
public int viewCount { get; set; }
|
||||
public int lastViewedAt { get; set; }
|
||||
public int year { get; set; }
|
||||
public string thumb { get; set; }
|
||||
public string art { get; set; }
|
||||
public string banner { get; set; }
|
||||
public string theme { get; set; }
|
||||
public string duration { get; set; }
|
||||
public string originallyAvailableAt { get; set; }
|
||||
public int leafCount { get; set; }
|
||||
public int viewedLeafCount { get; set; }
|
||||
public int childCount { get; set; }
|
||||
public int addedAt { get; set; }
|
||||
public int updatedAt { get; set; }
|
||||
public Genre[] Genre { get; set; }
|
||||
public Role[] Role { get; set; }
|
||||
public string primaryExtraKey { get; set; }
|
||||
public string parentRatingKey { get; set; }
|
||||
public string grandparentRatingKey { get; set; }
|
||||
public string guid { get; set; }
|
||||
public int librarySectionID { get; set; }
|
||||
public string librarySectionKey { get; set; }
|
||||
public string grandparentKey { get; set; }
|
||||
public string parentKey { get; set; }
|
||||
public string grandparentTitle { get; set; }
|
||||
public string parentTitle { get; set; }
|
||||
public int parentIndex { get; set; }
|
||||
public string parentThumb { get; set; }
|
||||
public string grandparentThumb { get; set; }
|
||||
public string grandparentArt { get; set; }
|
||||
public string grandparentTheme { get; set; }
|
||||
public string chapterSource { get; set; }
|
||||
public Medium[] Media { get; set; }
|
||||
public Director[] Director { get; set; }
|
||||
public Writer[] Writer { get; set; }
|
||||
}
|
||||
}
|
15
src/Ombi.Api.Plex/Models/Part.cs
Normal file
15
src/Ombi.Api.Plex/Models/Part.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Part
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string key { get; set; }
|
||||
public string duration { get; set; }
|
||||
public string file { get; set; }
|
||||
public string size { get; set; }
|
||||
public string audioProfile { get; set; }
|
||||
public string container { get; set; }
|
||||
public string videoProfile { get; set; }
|
||||
public Stream[] Stream { get; set; }
|
||||
}
|
||||
}
|
10
src/Ombi.Api.Plex/Models/PlexAuthentication.cs
Normal file
10
src/Ombi.Api.Plex/Models/PlexAuthentication.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class PlexAuthentication
|
||||
{
|
||||
public User user { get; set; }
|
||||
}
|
||||
}
|
33
src/Ombi.Api.Plex/Models/PlexLibraries.cs
Normal file
33
src/Ombi.Api.Plex/Models/PlexLibraries.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: Library.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class PlexLibraries
|
||||
{
|
||||
public Mediacontainer MediaContainer { get; set; }
|
||||
}
|
||||
}
|
33
src/Ombi.Api.Plex/Models/PlexMetadata.cs
Normal file
33
src/Ombi.Api.Plex/Models/PlexMetadata.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: PlexMetadata.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class PlexMetadata
|
||||
{
|
||||
public Mediacontainer MediaContainer { get; set; }
|
||||
}
|
||||
}
|
33
src/Ombi.Api.Plex/Models/PlexUserRequest.cs
Normal file
33
src/Ombi.Api.Plex/Models/PlexUserRequest.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: PlexUserRequest.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class PlexUserRequest
|
||||
{
|
||||
public UserRequest user { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.Plex/Models/Role.cs
Normal file
7
src/Ombi.Api.Plex/Models/Role.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Role
|
||||
{
|
||||
public string tag { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Api.Plex/Models/Roles.cs
Normal file
9
src/Ombi.Api.Plex/Models/Roles.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Roles
|
||||
{
|
||||
public List<object> roles { get; set; }
|
||||
}
|
||||
}
|
47
src/Ombi.Api.Plex/Models/Server/PlexServer.cs
Normal file
47
src/Ombi.Api.Plex/Models/Server/PlexServer.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: PlexServer.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;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Ombi.Api.Plex.Models.Server
|
||||
{
|
||||
[XmlRoot(ElementName = "MediaContainer")]
|
||||
public class PlexServer
|
||||
{
|
||||
[XmlElement(ElementName = "Server")]
|
||||
public List<ServerInfo> Server { get; set; }
|
||||
[XmlAttribute(AttributeName = "friendlyName")]
|
||||
public string FriendlyName { get; set; }
|
||||
[XmlAttribute(AttributeName = "identifier")]
|
||||
public string Identifier { get; set; }
|
||||
[XmlAttribute(AttributeName = "machineIdentifier")]
|
||||
public string MachineIdentifier { get; set; }
|
||||
[XmlAttribute(AttributeName = "size")]
|
||||
public string Size { get; set; }
|
||||
}
|
||||
}
|
41
src/Ombi.Api.Plex/Models/Server/ServerInfo.cs
Normal file
41
src/Ombi.Api.Plex/Models/Server/ServerInfo.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System.Xml.Serialization;
|
||||
|
||||
namespace Ombi.Api.Plex.Models.Server
|
||||
{
|
||||
[XmlRoot(ElementName = "Server")]
|
||||
public class ServerInfo
|
||||
{
|
||||
[XmlAttribute(AttributeName = "accessToken")]
|
||||
public string AccessToken { get; set; }
|
||||
[XmlAttribute(AttributeName = "name")]
|
||||
public string Name { get; set; }
|
||||
[XmlAttribute(AttributeName = "address")]
|
||||
public string Address { get; set; }
|
||||
[XmlAttribute(AttributeName = "port")]
|
||||
public string Port { get; set; }
|
||||
[XmlAttribute(AttributeName = "version")]
|
||||
public string Version { get; set; }
|
||||
[XmlAttribute(AttributeName = "scheme")]
|
||||
public string Scheme { get; set; }
|
||||
[XmlAttribute(AttributeName = "host")]
|
||||
public string Host { get; set; }
|
||||
[XmlAttribute(AttributeName = "localAddresses")]
|
||||
public string LocalAddresses { get; set; }
|
||||
[XmlAttribute(AttributeName = "machineIdentifier")]
|
||||
public string MachineIdentifier { get; set; }
|
||||
[XmlAttribute(AttributeName = "createdAt")]
|
||||
public string CreatedAt { get; set; }
|
||||
[XmlAttribute(AttributeName = "updatedAt")]
|
||||
public string UpdatedAt { get; set; }
|
||||
[XmlAttribute(AttributeName = "owned")]
|
||||
public string Owned { get; set; }
|
||||
[XmlAttribute(AttributeName = "synced")]
|
||||
public string Synced { get; set; }
|
||||
[XmlAttribute(AttributeName = "sourceTitle")]
|
||||
public string SourceTitle { get; set; }
|
||||
[XmlAttribute(AttributeName = "ownerId")]
|
||||
public string OwnerId { get; set; }
|
||||
[XmlAttribute(AttributeName = "home")]
|
||||
public string Home { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Api.Plex/Models/Status/Directory.cs
Normal file
9
src/Ombi.Api.Plex/Models/Status/Directory.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.Plex.Models.Status
|
||||
{
|
||||
public class Directory
|
||||
{
|
||||
public int count { get; set; }
|
||||
public string key { get; set; }
|
||||
public string title { get; set; }
|
||||
}
|
||||
}
|
51
src/Ombi.Api.Plex/Models/Status/Mediacontainer.cs
Normal file
51
src/Ombi.Api.Plex/Models/Status/Mediacontainer.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
namespace Ombi.Api.Plex.Models.Status
|
||||
{
|
||||
public class Mediacontainer
|
||||
{
|
||||
public int size { get; set; }
|
||||
public bool allowCameraUpload { get; set; }
|
||||
public bool allowChannelAccess { get; set; }
|
||||
public bool allowMediaDeletion { get; set; }
|
||||
public bool allowSharing { get; set; }
|
||||
public bool allowSync { get; set; }
|
||||
public bool backgroundProcessing { get; set; }
|
||||
public bool certificate { get; set; }
|
||||
public bool companionProxy { get; set; }
|
||||
public string countryCode { get; set; }
|
||||
public string diagnostics { get; set; }
|
||||
public bool eventStream { get; set; }
|
||||
public string friendlyName { get; set; }
|
||||
public bool hubSearch { get; set; }
|
||||
public bool itemClusters { get; set; }
|
||||
public string machineIdentifier { get; set; }
|
||||
public bool mediaProviders { get; set; }
|
||||
public bool multiuser { get; set; }
|
||||
public bool myPlex { get; set; }
|
||||
public string myPlexMappingState { get; set; }
|
||||
public string myPlexSigninState { get; set; }
|
||||
public bool myPlexSubscription { get; set; }
|
||||
public string myPlexUsername { get; set; }
|
||||
public bool photoAutoTag { get; set; }
|
||||
public string platform { get; set; }
|
||||
public string platformVersion { get; set; }
|
||||
public bool pluginHost { get; set; }
|
||||
public bool readOnlyLibraries { get; set; }
|
||||
public bool requestParametersInCookie { get; set; }
|
||||
public int streamingBrainVersion { get; set; }
|
||||
public bool sync { get; set; }
|
||||
public int transcoderActiveVideoSessions { get; set; }
|
||||
public bool transcoderAudio { get; set; }
|
||||
public bool transcoderLyrics { get; set; }
|
||||
public bool transcoderPhoto { get; set; }
|
||||
public bool transcoderSubtitles { get; set; }
|
||||
public bool transcoderVideo { get; set; }
|
||||
public string transcoderVideoBitrates { get; set; }
|
||||
public string transcoderVideoQualities { get; set; }
|
||||
public string transcoderVideoResolutions { get; set; }
|
||||
public int updatedAt { get; set; }
|
||||
public bool updater { get; set; }
|
||||
public string version { get; set; }
|
||||
public bool voiceSearch { get; set; }
|
||||
public Directory[] Directory { get; set; }
|
||||
}
|
||||
}
|
34
src/Ombi.Api.Plex/Models/Status/PlexStatus.cs
Normal file
34
src/Ombi.Api.Plex/Models/Status/PlexStatus.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: PlexStatus.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Api.Plex.Models.Status
|
||||
{
|
||||
|
||||
public class PlexStatus
|
||||
{
|
||||
public Mediacontainer MediaContainer { get; set; }
|
||||
}
|
||||
}
|
28
src/Ombi.Api.Plex/Models/Stream.cs
Normal file
28
src/Ombi.Api.Plex/Models/Stream.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Stream
|
||||
{
|
||||
public int id { get; set; }
|
||||
public int streamType { get; set; }
|
||||
public bool _default { get; set; }
|
||||
public string codec { get; set; }
|
||||
public int index { get; set; }
|
||||
public int bitrate { get; set; }
|
||||
public int bitDepth { get; set; }
|
||||
public string chromaSubsampling { get; set; }
|
||||
public float frameRate { get; set; }
|
||||
public bool hasScalingMatrix { get; set; }
|
||||
public int height { get; set; }
|
||||
public int level { get; set; }
|
||||
public string profile { get; set; }
|
||||
public int refFrames { get; set; }
|
||||
public string scanType { get; set; }
|
||||
public int width { get; set; }
|
||||
public int channels { get; set; }
|
||||
public string language { get; set; }
|
||||
public string languageCode { get; set; }
|
||||
public string audioChannelLayout { get; set; }
|
||||
public int samplingRate { get; set; }
|
||||
public bool selected { get; set; }
|
||||
}
|
||||
}
|
10
src/Ombi.Api.Plex/Models/Subscription.cs
Normal file
10
src/Ombi.Api.Plex/Models/Subscription.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Subscription
|
||||
{
|
||||
public bool active { get; set; }
|
||||
public string status { get; set; }
|
||||
public object plan { get; set; }
|
||||
public object features { get; set; }
|
||||
}
|
||||
}
|
19
src/Ombi.Api.Plex/Models/User.cs
Normal file
19
src/Ombi.Api.Plex/Models/User.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class User
|
||||
{
|
||||
public string email { get; set; }
|
||||
public string uuid { get; set; }
|
||||
public string joined_at { get; set; }
|
||||
public string username { get; set; }
|
||||
public string title { get; set; }
|
||||
public string authentication_token { get; set; }
|
||||
public Subscription subscription { get; set; }
|
||||
public Roles roles { get; set; }
|
||||
public List<string> entitlements { get; set; }
|
||||
public object confirmed_at { get; set; }
|
||||
public int forum_id { get; set; }
|
||||
}
|
||||
}
|
8
src/Ombi.Api.Plex/Models/UserRequest.cs
Normal file
8
src/Ombi.Api.Plex/Models/UserRequest.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class UserRequest
|
||||
{
|
||||
public string login { get; set; }
|
||||
public string password { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Api.Plex/Models/Writer.cs
Normal file
9
src/Ombi.Api.Plex/Models/Writer.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.Plex.Models
|
||||
{
|
||||
public class Writer
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string filter { get; set; }
|
||||
public string tag { get; set; }
|
||||
}
|
||||
}
|
15
src/Ombi.Api.Plex/Ombi.Api.Plex.csproj
Normal file
15
src/Ombi.Api.Plex/Ombi.Api.Plex.csproj
Normal file
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.6</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
135
src/Ombi.Api.Plex/PlexApi.cs
Normal file
135
src/Ombi.Api.Plex/PlexApi.cs
Normal file
|
@ -0,0 +1,135 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Api.Plex.Models;
|
||||
using Ombi.Api.Plex.Models.Server;
|
||||
using Ombi.Api.Plex.Models.Status;
|
||||
|
||||
namespace Ombi.Api.Plex
|
||||
{
|
||||
public class PlexApi : IPlexApi
|
||||
{
|
||||
public PlexApi()
|
||||
{
|
||||
Api = new Api();
|
||||
}
|
||||
|
||||
private Api Api { get; }
|
||||
|
||||
private const string SignInUri = "https://plex.tv/users/sign_in.json";
|
||||
private const string FriendsUri = "https://plex.tv/pms/friends/all";
|
||||
private const string GetAccountUri = "https://plex.tv/users/account";
|
||||
private const string ServerUri = "https://plex.tv/pms/servers.xml";
|
||||
|
||||
/// <summary>
|
||||
/// Sign into the Plex API
|
||||
/// This is for authenticating users credentials with Plex
|
||||
/// <para>NOTE: Plex "Managed" users do not work</para>
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<PlexAuthentication> SignIn(UserRequest user)
|
||||
{
|
||||
var userModel = new PlexUserRequest
|
||||
{
|
||||
user = user
|
||||
};
|
||||
var request = new Request(SignInUri, string.Empty, HttpMethod.Post);
|
||||
|
||||
AddHeaders(request);
|
||||
request.AddJsonBody(userModel);
|
||||
|
||||
var obj = await Api.Request<PlexAuthentication>(request);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public async Task<PlexStatus> GetStatus(string authToken, string uri)
|
||||
{
|
||||
var request = new Request(uri, string.Empty, HttpMethod.Get);
|
||||
AddHeaders(request, authToken);
|
||||
return await Api.Request<PlexStatus>(request);
|
||||
}
|
||||
|
||||
public async Task<PlexServer> GetServer(string authToken)
|
||||
{
|
||||
var request = new Request(ServerUri, string.Empty, HttpMethod.Get, ContentType.Xml);
|
||||
|
||||
AddHeaders(request, authToken);
|
||||
|
||||
return await Api.Request<PlexServer>(request);
|
||||
}
|
||||
|
||||
public async Task<PlexLibraries> GetLibrarySections(string authToken, string plexFullHost)
|
||||
{
|
||||
var request = new Request("library/sections", plexFullHost, HttpMethod.Get);
|
||||
AddHeaders(request, authToken);
|
||||
return await Api.Request<PlexLibraries>(request);
|
||||
}
|
||||
|
||||
public async Task<PlexLibraries> GetLibrary(string authToken, string plexFullHost, string libraryId)
|
||||
{
|
||||
var request = new Request($"library/sections/{libraryId}/all", plexFullHost, HttpMethod.Get);
|
||||
AddHeaders(request, authToken);
|
||||
return await Api.Request<PlexLibraries>(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
// 192.168.1.69:32400/library/metadata/3662/allLeaves
|
||||
// The metadata ratingkey should be in the Cache
|
||||
// Search for it and then call the above with the Directory.RatingKey
|
||||
// THEN! We need the episode metadata using result.Vide.Key ("/library/metadata/3664")
|
||||
// We then have the GUID which contains the TVDB ID plus the season and episode number: guid="com.plexapp.agents.thetvdb://269586/2/8?lang=en"
|
||||
/// </summary>
|
||||
/// <param name="authToken"></param>
|
||||
/// <param name="plexFullHost"></param>
|
||||
/// <param name="ratingKey"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<PlexMetadata> GetEpisodeMetaData(string authToken, string plexFullHost, string ratingKey)
|
||||
{
|
||||
var request = new Request($"/library/metadata/{ratingKey}", plexFullHost, HttpMethod.Get);
|
||||
AddHeaders(request, authToken);
|
||||
return await Api.Request<PlexMetadata>(request);
|
||||
}
|
||||
|
||||
public async Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId)
|
||||
{
|
||||
var request = new Request($"library/metadata/{itemId}", plexFullHost, HttpMethod.Get);
|
||||
AddHeaders(request, authToken);
|
||||
return await Api.Request<PlexMetadata>(request);
|
||||
}
|
||||
|
||||
public async Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey)
|
||||
{
|
||||
var request = new Request($"library/metadata/{ratingKey}/children", plexFullHost, HttpMethod.Get);
|
||||
AddHeaders(request, authToken);
|
||||
return await Api.Request<PlexMetadata>(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the required headers and also the authorization header
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="authToken"></param>
|
||||
private void AddHeaders(Request request, string authToken)
|
||||
{
|
||||
request.AddHeader("X-Plex-Token", authToken);
|
||||
AddHeaders(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the main required headers to the Plex Request
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
private void AddHeaders(Request request)
|
||||
{
|
||||
request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3");
|
||||
request.AddHeader("X-Plex-Product", "Ombi");
|
||||
request.AddHeader("X-Plex-Version", "3");
|
||||
request.AddContentHeader("Content-Type", request.ContentType == ContentType.Json ? "application/json" : "application/xml");
|
||||
request.AddHeader("Accept", "application/json");
|
||||
}
|
||||
}
|
||||
}
|
12
src/Ombi.Api.Sonarr/ISonarrApi.cs
Normal file
12
src/Ombi.Api.Sonarr/ISonarrApi.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Api.Sonarr.Models;
|
||||
|
||||
namespace Ombi.Api.Sonarr
|
||||
{
|
||||
public interface ISonarrApi
|
||||
{
|
||||
Task<IEnumerable<SonarrProfile>> GetProfiles(string apiKey, string baseUrl);
|
||||
Task<IEnumerable<SonarrRootFolder>> GetRootFolders(string apiKey, string baseUrl);
|
||||
}
|
||||
}
|
8
src/Ombi.Api.Sonarr/Models/Cutoff.cs
Normal file
8
src/Ombi.Api.Sonarr/Models/Cutoff.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Api.Sonarr.Models
|
||||
{
|
||||
public class Cutoff
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
}
|
8
src/Ombi.Api.Sonarr/Models/Item.cs
Normal file
8
src/Ombi.Api.Sonarr/Models/Item.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Api.Sonarr.Models
|
||||
{
|
||||
public class Item
|
||||
{
|
||||
public Quality quality { get; set; }
|
||||
public bool allowed { get; set; }
|
||||
}
|
||||
}
|
8
src/Ombi.Api.Sonarr/Models/Quality.cs
Normal file
8
src/Ombi.Api.Sonarr/Models/Quality.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Api.Sonarr.Models
|
||||
{
|
||||
public class Quality
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
}
|
12
src/Ombi.Api.Sonarr/Models/SonarrProfile.cs
Normal file
12
src/Ombi.Api.Sonarr/Models/SonarrProfile.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.Sonarr.Models
|
||||
{
|
||||
public class SonarrProfile
|
||||
{
|
||||
public string name { get; set; }
|
||||
public Cutoff cutoff { get; set; }
|
||||
public List<Item> items { get; set; }
|
||||
public int id { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Api.Sonarr/Models/SonarrRootFolder.cs
Normal file
9
src/Ombi.Api.Sonarr/Models/SonarrRootFolder.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.Sonarr.Models
|
||||
{
|
||||
public class SonarrRootFolder
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string path { get; set; }
|
||||
public long freespace { get; set; }
|
||||
}
|
||||
}
|
11
src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj
Normal file
11
src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj
Normal file
|
@ -0,0 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.6</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
37
src/Ombi.Api.Sonarr/SonarrApi.cs
Normal file
37
src/Ombi.Api.Sonarr/SonarrApi.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using System.Net.Http;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Ombi.Api.Sonarr.Models;
|
||||
|
||||
namespace Ombi.Api.Sonarr
|
||||
{
|
||||
public class SonarrApi : ISonarrApi
|
||||
{
|
||||
|
||||
public SonarrApi()
|
||||
{
|
||||
Api = new Api();
|
||||
}
|
||||
|
||||
private Api Api { get; }
|
||||
|
||||
public async Task<IEnumerable<SonarrProfile>> GetProfiles(string apiKey, string baseUrl)
|
||||
{
|
||||
var request = new Request(baseUrl, "/api/profile", HttpMethod.Get);
|
||||
|
||||
request.AddHeader("X-Api-Key", apiKey);
|
||||
|
||||
return await Api.Request<List<SonarrProfile>>(request);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SonarrRootFolder>> GetRootFolders(string apiKey, string baseUrl)
|
||||
{
|
||||
var request = new Request(baseUrl, "/api/rootfolder", HttpMethod.Get);
|
||||
|
||||
request.AddHeader("X-Api-Key", apiKey);
|
||||
|
||||
return await Api.Request<List<SonarrRootFolder>>(request);
|
||||
}
|
||||
}
|
||||
}
|
16
src/Ombi.Api.Trakt/ITraktApi.cs
Normal file
16
src/Ombi.Api.Trakt/ITraktApi.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
//using TraktApiSharp.Enums;
|
||||
//using TraktApiSharp.Objects.Get.Shows;
|
||||
//using TraktApiSharp.Objects.Get.Shows.Common;
|
||||
|
||||
namespace Ombi.Api.Trakt
|
||||
{
|
||||
public interface ITraktApi
|
||||
{
|
||||
//Task<IEnumerable<TraktMostAnticipatedShow>> GetAnticipatedShows(int? page = default(int?), int? limitPerPage = default(int?));
|
||||
//Task<IEnumerable<TraktMostWatchedShow>> GetMostWatchesShows(TraktTimePeriod period = null, int? page = default(int?), int? limitPerPage = default(int?));
|
||||
//Task<IEnumerable<TraktShow>> GetPopularShows(int? page = default(int?), int? limitPerPage = default(int?));
|
||||
//Task<IEnumerable<TraktTrendingShow>> GetTrendingShows(int? page = default(int?), int? limitPerPage = default(int?));
|
||||
}
|
||||
}
|
12
src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj
Normal file
12
src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj
Normal file
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.6</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
49
src/Ombi.Api.Trakt/TraktApi.cs
Normal file
49
src/Ombi.Api.Trakt/TraktApi.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Threading.Tasks;
|
||||
//using Ombi.Helpers;
|
||||
//using TraktApiSharp;
|
||||
//using TraktApiSharp.Enums;
|
||||
//using TraktApiSharp.Objects.Get.Shows;
|
||||
//using TraktApiSharp.Objects.Get.Shows.Common;
|
||||
//using TraktApiSharp.Requests.Parameters;
|
||||
|
||||
//namespace Ombi.Api.Trakt
|
||||
//{
|
||||
// public class TraktApi : ITraktApi
|
||||
// {
|
||||
// private TraktClient Client { get; }
|
||||
|
||||
// private static readonly string Encrypted = "MTM0ZTU2ODM1MGY3NDI3NTExZTI1N2E2NTM0MDI2NjYwNDgwY2Y5YjkzYzc3ZjczNzhmMzQwNjAzYjY3MzgxZA==";
|
||||
// private readonly string _apiKey = StringCipher.DecryptString(Encrypted, "ApiKey");
|
||||
// public TraktApi()
|
||||
// {
|
||||
// Client = new TraktClient(_apiKey);
|
||||
// }
|
||||
|
||||
// public async Task<IEnumerable<TraktShow>> GetPopularShows(int? page = null, int? limitPerPage = null)
|
||||
// {
|
||||
// var popular = await Client.Shows.GetPopularShowsAsync(new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
|
||||
// return popular.Value;
|
||||
// }
|
||||
|
||||
// public async Task<IEnumerable<TraktTrendingShow>> GetTrendingShows(int? page = null, int? limitPerPage = null)
|
||||
// {
|
||||
// var trendingShowsTop10 = await Client.Shows.GetTrendingShowsAsync(new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
|
||||
// return trendingShowsTop10.Value;
|
||||
// }
|
||||
|
||||
// public async Task<IEnumerable<TraktMostAnticipatedShow>> GetAnticipatedShows(int? page = null, int? limitPerPage = null)
|
||||
// {
|
||||
// var anticipatedShows = await Client.Shows.GetMostAnticipatedShowsAsync(new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
|
||||
// return anticipatedShows.Value;
|
||||
// }
|
||||
|
||||
// public async Task<IEnumerable<TraktMostWatchedShow>> GetMostWatchesShows(TraktTimePeriod period = null, int? page = null, int? limitPerPage = null)
|
||||
// {
|
||||
// var anticipatedShows = await Client.Shows.GetMostWatchedShowsAsync(period ?? TraktTimePeriod.Monthly, new TraktExtendedInfo { Full = true }, null, page ?? 1, limitPerPage ?? 10);
|
||||
// return anticipatedShows.Value;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
15
src/Ombi.Api.TvMaze/ITvMazeApi.cs
Normal file
15
src/Ombi.Api.TvMaze/ITvMazeApi.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Api.TvMaze.Models;
|
||||
|
||||
namespace Ombi.Api.TvMaze
|
||||
{
|
||||
public interface ITvMazeApi
|
||||
{
|
||||
Task<IEnumerable<TvMazeEpisodes>> EpisodeLookup(int showId);
|
||||
Task<List<TvMazeSeasons>> GetSeasons(int id);
|
||||
Task<List<TvMazeSearch>> Search(string searchTerm);
|
||||
Task<TvMazeShow> ShowLookup(int showId);
|
||||
Task<TvMazeShow> ShowLookupByTheTvDbId(int theTvDbId);
|
||||
}
|
||||
}
|
9
src/Ombi.Api.TvMaze/Models/Search/Country.cs
Normal file
9
src/Ombi.Api.TvMaze/Models/Search/Country.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Country
|
||||
{
|
||||
public string code { get; set; }
|
||||
public string name { get; set; }
|
||||
public string timezone { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Api.TvMaze/Models/Search/Externals.cs
Normal file
9
src/Ombi.Api.TvMaze/Models/Search/Externals.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Externals
|
||||
{
|
||||
public string imdb { get; set; }
|
||||
public int? thetvdb { get; set; }
|
||||
public int? tvrage { get; set; }
|
||||
}
|
||||
}
|
8
src/Ombi.Api.TvMaze/Models/Search/Image.cs
Normal file
8
src/Ombi.Api.TvMaze/Models/Search/Image.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Image
|
||||
{
|
||||
public string medium { get; set; }
|
||||
public string original { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Api.TvMaze/Models/Search/Links.cs
Normal file
9
src/Ombi.Api.TvMaze/Models/Search/Links.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Links
|
||||
{
|
||||
public Nextepisode nextepisode { get; set; }
|
||||
public Previousepisode previousepisode { get; set; }
|
||||
public Self self { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Api.TvMaze/Models/Search/Network.cs
Normal file
9
src/Ombi.Api.TvMaze/Models/Search/Network.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Network
|
||||
{
|
||||
public Country country { get; set; }
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.TvMaze/Models/Search/Nextepisode.cs
Normal file
7
src/Ombi.Api.TvMaze/Models/Search/Nextepisode.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Nextepisode
|
||||
{
|
||||
public string href { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.TvMaze/Models/Search/Previousepisode.cs
Normal file
7
src/Ombi.Api.TvMaze/Models/Search/Previousepisode.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Previousepisode
|
||||
{
|
||||
public string href { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.TvMaze/Models/Search/Rating.cs
Normal file
7
src/Ombi.Api.TvMaze/Models/Search/Rating.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Rating
|
||||
{
|
||||
public double? average { get; set; }
|
||||
}
|
||||
}
|
10
src/Ombi.Api.TvMaze/Models/Search/Schedule.cs
Normal file
10
src/Ombi.Api.TvMaze/Models/Search/Schedule.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Schedule
|
||||
{
|
||||
public List<object> days { get; set; }
|
||||
public string time { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.TvMaze/Models/Search/Self.cs
Normal file
7
src/Ombi.Api.TvMaze/Models/Search/Self.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Self
|
||||
{
|
||||
public string href { get; set; }
|
||||
}
|
||||
}
|
27
src/Ombi.Api.TvMaze/Models/Search/Show.cs
Normal file
27
src/Ombi.Api.TvMaze/Models/Search/Show.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class Show
|
||||
{
|
||||
public Links _links { get; set; }
|
||||
public Externals externals { get; set; }
|
||||
public List<object> genres { get; set; }
|
||||
public int id { get; set; }
|
||||
public Image image { get; set; }
|
||||
public string language { get; set; }
|
||||
public string name { get; set; }
|
||||
public Network network { get; set; }
|
||||
public string premiered { get; set; }
|
||||
public Rating rating { get; set; }
|
||||
public int? runtime { get; set; }
|
||||
public Schedule schedule { get; set; }
|
||||
public string status { get; set; }
|
||||
public string summary { get; set; }
|
||||
public string type { get; set; }
|
||||
public int updated { get; set; }
|
||||
public string url { get; set; }
|
||||
public object webChannel { get; set; }
|
||||
public int weight { get; set; }
|
||||
}
|
||||
}
|
8
src/Ombi.Api.TvMaze/Models/Search/TvMazeSearch.cs
Normal file
8
src/Ombi.Api.TvMaze/Models/Search/TvMazeSearch.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class TvMazeSearch
|
||||
{
|
||||
public double score { get; set; }
|
||||
public Show show { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.TvMaze/Models/TVMazeSeasons.cs
Normal file
7
src/Ombi.Api.TvMaze/Models/TVMazeSeasons.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class TvMazeSeasons : TvMazeShow
|
||||
{
|
||||
public int number { get; set; }
|
||||
}
|
||||
}
|
18
src/Ombi.Api.TvMaze/Models/TvMazeEpisode.cs
Normal file
18
src/Ombi.Api.TvMaze/Models/TvMazeEpisode.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class TvMazeEpisodes
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string url { get; set; }
|
||||
public string name { get; set; }
|
||||
public int season { get; set; }
|
||||
public int number { get; set; }
|
||||
public string airdate { get; set; }
|
||||
public string airtime { get; set; }
|
||||
public string airstamp { get; set; }
|
||||
public int runtime { get; set; }
|
||||
public Image image { get; set; }
|
||||
public string summary { get; set; }
|
||||
public Links _links { get; set; }
|
||||
}
|
||||
}
|
89
src/Ombi.Api.TvMaze/Models/TvMazeShow.cs
Normal file
89
src/Ombi.Api.TvMaze/Models/TvMazeShow.cs
Normal file
|
@ -0,0 +1,89 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.TvMaze.Models
|
||||
{
|
||||
public class TvMazeShow
|
||||
{
|
||||
public TvMazeShow()
|
||||
{
|
||||
Season = new List<TvMazeCustomSeason>();
|
||||
}
|
||||
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 double 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 List<TvMazeCustomSeason> Season { get; set; }
|
||||
public Embedded _embedded { get; set; }
|
||||
}
|
||||
|
||||
public class TvMazeCustomSeason
|
||||
{
|
||||
public int SeasonNumber { get; set; }
|
||||
public List<int> EpisodeNumber { get; set; }
|
||||
}
|
||||
|
||||
public class Season
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string url { get; set; }
|
||||
public int number { get; set; }
|
||||
public string name { get; set; }
|
||||
public int? episodeOrder { get; set; }
|
||||
public string premiereDate { get; set; }
|
||||
public string endDate { get; set; }
|
||||
public Network2 network { get; set; }
|
||||
public object webChannel { get; set; }
|
||||
public Image2 image { get; set; }
|
||||
public string summary { get; set; }
|
||||
public Links2 _links { get; set; }
|
||||
}
|
||||
public class Country2
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string code { get; set; }
|
||||
public string timezone { get; set; }
|
||||
}
|
||||
|
||||
public class Network2
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
public Country2 country { get; set; }
|
||||
}
|
||||
|
||||
public class Image2
|
||||
{
|
||||
public string medium { get; set; }
|
||||
public string original { get; set; }
|
||||
}
|
||||
|
||||
public class Self2
|
||||
{
|
||||
public string href { get; set; }
|
||||
}
|
||||
|
||||
public class Links2
|
||||
{
|
||||
public Self2 self { get; set; }
|
||||
}
|
||||
|
||||
public class Embedded
|
||||
{
|
||||
public List<Season> seasons { get; set; }
|
||||
}
|
||||
}
|
18
src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj
Normal file
18
src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj
Normal file
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.6</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions">
|
||||
<HintPath>..\..\..\..\..\.nuget\packages\microsoft.extensions.logging.abstractions\1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
104
src/Ombi.Api.TvMaze/TvMazeApi.cs
Normal file
104
src/Ombi.Api.TvMaze/TvMazeApi.cs
Normal file
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.TvMaze.Models;
|
||||
using Ombi.Helpers;
|
||||
|
||||
namespace Ombi.Api.TvMaze
|
||||
{
|
||||
public class TvMazeApi : ITvMazeApi
|
||||
{
|
||||
public TvMazeApi(ILogger<TvMazeApi> logger)
|
||||
{
|
||||
Api = new Ombi.Api.Api();
|
||||
Logger = logger;
|
||||
//Mapper = mapper;
|
||||
}
|
||||
private string Uri = "http://api.tvmaze.com";
|
||||
private Api Api { get; }
|
||||
private ILogger<TvMazeApi> Logger { get; }
|
||||
|
||||
public async Task<List<TvMazeSearch>> Search(string searchTerm)
|
||||
{
|
||||
var request = new Request("search/shows", Uri, HttpMethod.Get);
|
||||
|
||||
request.AddQueryString("q", searchTerm);
|
||||
request.ContentHeaders.Add(new KeyValuePair<string, string>("Content-Type","application/json"));
|
||||
|
||||
return await Api.Request<List<TvMazeSearch>>(request);
|
||||
}
|
||||
|
||||
public async Task<TvMazeShow> ShowLookup(int showId)
|
||||
{
|
||||
var request = new Request($"shows/{showId}", Uri, HttpMethod.Get);
|
||||
request.AddContentHeader("Content-Type", "application/json");
|
||||
|
||||
return await Api.Request<TvMazeShow>(request);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TvMazeEpisodes>> EpisodeLookup(int showId)
|
||||
{
|
||||
|
||||
var request = new Request($"shows/{showId}/episodes", Uri, HttpMethod.Get);
|
||||
|
||||
request.AddContentHeader("Content-Type", "application/json");
|
||||
|
||||
return await Api.Request<List<TvMazeEpisodes>>(request);
|
||||
}
|
||||
|
||||
public async Task<TvMazeShow> ShowLookupByTheTvDbId(int theTvDbId)
|
||||
{
|
||||
var request = new Request($"lookup/shows?thetvdb={theTvDbId}", Uri, HttpMethod.Get);
|
||||
request.AddContentHeader("Content-Type", "application/json");
|
||||
try
|
||||
{
|
||||
var obj = await Api.Request<TvMazeShow>(request);
|
||||
|
||||
var episodes = await EpisodeLookup(obj.id);
|
||||
|
||||
foreach (var e in episodes)
|
||||
{
|
||||
// Check if the season exists
|
||||
var currentSeason = obj.Season.FirstOrDefault(x => x.SeasonNumber == e.season);
|
||||
|
||||
if (currentSeason == null)
|
||||
{
|
||||
// Create the season
|
||||
obj.Season.Add(new TvMazeCustomSeason
|
||||
{
|
||||
SeasonNumber = e.season,
|
||||
EpisodeNumber = new List<int> {e.number}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just add a new episode into that season
|
||||
currentSeason.EpisodeNumber.Add(e.number);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError(LoggingEvents.ApiException, e, "Exception when calling ShowLookupByTheTvDbId with id:{0}",theTvDbId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<TvMazeSeasons>> GetSeasons(int id)
|
||||
{
|
||||
var request = new Request($"shows/{id}/seasons", Uri, HttpMethod.Get);
|
||||
|
||||
request.AddContentHeader("Content-Type", "application/json");
|
||||
|
||||
return await Api.Request<List<TvMazeSeasons>>(request);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
65
src/Ombi.Api/Api.cs
Normal file
65
src/Ombi.Api/Api.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Ombi.Api
|
||||
{
|
||||
public class Api
|
||||
{
|
||||
private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
public async Task<T> Request<T>(Request request)
|
||||
{
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
|
||||
{
|
||||
// Add the Json Body
|
||||
if (request.JsonBody != null)
|
||||
{
|
||||
httpRequestMessage.Content = new JsonContent(request.JsonBody);
|
||||
}
|
||||
|
||||
// Add headers
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
httpRequestMessage.Headers.Add(header.Key, header.Value);
|
||||
|
||||
}
|
||||
using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
|
||||
{
|
||||
if (!httpResponseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
// Logging
|
||||
}
|
||||
// do something with the response
|
||||
var data = httpResponseMessage.Content;
|
||||
|
||||
|
||||
var receivedString = await data.ReadAsStringAsync();
|
||||
if (request.ContentType == ContentType.Json)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(receivedString, Settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
// XML
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(T));
|
||||
StringReader reader = new StringReader(receivedString);
|
||||
var value = (T)serializer.Deserialize(reader);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
75
src/Ombi.Api/ApiHelper.cs
Normal file
75
src/Ombi.Api/ApiHelper.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: ApiHelper.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;
|
||||
|
||||
namespace Ombi.Api
|
||||
{
|
||||
public static class ApiHelper
|
||||
{
|
||||
public static Uri ChangePath(this Uri uri, string path, params string[] args)
|
||||
{
|
||||
var builder = new UriBuilder(uri);
|
||||
|
||||
if (args != null && args.Length > 0)
|
||||
{
|
||||
builder.Path = builder.Path + string.Format(path, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Path += path;
|
||||
}
|
||||
return builder.Uri;
|
||||
}
|
||||
public static Uri ChangePath(this Uri uri, string path)
|
||||
{
|
||||
return ChangePath(uri, path, null);
|
||||
}
|
||||
|
||||
public static Uri AddQueryParameter(this Uri uri, string parameter, string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(parameter) || string.IsNullOrEmpty(value)) return uri;
|
||||
var builder = new UriBuilder(uri);
|
||||
var startingTag = string.Empty;
|
||||
var hasQuery = false;
|
||||
if (string.IsNullOrEmpty(builder.Query))
|
||||
{
|
||||
startingTag = "?";
|
||||
}
|
||||
else
|
||||
{
|
||||
hasQuery = true;
|
||||
startingTag = builder.Query.Contains("?") ? "&" : "?";
|
||||
}
|
||||
|
||||
builder.Query = hasQuery
|
||||
? $"{builder.Query}{startingTag}{parameter}={value}"
|
||||
: $"{startingTag}{parameter}={value}";
|
||||
return builder.Uri;
|
||||
}
|
||||
}
|
||||
}
|
10
src/Ombi.Api/ContentType.cs
Normal file
10
src/Ombi.Api/ContentType.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Ombi.Api
|
||||
{
|
||||
public enum ContentType
|
||||
{
|
||||
Json,
|
||||
Xml,
|
||||
Text,
|
||||
Html,
|
||||
}
|
||||
}
|
13
src/Ombi.Api/JsonContent.cs
Normal file
13
src/Ombi.Api/JsonContent.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Ombi.Api
|
||||
{
|
||||
internal class JsonContent : StringContent
|
||||
{
|
||||
public JsonContent(object obj) :
|
||||
base(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json")
|
||||
{ }
|
||||
}
|
||||
}
|
13
src/Ombi.Api/Ombi.Api.csproj
Normal file
13
src/Ombi.Api/Ombi.Api.csproj
Normal file
|
@ -0,0 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.6</TargetFramework>
|
||||
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
110
src/Ombi.Api/Request.cs
Normal file
110
src/Ombi.Api/Request.cs
Normal file
|
@ -0,0 +1,110 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
|
||||
namespace Ombi.Api
|
||||
{
|
||||
public class Request
|
||||
{
|
||||
public Request()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Request(string endpoint, string baseUrl, HttpMethod http, ContentType contentType = ContentType.Json)
|
||||
{
|
||||
Endpoint = endpoint;
|
||||
BaseUrl = baseUrl;
|
||||
HttpMethod = http;
|
||||
ContentType = contentType;
|
||||
}
|
||||
|
||||
public ContentType ContentType { get; }
|
||||
public string Endpoint { get; }
|
||||
public string BaseUrl { get; }
|
||||
public HttpMethod HttpMethod { get; }
|
||||
|
||||
private string FullUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (!string.IsNullOrEmpty(BaseUrl))
|
||||
{
|
||||
sb.Append(!BaseUrl.EndsWith("/") ? string.Format("{0}/", BaseUrl) : BaseUrl);
|
||||
}
|
||||
sb.Append(Endpoint.StartsWith("/") ? Endpoint.Remove(0, 1) : Endpoint);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private Uri _modified;
|
||||
|
||||
public Uri FullUri
|
||||
{
|
||||
get => _modified != null ? _modified : new Uri(FullUrl);
|
||||
set => _modified = value;
|
||||
}
|
||||
|
||||
public List<KeyValuePair<string, string>> Headers { get; } = new List<KeyValuePair<string, string>>();
|
||||
public List<KeyValuePair<string, string>> ContentHeaders { get; } = new List<KeyValuePair<string, string>>();
|
||||
|
||||
public object JsonBody { get; set; }
|
||||
|
||||
public bool IsValidUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
new Uri(FullUrl);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddHeader(string key, string value)
|
||||
{
|
||||
Headers.Add(new KeyValuePair<string, string>(key, value));
|
||||
}
|
||||
public void AddContentHeader(string key, string value)
|
||||
{
|
||||
ContentHeaders.Add(new KeyValuePair<string, string>(key, value));
|
||||
}
|
||||
|
||||
public void AddQueryString(string key, string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return;
|
||||
|
||||
var builder = new UriBuilder(FullUri);
|
||||
var startingTag = string.Empty;
|
||||
var hasQuery = false;
|
||||
if (string.IsNullOrEmpty(builder.Query))
|
||||
{
|
||||
startingTag = "?";
|
||||
}
|
||||
else
|
||||
{
|
||||
hasQuery = true;
|
||||
startingTag = builder.Query.Contains("?") ? "&" : "?";
|
||||
}
|
||||
|
||||
builder.Query = hasQuery
|
||||
? $"{builder.Query}{startingTag}{key}={value}"
|
||||
: $"{startingTag}{key}={value}";
|
||||
_modified = builder.Uri;
|
||||
}
|
||||
|
||||
public void AddJsonBody(object obj)
|
||||
{
|
||||
JsonBody = obj;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
36
src/Ombi.Core/Claims/OmbiClaims.cs
Normal file
36
src/Ombi.Core/Claims/OmbiClaims.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: OmbiClaims.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Core.Claims
|
||||
{
|
||||
public static class OmbiClaims
|
||||
{
|
||||
public const string Admin = nameof(Admin);
|
||||
public const string AutoApproveMovie = nameof(AutoApproveMovie);
|
||||
public const string AutoApproveTv = nameof(AutoApproveTv);
|
||||
public const string PowerUser = nameof(PowerUser);
|
||||
}
|
||||
}
|
56
src/Ombi.Core/Engine/BaseMediaEngine.cs
Normal file
56
src/Ombi.Core/Engine/BaseMediaEngine.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.Engine.Interfaces;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Requests.Models;
|
||||
using Ombi.Helpers;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public abstract class BaseMediaEngine : BaseEngine
|
||||
{
|
||||
protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService) : base(identity)
|
||||
{
|
||||
RequestService = requestService;
|
||||
}
|
||||
|
||||
protected IRequestServiceMain RequestService { get; }
|
||||
protected IRequestService<MovieRequestModel> MovieRequestService => RequestService.MovieRequestService;
|
||||
protected IRequestService<TvRequestModel> TvRequestService => RequestService.TvRequestService;
|
||||
|
||||
private long _cacheTime = 0;
|
||||
private Dictionary<int, MovieRequestModel> _dbMovies;
|
||||
private Dictionary<int, TvRequestModel> _dbTv;
|
||||
protected async Task<Dictionary<int, MovieRequestModel>> GetMovieRequests()
|
||||
{
|
||||
long now = DateTime.Now.Ticks;
|
||||
if (_dbMovies == null || (now - _cacheTime) > 10000)
|
||||
{
|
||||
var allResults = await MovieRequestService.GetAllAsync();
|
||||
|
||||
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
|
||||
_dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
|
||||
_cacheTime = now;
|
||||
}
|
||||
return _dbMovies;
|
||||
}
|
||||
|
||||
protected async Task<Dictionary<int, TvRequestModel>> GetTvRequests()
|
||||
{
|
||||
long now = DateTime.Now.Ticks;
|
||||
if (_dbTv == null || (now - _cacheTime) > 10000)
|
||||
{
|
||||
var allResults = await TvRequestService.GetAllAsync();
|
||||
|
||||
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
|
||||
_dbTv = distinctResults.ToDictionary(x => x.ProviderId);
|
||||
_cacheTime = now;
|
||||
}
|
||||
return _dbTv;
|
||||
}
|
||||
}
|
||||
}
|
16
src/Ombi.Core/Engine/ITvRequestEngine.cs
Normal file
16
src/Ombi.Core/Engine/ITvRequestEngine.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Models.Search;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public interface ITvRequestEngine
|
||||
{
|
||||
Task<IEnumerable<TvRequestModel>> GetTvRequests(int count, int position);
|
||||
Task RemoveTvRequest(int requestId);
|
||||
Task<RequestEngineResult> RequestTvShow(SearchTvShowViewModel tv);
|
||||
Task<IEnumerable<TvRequestModel>> SearchTvRequest(string search);
|
||||
Task<TvRequestModel> UpdateTvRequest(TvRequestModel request);
|
||||
}
|
||||
}
|
55
src/Ombi.Core/Engine/Interfaces/BaseEngine.cs
Normal file
55
src/Ombi.Core/Engine/Interfaces/BaseEngine.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
using System.Security.Principal;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Engine.Interfaces
|
||||
{
|
||||
public abstract class BaseEngine
|
||||
{
|
||||
protected BaseEngine(IPrincipal user)
|
||||
{
|
||||
User = user;
|
||||
}
|
||||
|
||||
protected IPrincipal User { get; }
|
||||
|
||||
protected string Username => User.Identity.Name;
|
||||
|
||||
protected bool HasRole(string roleName)
|
||||
{
|
||||
return User.IsInRole(roleName);
|
||||
}
|
||||
|
||||
protected bool ShouldSendNotification(RequestType type)
|
||||
{
|
||||
var sendNotification = !ShouldAutoApprove(type); /*|| !prSettings.IgnoreNotifyForAutoApprovedRequests;*/
|
||||
|
||||
if (HasRole(OmbiClaims.Admin))
|
||||
{
|
||||
sendNotification = false; // Don't bother sending a notification if the user is an admin
|
||||
|
||||
}
|
||||
return sendNotification;
|
||||
}
|
||||
|
||||
public bool ShouldAutoApprove(RequestType requestType)
|
||||
{
|
||||
var admin = HasRole(OmbiClaims.Admin);
|
||||
// if the user is an admin, they go ahead and allow auto-approval
|
||||
if (admin) return true;
|
||||
|
||||
// check by request type if the category requires approval or not
|
||||
switch (requestType)
|
||||
{
|
||||
case RequestType.Movie:
|
||||
return HasRole(OmbiClaims.AutoApproveMovie);
|
||||
case RequestType.TvShow:
|
||||
return HasRole(OmbiClaims.AutoApproveTv);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
16
src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs
Normal file
16
src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models.Search;
|
||||
|
||||
namespace Ombi.Core
|
||||
{
|
||||
public interface IMovieEngine
|
||||
{
|
||||
Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies();
|
||||
Task<IEnumerable<SearchMovieViewModel>> PopularMovies();
|
||||
Task<IEnumerable<SearchMovieViewModel>> Search(string search);
|
||||
Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies();
|
||||
Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies();
|
||||
Task<IEnumerable<SearchMovieViewModel>> LookupImdbInformation(IEnumerable<SearchMovieViewModel> movies);
|
||||
}
|
||||
}
|
18
src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs
Normal file
18
src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public interface IMovieRequestEngine
|
||||
{
|
||||
Task<RequestEngineResult> RequestMovie(SearchMovieViewModel model);
|
||||
bool ShouldAutoApprove(RequestType requestType);
|
||||
Task<IEnumerable<MovieRequestModel>> GetMovieRequests(int count, int position);
|
||||
Task<IEnumerable<MovieRequestModel>> SearchMovieRequest(string search);
|
||||
Task RemoveMovieRequest(int requestId);
|
||||
Task<MovieRequestModel> UpdateMovieRequest(MovieRequestModel request);
|
||||
}
|
||||
}
|
17
src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs
Normal file
17
src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models.Search;
|
||||
|
||||
namespace Ombi.Core.Engine.Interfaces
|
||||
{
|
||||
public interface ITvSearchEngine
|
||||
{
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm);
|
||||
|
||||
Task<SearchTvShowViewModel> GetShowInformation(int tvdbId);
|
||||
//Task<IEnumerable<SearchTvShowViewModel>> Popular();
|
||||
//Task<IEnumerable<SearchTvShowViewModel>> Anticipated();
|
||||
//Task<IEnumerable<SearchTvShowViewModel>> MostWatches();
|
||||
//Task<IEnumerable<SearchTvShowViewModel>> Trending();
|
||||
}
|
||||
}
|
256
src/Ombi.Core/Engine/MovieRequestEngine.cs
Normal file
256
src/Ombi.Core/Engine/MovieRequestEngine.cs
Normal file
|
@ -0,0 +1,256 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Hangfire;
|
||||
using Ombi.Api.TheMovieDb;
|
||||
using Ombi.Api.TvMaze;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Requests.Models;
|
||||
using Ombi.Store.Entities;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Notifications;
|
||||
using Ombi.Notifications.Models;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine
|
||||
{
|
||||
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, INotificationService notificationService) : base(user, requestService)
|
||||
{
|
||||
MovieApi = movieApi;
|
||||
NotificationService = notificationService;
|
||||
}
|
||||
private IMovieDbApi MovieApi { get; }
|
||||
private INotificationService NotificationService { get; }
|
||||
public async Task<RequestEngineResult> RequestMovie(SearchMovieViewModel model)
|
||||
{
|
||||
var movieInfo = await MovieApi.GetMovieInformation(model.Id);
|
||||
if (movieInfo == null)
|
||||
{
|
||||
return new RequestEngineResult
|
||||
{
|
||||
RequestAdded = false,
|
||||
Message = "There was an issue adding this movie!",
|
||||
ErrorMessage = $"TheMovieDb didn't have any information for ID {model.Id}"
|
||||
};
|
||||
}
|
||||
var fullMovieName =
|
||||
$"{movieInfo.Title}{(!string.IsNullOrEmpty(movieInfo.ReleaseDate) ? $" ({DateTime.Parse(movieInfo.ReleaseDate).Year})" : string.Empty)}";
|
||||
|
||||
var existingRequest = await MovieRequestService.CheckRequestAsync(model.Id);
|
||||
if (existingRequest != null)
|
||||
{
|
||||
return new RequestEngineResult
|
||||
{
|
||||
RequestAdded = false,
|
||||
Message = $"{fullMovieName} has already been requested"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// TODO
|
||||
//try
|
||||
//{
|
||||
|
||||
// var content = PlexContentRepository.GetAll();
|
||||
// var movies = PlexChecker.GetPlexMovies(content);
|
||||
// if (PlexChecker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
|
||||
// {
|
||||
// return
|
||||
// Response.AsJson(new JsonResponseModel
|
||||
// {
|
||||
// Result = false,
|
||||
// Message = $"{fullMovieName} is already in Plex!"
|
||||
// });
|
||||
// }
|
||||
//}
|
||||
//catch (Exception e)
|
||||
//{
|
||||
// Log.Error(e);
|
||||
// return
|
||||
// Response.AsJson(new JsonResponseModel
|
||||
// {
|
||||
// Result = false,
|
||||
// Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName, GetMediaServerName())
|
||||
// });
|
||||
//}
|
||||
|
||||
var requestModel = new MovieRequestModel
|
||||
{
|
||||
ProviderId = movieInfo.Id,
|
||||
Type = RequestType.Movie,
|
||||
Overview = movieInfo.Overview,
|
||||
ImdbId = movieInfo.ImdbId,
|
||||
PosterPath = movieInfo.PosterPath,
|
||||
Title = movieInfo.Title,
|
||||
ReleaseDate = !string.IsNullOrEmpty(movieInfo.ReleaseDate) ? DateTime.Parse(movieInfo.ReleaseDate) : DateTime.MinValue,
|
||||
Status = movieInfo.Status,
|
||||
RequestedDate = DateTime.UtcNow,
|
||||
Approved = false,
|
||||
RequestedUsers = new List<string> { Username },
|
||||
Issues = IssueState.None,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
if (ShouldAutoApprove(RequestType.Movie))
|
||||
{
|
||||
model.Approved = true;
|
||||
|
||||
// var result = await MovieSender.Send(model);
|
||||
// if (result.Result)
|
||||
// {
|
||||
// return await AddRequest(model, settings,
|
||||
// $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
||||
// }
|
||||
// if (result.Error)
|
||||
|
||||
// {
|
||||
// return
|
||||
// Response.AsJson(new JsonResponseModel
|
||||
// {
|
||||
// Message = "Could not add movie, please contact your administrator",
|
||||
// Result = false
|
||||
// });
|
||||
// }
|
||||
// if (!result.MovieSendingEnabled)
|
||||
// {
|
||||
|
||||
// return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
||||
// }
|
||||
|
||||
// return Response.AsJson(new JsonResponseModel
|
||||
// {
|
||||
// Result = false,
|
||||
// Message = Resources.UI.Search_CouchPotatoError
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
return await AddMovieRequest(requestModel, /*settings,*/
|
||||
$"{fullMovieName} has been successfully added!");
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//Log.Fatal(e);
|
||||
//await FaultQueue.QueueItemAsync(model, movieInfo.Id.ToString(), RequestType.Movie, FaultType.RequestFault, e.Message);
|
||||
var notification = new NotificationModel
|
||||
{
|
||||
DateTime = DateTime.Now,
|
||||
User = Username,
|
||||
RequestType = RequestType.Movie,
|
||||
Title = model.Title,
|
||||
NotificationType = NotificationType.ItemAddedToFaultQueue
|
||||
};
|
||||
BackgroundJob.Enqueue(() => NotificationService.Publish(notification).Wait());
|
||||
|
||||
//return Response.AsJson(new JsonResponseModel
|
||||
//{
|
||||
// Result = true,
|
||||
// Message = $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}"
|
||||
//});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private IEnumerable<EpisodesModel> GetListDifferences(IEnumerable<EpisodesModel> existing, IEnumerable<EpisodesModel> request)
|
||||
{
|
||||
var newRequest = request
|
||||
.Select(r =>
|
||||
new EpisodesModel
|
||||
{
|
||||
SeasonNumber = r.SeasonNumber,
|
||||
EpisodeNumber = r.EpisodeNumber
|
||||
}).ToList();
|
||||
|
||||
return newRequest.Except(existing);
|
||||
}
|
||||
|
||||
|
||||
private async Task<RequestEngineResult> AddMovieRequest(MovieRequestModel model, string message)
|
||||
{
|
||||
await MovieRequestService.AddRequestAsync(model);
|
||||
|
||||
if (ShouldSendNotification(model.Type))
|
||||
{
|
||||
var notificationModel = new NotificationModel
|
||||
{
|
||||
Title = model.Title,
|
||||
User = Username,
|
||||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest,
|
||||
RequestType = model.Type,
|
||||
ImgSrc = model.Type == RequestType.Movie ? $"https://image.tmdb.org/t/p/w300/{model.PosterPath}" : model.PosterPath
|
||||
};
|
||||
|
||||
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel).Wait());
|
||||
}
|
||||
|
||||
//var limit = await RequestLimitRepo.GetAllAsync();
|
||||
//var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type);
|
||||
//if (usersLimit == null)
|
||||
//{
|
||||
// await RequestLimitRepo.InsertAsync(new RequestLimit
|
||||
// {
|
||||
// Username = Username,
|
||||
// RequestType = model.Type,
|
||||
// FirstRequestDate = DateTime.UtcNow,
|
||||
// RequestCount = 1
|
||||
// });
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// usersLimit.RequestCount++;
|
||||
// await RequestLimitRepo.UpdateAsync(usersLimit);
|
||||
//}
|
||||
|
||||
return new RequestEngineResult { RequestAdded = true };
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MovieRequestModel>> GetMovieRequests(int count, int position)
|
||||
{
|
||||
var allRequests = await MovieRequestService.GetAllAsync(count, position);
|
||||
return allRequests;
|
||||
}
|
||||
public async Task<IEnumerable<MovieRequestModel>> SearchMovieRequest(string search)
|
||||
{
|
||||
var allRequests = await MovieRequestService.GetAllAsync();
|
||||
var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase));
|
||||
return results;
|
||||
}
|
||||
public async Task<MovieRequestModel> UpdateMovieRequest(MovieRequestModel request)
|
||||
{
|
||||
var allRequests = await MovieRequestService.GetAllAsync();
|
||||
var results = allRequests.FirstOrDefault(x => x.Id == request.Id);
|
||||
|
||||
results.Approved = request.Approved;
|
||||
results.Available = request.Available;
|
||||
results.Denied = request.Denied;
|
||||
results.DeniedReason = request.DeniedReason;
|
||||
results.AdminNote = request.AdminNote;
|
||||
results.ImdbId = request.ImdbId;
|
||||
results.IssueId = request.IssueId;
|
||||
results.Issues = request.Issues;
|
||||
results.OtherMessage = request.OtherMessage;
|
||||
results.Overview = request.Overview;
|
||||
results.PosterPath = request.PosterPath;
|
||||
results.RequestedUsers = request.RequestedUsers?.ToList() ?? new List<string>();
|
||||
|
||||
|
||||
var model = MovieRequestService.UpdateRequest(results);
|
||||
return model;
|
||||
}
|
||||
|
||||
public async Task RemoveMovieRequest(int requestId)
|
||||
{
|
||||
await MovieRequestService.DeleteRequestAsync(requestId);
|
||||
}
|
||||
}
|
||||
}
|
185
src/Ombi.Core/Engine/MovieSearchEngine.cs
Normal file
185
src/Ombi.Core/Engine/MovieSearchEngine.cs
Normal file
|
@ -0,0 +1,185 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Api.TheMovieDb;
|
||||
using Ombi.Api.TheMovieDb.Models;
|
||||
using Ombi.Core.IdentityResolver;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Requests.Models;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public class MovieSearchEngine : BaseMediaEngine, IMovieEngine
|
||||
{
|
||||
|
||||
public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ISettingsService<PlexSettings> plexSettings, ISettingsService<EmbySettings> embySettings,
|
||||
ILogger<MovieSearchEngine> logger)
|
||||
: base(identity, service)
|
||||
{
|
||||
MovieApi = movApi;
|
||||
Mapper = mapper;
|
||||
PlexSettings = plexSettings;
|
||||
EmbySettings = embySettings;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
private IMovieDbApi MovieApi { get; }
|
||||
private IMapper Mapper { get; }
|
||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
private ILogger<MovieSearchEngine> Logger { get; }
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> LookupImdbInformation(IEnumerable<SearchMovieViewModel> movies)
|
||||
{
|
||||
var searchMovieViewModels
|
||||
= movies as IList<SearchMovieViewModel> ?? movies.ToList();
|
||||
if (searchMovieViewModels == null || !searchMovieViewModels.Any())
|
||||
{
|
||||
return new List<SearchMovieViewModel>();
|
||||
}
|
||||
|
||||
var retVal = new List<SearchMovieViewModel>();
|
||||
Dictionary<int, MovieRequestModel> dbMovies = await GetMovieRequests();
|
||||
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
|
||||
foreach (var m in searchMovieViewModels)
|
||||
{
|
||||
var movieInfo = await MovieApi.GetMovieInformationWithVideo(m.Id);
|
||||
var viewMovie = Mapper.Map<SearchMovieViewModel>(movieInfo);
|
||||
|
||||
retVal.Add(await ProcessSingleMovie(viewMovie, dbMovies, plexSettings, embySettings));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> Search(string search)
|
||||
{
|
||||
var result = await MovieApi.SearchMovie(search);
|
||||
if (result != null)
|
||||
{
|
||||
Logger.LogDebug("Search Result: {result}", result);
|
||||
return await TransformMovieResultsToResponse(result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> PopularMovies()
|
||||
{
|
||||
var result = await MovieApi.PopularMovies();
|
||||
if (result != null)
|
||||
{
|
||||
Logger.LogDebug("Search Result: {result}", result);
|
||||
return await TransformMovieResultsToResponse(result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies()
|
||||
{
|
||||
var result = await MovieApi.TopRated();
|
||||
if (result != null)
|
||||
{
|
||||
Logger.LogDebug("Search Result: {result}", result);
|
||||
return await TransformMovieResultsToResponse(result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies()
|
||||
{
|
||||
var result = await MovieApi.Upcoming();
|
||||
if (result != null)
|
||||
{
|
||||
Logger.LogDebug("Search Result: {result}", result);
|
||||
return await TransformMovieResultsToResponse(result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies()
|
||||
{
|
||||
var result = await MovieApi.NowPlaying();
|
||||
if (result != null)
|
||||
{
|
||||
|
||||
Logger.LogDebug("Search Result: {result}", result);
|
||||
return await TransformMovieResultsToResponse(result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private async Task<List<SearchMovieViewModel>> TransformMovieResultsToResponse(IEnumerable<MovieSearchResult> movies)
|
||||
{
|
||||
var viewMovies = new List<SearchMovieViewModel>();
|
||||
Dictionary<int, MovieRequestModel> dbMovies = await GetMovieRequests();
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
foreach (var movie in movies)
|
||||
{
|
||||
|
||||
viewMovies.Add(await ProcessSingleMovie(movie, dbMovies, plexSettings, embySettings));
|
||||
|
||||
}
|
||||
return viewMovies;
|
||||
}
|
||||
|
||||
private async Task<SearchMovieViewModel> ProcessSingleMovie(SearchMovieViewModel viewMovie,
|
||||
Dictionary<int, MovieRequestModel> existingRequests, PlexSettings plexSettings, EmbySettings embySettings)
|
||||
{
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
// var content = PlexContentRepository.GetAll();
|
||||
// var plexMovies = PlexChecker.GetPlexMovies(content);
|
||||
|
||||
// var plexMovie = PlexChecker.GetMovie(plexMovies.ToArray(), movie.Title,
|
||||
// movie.ReleaseDate?.Year.ToString(),
|
||||
// viewMovie.ImdbId);
|
||||
// if (plexMovie != null)
|
||||
// {
|
||||
// viewMovie.Available = true;
|
||||
// viewMovie.PlexUrl = plexMovie.Url;
|
||||
// }
|
||||
}
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
// var embyContent = EmbyContentRepository.GetAll();
|
||||
// var embyMovies = EmbyChecker.GetEmbyMovies(embyContent);
|
||||
|
||||
// var embyMovie = EmbyChecker.GetMovie(embyMovies.ToArray(), movie.Title,
|
||||
// movie.ReleaseDate?.Year.ToString(), viewMovie.ImdbId);
|
||||
// if (embyMovie != null)
|
||||
// {
|
||||
// viewMovie.Available = true;
|
||||
// }
|
||||
}
|
||||
|
||||
if (existingRequests.ContainsKey(viewMovie.Id)) // Do we already have a request for this?
|
||||
{
|
||||
var requestedMovie = existingRequests[viewMovie.Id];
|
||||
|
||||
viewMovie.Requested = true;
|
||||
viewMovie.Approved = requestedMovie.Approved;
|
||||
viewMovie.Available = requestedMovie.Available;
|
||||
}
|
||||
|
||||
|
||||
return viewMovie;
|
||||
}
|
||||
|
||||
private async Task<SearchMovieViewModel> ProcessSingleMovie(MovieSearchResult movie, Dictionary<int, MovieRequestModel> existingRequests, PlexSettings plexSettings, EmbySettings embySettings)
|
||||
{
|
||||
var viewMovie = Mapper.Map<SearchMovieViewModel>(movie);
|
||||
return await ProcessSingleMovie(viewMovie, existingRequests, plexSettings, embySettings);
|
||||
}
|
||||
}
|
||||
}
|
10
src/Ombi.Core/Engine/RequestEngineResult.cs
Normal file
10
src/Ombi.Core/Engine/RequestEngineResult.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public class RequestEngineResult
|
||||
{
|
||||
public bool RequestAdded { get; set; }
|
||||
public string Message { get; set; }
|
||||
public bool IsError => !string.IsNullOrEmpty(ErrorMessage);
|
||||
public string ErrorMessage { get; set; }
|
||||
}
|
||||
}
|
253
src/Ombi.Core/Engine/TvRequestEngine.cs
Normal file
253
src/Ombi.Core/Engine/TvRequestEngine.cs
Normal file
|
@ -0,0 +1,253 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using Hangfire;
|
||||
using Ombi.Api.TvMaze;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Store.Entities;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Notifications;
|
||||
using Ombi.Notifications.Models;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine
|
||||
{
|
||||
public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPrincipal user, INotificationService notificationService, IMapper map) : base(user, requestService)
|
||||
{
|
||||
TvApi = tvApi;
|
||||
NotificationService = notificationService;
|
||||
Mapper = map;
|
||||
}
|
||||
private INotificationService NotificationService { get; }
|
||||
private ITvMazeApi TvApi { get; }
|
||||
private IMapper Mapper { get; }
|
||||
|
||||
public async Task<RequestEngineResult> RequestTvShow(SearchTvShowViewModel tv)
|
||||
{
|
||||
|
||||
var showInfo = await TvApi.ShowLookupByTheTvDbId(tv.Id);
|
||||
DateTime.TryParse(showInfo.premiered, out DateTime firstAir);
|
||||
|
||||
// For some reason the poster path is always http
|
||||
var posterPath = showInfo.image?.medium.Replace("http:", "https:");
|
||||
var model = new TvRequestModel
|
||||
{
|
||||
Id = tv.Id,
|
||||
Type = RequestType.TvShow,
|
||||
Overview = showInfo.summary.RemoveHtml(),
|
||||
PosterPath = posterPath,
|
||||
Title = showInfo.name,
|
||||
ReleaseDate = firstAir,
|
||||
Status = showInfo.status,
|
||||
RequestedDate = DateTime.UtcNow,
|
||||
Approved = false,
|
||||
RequestedUsers = new List<string> { Username },
|
||||
Issues = IssueState.None,
|
||||
ImdbId = showInfo.externals?.imdb ?? string.Empty,
|
||||
TvDbId = tv.Id.ToString(),
|
||||
ProviderId = tv.Id,
|
||||
RequestAll = tv.RequestAll
|
||||
};
|
||||
|
||||
var episodes = await TvApi.EpisodeLookup(showInfo.id);
|
||||
|
||||
foreach (var e in episodes)
|
||||
{
|
||||
var season = model.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season);
|
||||
season?.Episodes.Add(new EpisodesRequested
|
||||
{
|
||||
Url = e.url,
|
||||
Title = e.name,
|
||||
AirDate = DateTime.Parse(e.airstamp),
|
||||
EpisodeNumber = e.number,
|
||||
});
|
||||
}
|
||||
|
||||
if (tv.LatestSeason)
|
||||
{
|
||||
var latest = showInfo.Season.OrderBy(x => x.SeasonNumber).FirstOrDefault();
|
||||
foreach (var modelSeasonRequest in model.SeasonRequests)
|
||||
{
|
||||
if (modelSeasonRequest.SeasonNumber == latest.SeasonNumber)
|
||||
{
|
||||
foreach (var episodesRequested in modelSeasonRequest.Episodes)
|
||||
{
|
||||
episodesRequested.Requested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tv.FirstSeason)
|
||||
{
|
||||
var first = showInfo.Season.OrderByDescending(x => x.SeasonNumber).FirstOrDefault();
|
||||
foreach (var modelSeasonRequest in model.SeasonRequests)
|
||||
{
|
||||
if (modelSeasonRequest.SeasonNumber == first.SeasonNumber)
|
||||
{
|
||||
foreach (var episodesRequested in modelSeasonRequest.Episodes)
|
||||
{
|
||||
episodesRequested.Requested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var existingRequest = await TvRequestService.CheckRequestAsync(model.Id);
|
||||
if (existingRequest != null)
|
||||
{
|
||||
return await AddExistingRequest(model, existingRequest);
|
||||
}
|
||||
|
||||
// This is a new request
|
||||
return await AddRequest(model);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TvRequestModel>> GetTvRequests(int count, int position)
|
||||
{
|
||||
var allRequests = await TvRequestService.GetAllAsync(count, position);
|
||||
return allRequests;
|
||||
}
|
||||
public async Task<IEnumerable<TvRequestModel>> SearchTvRequest(string search)
|
||||
{
|
||||
var allRequests = await TvRequestService.GetAllAsync();
|
||||
var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase));
|
||||
return results;
|
||||
}
|
||||
public async Task<TvRequestModel> UpdateTvRequest(TvRequestModel request)
|
||||
{
|
||||
var allRequests = await TvRequestService.GetAllAsync();
|
||||
var results = allRequests.FirstOrDefault(x => x.Id == request.Id);
|
||||
|
||||
results.Approved = request.Approved;
|
||||
results.Available = request.Available;
|
||||
results.Denied = request.Denied;
|
||||
results.DeniedReason = request.DeniedReason;
|
||||
results.AdminNote = request.AdminNote;
|
||||
results.ImdbId = request.ImdbId;
|
||||
results.IssueId = request.IssueId;
|
||||
results.Issues = request.Issues;
|
||||
results.OtherMessage = request.OtherMessage;
|
||||
results.Overview = request.Overview;
|
||||
results.PosterPath = request.PosterPath;
|
||||
results.RequestedUsers = request.RequestedUsers?.ToList() ?? new List<string>();
|
||||
|
||||
var model = TvRequestService.UpdateRequest(results);
|
||||
return model;
|
||||
}
|
||||
|
||||
public async Task RemoveTvRequest(int requestId)
|
||||
{
|
||||
await TvRequestService.DeleteRequestAsync(requestId);
|
||||
}
|
||||
|
||||
private async Task<RequestEngineResult> AddExistingRequest(TvRequestModel newRequest, TvRequestModel existingRequest)
|
||||
{
|
||||
var episodeDifference = new List<SeasonRequestModel>();
|
||||
if (existingRequest.HasChildRequests)
|
||||
{
|
||||
// Let's check if this has already been requested as a child!
|
||||
foreach (var children in existingRequest.ChildRequests)
|
||||
{
|
||||
var difference = GetListDifferences(children.SeasonRequests, newRequest.SeasonRequests).ToList();
|
||||
if (difference.Any())
|
||||
{
|
||||
episodeDifference = difference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (episodeDifference.Any())
|
||||
{
|
||||
// This is where there are some episodes that have been requested, but this list contains the 'new' requests
|
||||
newRequest.SeasonRequests = episodeDifference;
|
||||
}
|
||||
|
||||
if (!existingRequest.HasChildRequests)
|
||||
{
|
||||
// So this is the first child request, we will want to convert the original request to a child
|
||||
var originalRequest = Mapper.Map<TvRequestModel>(existingRequest);
|
||||
existingRequest.ChildRequests.Add(originalRequest);
|
||||
existingRequest.RequestedUsers.Clear();
|
||||
existingRequest.Approved = false;
|
||||
existingRequest.Available = false;
|
||||
}
|
||||
|
||||
existingRequest.ChildRequests.Add(newRequest);
|
||||
|
||||
TvRequestService.UpdateRequest(existingRequest);
|
||||
|
||||
if (ShouldAutoApprove(RequestType.TvShow))
|
||||
{
|
||||
// TODO Auto Approval Code
|
||||
}
|
||||
return await AfterRequest(newRequest);
|
||||
}
|
||||
|
||||
private IEnumerable<SeasonRequestModel> GetListDifferences(IEnumerable<SeasonRequestModel> existing, IEnumerable<SeasonRequestModel> request)
|
||||
{
|
||||
var newRequest = request
|
||||
.Select(r =>
|
||||
new SeasonRequestModel
|
||||
{
|
||||
SeasonNumber = r.SeasonNumber,
|
||||
Episodes = r.Episodes
|
||||
}).ToList();
|
||||
|
||||
return newRequest.Except(existing);
|
||||
}
|
||||
|
||||
private async Task<RequestEngineResult> AddRequest(TvRequestModel model)
|
||||
{
|
||||
await TvRequestService.AddRequestAsync(model);
|
||||
|
||||
return await AfterRequest(model);
|
||||
}
|
||||
|
||||
private async Task<RequestEngineResult> AfterRequest(BaseRequestModel model)
|
||||
{
|
||||
if (ShouldSendNotification(model.Type))
|
||||
{
|
||||
var notificationModel = new NotificationModel
|
||||
{
|
||||
Title = model.Title,
|
||||
User = Username,
|
||||
DateTime = DateTime.Now,
|
||||
NotificationType = NotificationType.NewRequest,
|
||||
RequestType = model.Type,
|
||||
ImgSrc = model.PosterPath
|
||||
};
|
||||
|
||||
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel).Wait());
|
||||
}
|
||||
|
||||
//var limit = await RequestLimitRepo.GetAllAsync();
|
||||
//var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type);
|
||||
//if (usersLimit == null)
|
||||
//{
|
||||
// await RequestLimitRepo.InsertAsync(new RequestLimit
|
||||
// {
|
||||
// Username = Username,
|
||||
// RequestType = model.Type,
|
||||
// FirstRequestDate = DateTime.UtcNow,
|
||||
// RequestCount = 1
|
||||
// });
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// usersLimit.RequestCount++;
|
||||
// await RequestLimitRepo.UpdateAsync(usersLimit);
|
||||
//}
|
||||
|
||||
return new RequestEngineResult { RequestAdded = true };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
194
src/Ombi.Core/Engine/TvSearchEngine.cs
Normal file
194
src/Ombi.Core/Engine/TvSearchEngine.cs
Normal file
|
@ -0,0 +1,194 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using Ombi.Api.Trakt;
|
||||
using Ombi.Api.TvMaze;
|
||||
using Ombi.Api.TvMaze.Models;
|
||||
using Ombi.Core.Engine.Interfaces;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Requests.Models;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
public class TvSearchEngine : BaseMediaEngine, ITvSearchEngine
|
||||
{
|
||||
|
||||
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService<PlexSettings> plexSettings,
|
||||
ISettingsService<EmbySettings> embySettings)
|
||||
: base(identity, service)
|
||||
{
|
||||
TvMazeApi = tvMaze;
|
||||
Mapper = mapper;
|
||||
PlexSettings = plexSettings;
|
||||
EmbySettings = embySettings;
|
||||
//TraktApi = trakt;
|
||||
}
|
||||
|
||||
private ITvMazeApi TvMazeApi { get; }
|
||||
private IMapper Mapper { get; }
|
||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
//private ITraktApi TraktApi { get; }
|
||||
|
||||
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm)
|
||||
{
|
||||
var searchResult = await TvMazeApi.Search(searchTerm);
|
||||
|
||||
if (searchResult != null)
|
||||
{
|
||||
return await ProcessResults(searchResult);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<SearchTvShowViewModel> GetShowInformation(int tvmazeId)
|
||||
{
|
||||
var show = await TvMazeApi.ShowLookup(tvmazeId);
|
||||
var episodes = await TvMazeApi.EpisodeLookup(show.id);
|
||||
|
||||
var mapped = Mapper.Map<SearchTvShowViewModel>(show);
|
||||
|
||||
foreach (var e in episodes)
|
||||
{
|
||||
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season);
|
||||
if (season == null)
|
||||
{
|
||||
var newSeason = new SeasonRequestModel
|
||||
{
|
||||
SeasonNumber = e.season,
|
||||
};
|
||||
newSeason.Episodes.Add(new EpisodesRequested
|
||||
{
|
||||
Url = e.url,
|
||||
Title = e.name,
|
||||
AirDate = DateTime.Parse(e.airstamp),
|
||||
EpisodeNumber = e.number,
|
||||
});
|
||||
mapped.SeasonRequests.Add(newSeason);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
season.Episodes.Add(new EpisodesRequested
|
||||
{
|
||||
Url = e.url,
|
||||
Title = e.name,
|
||||
AirDate = DateTime.Parse(e.airstamp),
|
||||
EpisodeNumber = e.number,
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var existingRequests = await GetTvRequests();
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
return ProcessResult(mapped, existingRequests, plexSettings, embySettings);
|
||||
}
|
||||
|
||||
//public async Task<IEnumerable<SearchTvShowViewModel>> Popular()
|
||||
//{
|
||||
// var result = await TraktApi.GetPopularShows();
|
||||
// return await ProcessResults(result);
|
||||
//}
|
||||
|
||||
//public async Task<IEnumerable<SearchTvShowViewModel>> Anticipated()
|
||||
//{
|
||||
// var result = await TraktApi.GetAnticipatedShows();
|
||||
// return await ProcessResults(result);
|
||||
//}
|
||||
//public async Task<IEnumerable<SearchTvShowViewModel>> MostWatches()
|
||||
//{
|
||||
// var result = await TraktApi.GetMostWatchesShows();
|
||||
// return await ProcessResults(result);
|
||||
//}
|
||||
//public async Task<IEnumerable<SearchTvShowViewModel>> Trending()
|
||||
//{
|
||||
// var result = await TraktApi.GetTrendingShows();
|
||||
// return await ProcessResults(result);
|
||||
//}
|
||||
|
||||
private async Task<IEnumerable<SearchTvShowViewModel>> ProcessResults<T>(IEnumerable<T> items)
|
||||
{
|
||||
var existingRequests = await GetTvRequests();
|
||||
|
||||
var plexSettings = await PlexSettings.GetSettingsAsync();
|
||||
var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
|
||||
var retVal = new List<SearchTvShowViewModel>();
|
||||
foreach (var tvMazeSearch in items)
|
||||
{
|
||||
var viewT = Mapper.Map<SearchTvShowViewModel>(tvMazeSearch);
|
||||
retVal.Add(ProcessResult(viewT, existingRequests, plexSettings, embySettings));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private SearchTvShowViewModel ProcessResult(SearchTvShowViewModel item, Dictionary<int, TvRequestModel> existingRequests, PlexSettings plexSettings, EmbySettings embySettings)
|
||||
{
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
//var embyShow = EmbyChecker.GetTvShow(embyCached.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId);
|
||||
//if (embyShow != null)
|
||||
//{
|
||||
// viewT.Available = true;
|
||||
//}
|
||||
}
|
||||
if (plexSettings.Enable)
|
||||
{
|
||||
//var plexShow = PlexChecker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4),
|
||||
// providerId);
|
||||
//if (plexShow != null)
|
||||
//{
|
||||
// viewT.Available = true;
|
||||
// viewT.PlexUrl = plexShow.Url;
|
||||
//}
|
||||
}
|
||||
|
||||
if (item.Id > 0 && item.Available)
|
||||
{
|
||||
var tvdbid = item.Id;
|
||||
if (existingRequests.ContainsKey(tvdbid))
|
||||
{
|
||||
var existingRequest = existingRequests[tvdbid];
|
||||
|
||||
item.Requested = true;
|
||||
item.Approved = existingRequest.Approved;
|
||||
|
||||
// Let's modify the seasonsrequested to reflect what we have requested...
|
||||
foreach (var season in item.SeasonRequests)
|
||||
{
|
||||
// Find the existing request season
|
||||
var existingSeason =
|
||||
existingRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == season.SeasonNumber);
|
||||
|
||||
foreach (var ep in existingSeason.Episodes)
|
||||
{
|
||||
// Find the episode from what we are searching
|
||||
var episodeSearching = season.Episodes.FirstOrDefault(x => x.EpisodeNumber == ep.EpisodeNumber);
|
||||
episodeSearching.Requested = ep.Requested;
|
||||
episodeSearching.Available = ep.Available;
|
||||
episodeSearching.Approved = ep.Approved;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//if (sonarrCached.Select(x => x.TvdbId).Contains(tvdbid) || sickRageCache.Contains(tvdbid))
|
||||
// // compare to the sonarr/sickrage db
|
||||
//{
|
||||
// item.Requested = true;
|
||||
//}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
16
src/Ombi.Core/IdentityResolver/IUserIdentityManager.cs
Normal file
16
src/Ombi.Core/IdentityResolver/IUserIdentityManager.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models;
|
||||
|
||||
namespace Ombi.Core.IdentityResolver
|
||||
{
|
||||
public interface IUserIdentityManager
|
||||
{
|
||||
Task<UserDto> CreateUser(UserDto user);
|
||||
Task<bool> CredentialsValid(string username, string password);
|
||||
Task<UserDto> GetUser(string username);
|
||||
Task<IEnumerable<UserDto>> GetUsers();
|
||||
Task DeleteUser(UserDto user);
|
||||
Task<UserDto> UpdateUser(UserDto userDto);
|
||||
}
|
||||
}
|
126
src/Ombi.Core/IdentityResolver/UserIdentityManager.cs
Normal file
126
src/Ombi.Core/IdentityResolver/UserIdentityManager.cs
Normal file
|
@ -0,0 +1,126 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: UserIdentityManager.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
using Ombi.Core.Models;
|
||||
using Ombi.Store.Entities;
|
||||
using Ombi.Store.Repository;
|
||||
|
||||
namespace Ombi.Core.IdentityResolver
|
||||
{
|
||||
public class UserIdentityManager : IUserIdentityManager
|
||||
{
|
||||
public UserIdentityManager(IUserRepository userRepository, IMapper mapper)
|
||||
{
|
||||
UserRepository = userRepository;
|
||||
Mapper = mapper;
|
||||
}
|
||||
|
||||
private IMapper Mapper { get; }
|
||||
private IUserRepository UserRepository { get; }
|
||||
|
||||
public async Task<bool> CredentialsValid(string username, string password)
|
||||
{
|
||||
var user = await UserRepository.GetUser(username);
|
||||
if (user == null) return false;
|
||||
|
||||
var hash = HashPassword(password, user.Salt);
|
||||
|
||||
return hash.HashedPass.Equals(user.Password);
|
||||
}
|
||||
|
||||
public async Task<UserDto> GetUser(string username)
|
||||
{
|
||||
return Mapper.Map<UserDto>(await UserRepository.GetUser(username));
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<UserDto>> GetUsers()
|
||||
{
|
||||
return Mapper.Map<List<UserDto>>(await UserRepository.GetUsers());
|
||||
}
|
||||
|
||||
public async Task<UserDto> CreateUser(UserDto userDto)
|
||||
{
|
||||
var user = Mapper.Map<User>(userDto);
|
||||
user.Claims.RemoveAll(x => x.Type == ClaimTypes.Country); // This is a hack around the Mapping Profile
|
||||
var result = HashPassword(user.Password);
|
||||
user.Password = result.HashedPass;
|
||||
user.Salt = result.Salt;
|
||||
await UserRepository.CreateUser(user);
|
||||
|
||||
return Mapper.Map<UserDto>(user);
|
||||
}
|
||||
|
||||
public async Task DeleteUser(UserDto user)
|
||||
{
|
||||
await UserRepository.DeleteUser(Mapper.Map<User>(user));
|
||||
}
|
||||
|
||||
public async Task<UserDto> UpdateUser(UserDto userDto)
|
||||
{
|
||||
var user = Mapper.Map<User>(userDto);
|
||||
return Mapper.Map<UserDto>(await UserRepository.UpdateUser(user));
|
||||
}
|
||||
|
||||
private UserHash HashPassword(string password)
|
||||
{
|
||||
// generate a 128-bit salt using a secure PRNG
|
||||
byte[] salt = new byte[128 / 8];
|
||||
using (var rng = RandomNumberGenerator.Create())
|
||||
{
|
||||
rng.GetBytes(salt);
|
||||
}
|
||||
return HashPassword(password, salt);
|
||||
}
|
||||
|
||||
|
||||
private UserHash HashPassword(string password, byte[] salt)
|
||||
{
|
||||
// derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
|
||||
var hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
|
||||
password: password,
|
||||
salt: salt,
|
||||
prf: KeyDerivationPrf.HMACSHA1,
|
||||
iterationCount: 10000,
|
||||
numBytesRequested: 256 / 8));
|
||||
|
||||
return new UserHash { HashedPass = hashed, Salt = salt };
|
||||
}
|
||||
|
||||
private class UserHash
|
||||
{
|
||||
public string HashedPass { get; set; }
|
||||
public byte[] Salt { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
8
src/Ombi.Core/Models/QualityModel.cs
Normal file
8
src/Ombi.Core/Models/QualityModel.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Core.Models
|
||||
{
|
||||
public class QualityModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
59
src/Ombi.Core/Models/Requests/BaseRequestModel.cs
Normal file
59
src/Ombi.Core/Models/Requests/BaseRequestModel.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public class BaseRequestModel : Entity
|
||||
{
|
||||
public BaseRequestModel()
|
||||
{
|
||||
RequestedUsers = new List<string>();
|
||||
}
|
||||
public int ProviderId { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string PosterPath { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public RequestType Type { get; set; }
|
||||
public string Status { get; set; }
|
||||
public bool Approved { get; set; }
|
||||
public bool Admin { get; set; }
|
||||
public DateTime RequestedDate { get; set; }
|
||||
public bool Available { get; set; }
|
||||
public IssueState Issues { get; set; }
|
||||
public string OtherMessage { get; set; }
|
||||
public string AdminNote { get; set; }
|
||||
public List<string> RequestedUsers { get; set; }
|
||||
public int IssueId { get; set; }
|
||||
public bool Denied { get; set; }
|
||||
public string DeniedReason { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool Released => DateTime.UtcNow > ReleaseDate;
|
||||
|
||||
[JsonIgnore]
|
||||
public IEnumerable<string> AllUsers
|
||||
{
|
||||
get
|
||||
{
|
||||
var u = new List<string>();
|
||||
if (RequestedUsers != null && RequestedUsers.Any())
|
||||
{
|
||||
u.AddRange(RequestedUsers);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public bool CanApprove => !Approved && !Available;
|
||||
|
||||
public bool UserHasRequested(string username)
|
||||
{
|
||||
return AllUsers.Any(x => x.Equals(username, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
26
src/Ombi.Core/Models/Requests/IRequestService.cs
Normal file
26
src/Ombi.Core/Models/Requests/IRequestService.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Requests.Models
|
||||
{
|
||||
public interface IRequestService<T> where T : BaseRequestModel
|
||||
{
|
||||
int AddRequest(T model);
|
||||
Task<int> AddRequestAsync(T model);
|
||||
void BatchDelete(IEnumerable<T> model);
|
||||
void BatchUpdate(IEnumerable<T> model);
|
||||
T CheckRequest(int providerId);
|
||||
Task<T> CheckRequestAsync(int providerId);
|
||||
void DeleteRequest(T request);
|
||||
Task DeleteRequestAsync(int request);
|
||||
Task DeleteRequestAsync(T request);
|
||||
T Get(int id);
|
||||
IEnumerable<T> GetAll();
|
||||
Task<IEnumerable<T>> GetAllAsync();
|
||||
Task<IEnumerable<T>> GetAllAsync(int count, int position);
|
||||
Task<T> GetAsync(int id);
|
||||
T UpdateRequest(T model);
|
||||
}
|
||||
}
|
179
src/Ombi.Core/Models/Requests/JsonRequestService.cs
Normal file
179
src/Ombi.Core/Models/Requests/JsonRequestService.cs
Normal file
|
@ -0,0 +1,179 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Requests.Models;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Store.Entities;
|
||||
using Ombi.Store.Repository;
|
||||
|
||||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public class JsonRequestService<T> : IRequestService<T> where T : BaseRequestModel
|
||||
{
|
||||
public JsonRequestService(IRequestRepository repo)
|
||||
{
|
||||
Repo = repo;
|
||||
RequestType = typeof(T) == typeof(TvRequestModel) ? RequestType.TvShow : RequestType.Movie;
|
||||
}
|
||||
private RequestType RequestType { get; }
|
||||
private IRequestRepository Repo { get; }
|
||||
public int AddRequest(T model)
|
||||
{
|
||||
var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId };
|
||||
var id = Repo.Insert(entity);
|
||||
|
||||
return id.Id;
|
||||
}
|
||||
|
||||
public async Task<int> AddRequestAsync(T model)
|
||||
{
|
||||
var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId };
|
||||
var id = await Repo.InsertAsync(entity).ConfigureAwait(false);
|
||||
|
||||
return id.Id;
|
||||
}
|
||||
|
||||
public T CheckRequest(int providerId)
|
||||
{
|
||||
var blobs = Repo.GetAll();
|
||||
var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType);
|
||||
|
||||
if (blob == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
||||
model.Id = blob.Id;
|
||||
return model;
|
||||
}
|
||||
|
||||
public async Task<T> CheckRequestAsync(int providerId)
|
||||
{
|
||||
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
|
||||
var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType); if (blob == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
||||
model.Id = blob.Id;
|
||||
return model;
|
||||
}
|
||||
|
||||
public void DeleteRequest(T request)
|
||||
{
|
||||
var blob = Repo.Get(request.Id);
|
||||
Repo.Delete(blob);
|
||||
}
|
||||
|
||||
public async Task DeleteRequestAsync(T request)
|
||||
{
|
||||
var blob = await Repo.GetAsync(request.Id).ConfigureAwait(false);
|
||||
Repo.Delete(blob);
|
||||
}
|
||||
public async Task DeleteRequestAsync(int request)
|
||||
{
|
||||
var blob = await Repo.GetAsync(request).ConfigureAwait(false);
|
||||
Repo.Delete(blob);
|
||||
}
|
||||
|
||||
public T UpdateRequest(T model)
|
||||
{
|
||||
var b = Repo.Get(model.Id);
|
||||
b.Content = ByteConverterHelper.ReturnBytes(model);
|
||||
var blob = Repo.Update(b);
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
public T Get(int id)
|
||||
{
|
||||
var blob = Repo.Get(id);
|
||||
if (blob == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
||||
model.Id = blob.Id; // They should always be the same, but for somereason a user didn't have it in the db https://github.com/tidusjar/Ombi/issues/862#issuecomment-269743847
|
||||
return model;
|
||||
}
|
||||
|
||||
public async Task<T> GetAsync(int id)
|
||||
{
|
||||
var blob = await Repo.GetAsync(id).ConfigureAwait(false);
|
||||
if (blob == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
||||
model.Id = blob.Id;
|
||||
return model;
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetAll()
|
||||
{
|
||||
var blobs = Repo.GetAll().Where(x => x.Type == RequestType).ToList();
|
||||
var retVal = new List<T>();
|
||||
|
||||
foreach (var b in blobs)
|
||||
{
|
||||
if (b == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
|
||||
model.Id = b.Id;
|
||||
retVal.Add(model);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<T>> GetAllAsync()
|
||||
{
|
||||
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
|
||||
var retVal = new List<T>();
|
||||
|
||||
foreach (var b in blobs.Where(x => x.Type == RequestType))
|
||||
{
|
||||
if (b == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
|
||||
model.Id = b.Id;
|
||||
retVal.Add(model);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<T>> GetAllAsync(int count, int position)
|
||||
{
|
||||
var blobs = await Repo.GetAllAsync(count, position).ConfigureAwait(false);
|
||||
var retVal = new List<T>();
|
||||
|
||||
foreach (var b in blobs.Where(x => x.Type == RequestType))
|
||||
{
|
||||
if (b == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
|
||||
model.Id = b.Id;
|
||||
retVal.Add(model);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void BatchUpdate(IEnumerable<T> model)
|
||||
{
|
||||
var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ByteConverterHelper.ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList();
|
||||
Repo.UpdateAll(entities);
|
||||
}
|
||||
|
||||
public void BatchDelete(IEnumerable<T> model)
|
||||
{
|
||||
var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ByteConverterHelper.ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList();
|
||||
Repo.DeleteAll(entities);
|
||||
}
|
||||
}
|
||||
}
|
15
src/Ombi.Core/Models/Requests/Movie/MovieRequestModel.cs
Normal file
15
src/Ombi.Core/Models/Requests/Movie/MovieRequestModel.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public class MovieRequestModel : BaseRequestModel
|
||||
{
|
||||
|
||||
public string ImdbId { get; set; }
|
||||
|
||||
}
|
||||
}
|
77
src/Ombi.Core/Models/Requests/RequestModel.cs
Normal file
77
src/Ombi.Core/Models/Requests/RequestModel.cs
Normal file
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public static class RequestTypeDisplay
|
||||
{
|
||||
public static string GetString(this RequestType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RequestType.Movie:
|
||||
return "Movie";
|
||||
case RequestType.TvShow:
|
||||
return "TV Show";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum IssueState
|
||||
{
|
||||
None = 99,
|
||||
WrongAudio = 0,
|
||||
NoSubtitles = 1,
|
||||
WrongContent = 2,
|
||||
PlaybackIssues = 3,
|
||||
Other = 4, // Provide a message
|
||||
}
|
||||
|
||||
public class EpisodesModel : IEquatable<EpisodesModel>
|
||||
{
|
||||
public int SeasonNumber { get; set; }
|
||||
public int EpisodeNumber { get; set; }
|
||||
public bool Equals(EpisodesModel other)
|
||||
{
|
||||
// Check whether the compared object is null.
|
||||
if (ReferenceEquals(other, null)) return false;
|
||||
|
||||
//Check whether the compared object references the same data.
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
//Check whether the properties are equal.
|
||||
return SeasonNumber.Equals(other.SeasonNumber) && EpisodeNumber.Equals(other.EpisodeNumber);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashSeason = SeasonNumber.GetHashCode();
|
||||
var hashEp = EpisodeNumber.GetHashCode();
|
||||
|
||||
//Calculate the hash code.
|
||||
return hashSeason + hashEp;
|
||||
}
|
||||
}
|
||||
|
||||
public class SeasonRequestModel
|
||||
{
|
||||
public int SeasonNumber { get; set; }
|
||||
public List<EpisodesRequested> Episodes { get; set; } = new List<EpisodesRequested>();
|
||||
}
|
||||
|
||||
public class EpisodesRequested
|
||||
{
|
||||
public int EpisodeNumber { get; set; }
|
||||
public string Title { get; set; }
|
||||
public DateTime AirDate { get; set; }
|
||||
public string Url { get; set; }
|
||||
public bool Requested { get; set; }
|
||||
public string Status { get; set; }
|
||||
public bool Available { get; set; }
|
||||
public bool Approved { get; set; }
|
||||
}
|
||||
|
||||
}
|
16
src/Ombi.Core/Models/Requests/RequestService.cs
Normal file
16
src/Ombi.Core/Models/Requests/RequestService.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using Ombi.Core.Requests.Models;
|
||||
|
||||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public class RequestService : IRequestServiceMain
|
||||
{
|
||||
public RequestService(IRequestService<TvRequestModel> tv, IRequestService<MovieRequestModel> movie)
|
||||
{
|
||||
TvRequestService = tv;
|
||||
MovieRequestService = movie;
|
||||
}
|
||||
|
||||
public IRequestService<TvRequestModel> TvRequestService { get; }
|
||||
public IRequestService<MovieRequestModel> MovieRequestService { get; }
|
||||
}
|
||||
}
|
33
src/Ombi.Core/Models/Requests/RequestViewModel.cs
Normal file
33
src/Ombi.Core/Models/Requests/RequestViewModel.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public class RequestViewModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int ProviderId { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string PosterPath { get; set; }
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
public bool Released { get; set; }
|
||||
public RequestType Type { get; set; }
|
||||
public string Status { get; set; }
|
||||
public bool Approved { get; set; }
|
||||
public string[] RequestedUsers { get; set; }
|
||||
public DateTime RequestedDate { get; set; }
|
||||
public string ReleaseYear { get; set; }
|
||||
public bool Available { get; set; }
|
||||
public bool Admin { get; set; }
|
||||
public int IssueId { get; set; }
|
||||
public QualityModel[] Qualities { get; set; }
|
||||
public EpisodesModel[] Episodes { get; set; }
|
||||
public bool Denied { get; set; }
|
||||
public string DeniedReason { get; set; }
|
||||
public RootFolderModel[] RootFolders { get; set; }
|
||||
public bool HasRootFolders { get; set; }
|
||||
public string CurrentRootPath { get; set; }
|
||||
}
|
||||
}
|
34
src/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs
Normal file
34
src/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public class TvRequestModel : BaseRequestModel
|
||||
{
|
||||
public TvRequestModel()
|
||||
{
|
||||
SeasonRequests = new List<SeasonRequestModel>();
|
||||
ChildRequests = new List<TvRequestModel>();
|
||||
}
|
||||
|
||||
public string ImdbId { get; set; }
|
||||
public string TvDbId { get; set; }
|
||||
public bool RequestAll { get; set; }
|
||||
public List<SeasonRequestModel> SeasonRequests { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is for TV requests, If there is more than 1 request for a show then it should be a child
|
||||
/// e.g. Request 1 is for Season 1, Request 2 is for season 5. There should be two child items.
|
||||
/// </summary>
|
||||
public List<TvRequestModel> ChildRequests { get; set; }
|
||||
|
||||
public bool HasChildRequests => ChildRequests.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// For TV Shows with a custom root folder
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The root folder selected.
|
||||
/// </value>
|
||||
public int RootFolderSelected { get; set; }
|
||||
}
|
||||
}
|
9
src/Ombi.Core/Models/RootFolderModel.cs
Normal file
9
src/Ombi.Core/Models/RootFolderModel.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ombi.Core.Models.Requests
|
||||
{
|
||||
public class RootFolderModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Path { get; set; }
|
||||
public long FreeSpace { get; set; }
|
||||
}
|
||||
}
|
54
src/Ombi.Core/Models/Search/SearchMovieViewModel.cs
Normal file
54
src/Ombi.Core/Models/Search/SearchMovieViewModel.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: SearchMovieViewModel.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;
|
||||
|
||||
namespace Ombi.Core.Models.Search
|
||||
{
|
||||
public class SearchMovieViewModel : SearchViewModel
|
||||
{
|
||||
public bool Adult { get; set; }
|
||||
public string BackdropPath { get; set; }
|
||||
public List<int> GenreIds { get; set; }
|
||||
public int Id { get; set; }
|
||||
public string OriginalLanguage { get; set; }
|
||||
public string OriginalTitle { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public double Popularity { get; set; }
|
||||
public string PosterPath { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool Video { get; set; }
|
||||
public double VoteAverage { get; set; }
|
||||
public int VoteCount { get; set; }
|
||||
public bool AlreadyInCp { get; set; }
|
||||
public string Trailer { get; set; }
|
||||
public string Homepage { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
}
|
||||
}
|
53
src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs
Normal file
53
src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using System.Collections.Generic;
|
||||
using Ombi.Core.Models.Requests;
|
||||
|
||||
namespace Ombi.Core.Models.Search
|
||||
{
|
||||
public class SearchTvShowViewModel : SearchViewModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public List<string> Aliases { get; set; }
|
||||
public string Banner { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public string Status { get; set; }
|
||||
public string FirstAired { get; set; }
|
||||
public string Network { get; set; }
|
||||
public string NetworkId { get; set; }
|
||||
public string Runtime { get; set; }
|
||||
public List<string> Genre { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public int LastUpdated { get; set; }
|
||||
public string AirsDayOfWeek { get; set; }
|
||||
public string AirsTime { get; set; }
|
||||
public string Rating { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public int SiteRating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is used from the Trakt API
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The trailer.
|
||||
/// </value>
|
||||
public string Trailer { get; set; }
|
||||
/// <summary>
|
||||
/// This is used from the Trakt API
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The trailer.
|
||||
/// </value>
|
||||
public string Homepage { get; set; }
|
||||
|
||||
public List<SeasonRequestModel> SeasonRequests { get; set; } = new List<SeasonRequestModel>();
|
||||
|
||||
/// <summary>
|
||||
/// If we are requesting the entire series
|
||||
/// </summary>
|
||||
public bool RequestAll { get; set; }
|
||||
|
||||
public bool FirstSeason { get; set; }
|
||||
public bool LatestSeason { get; set; }
|
||||
|
||||
}
|
||||
}
|
36
src/Ombi.Core/Models/Search/SearchViewModel.cs
Normal file
36
src/Ombi.Core/Models/Search/SearchViewModel.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: SearchViewModel.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Core.Models.Search
|
||||
{
|
||||
public class SearchViewModel
|
||||
{
|
||||
public bool Approved { get; set; }
|
||||
public bool Requested { get; set; }
|
||||
public bool Available { get; set; }
|
||||
public string PlexUrl { get; set; }
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue