Merge remote-tracking branch 'upstream/dev'

pull/1243/head
Patrick Frisch 7 years ago
commit cd2c9a40e5

@ -0,0 +1,9 @@
using Ombi.Api.Models.Appveyor;
namespace Ombi.Api.Interfaces
{
public interface IAppveyorApi
{
AppveyorProjects GetProjectHistory(string branchName, int records = 10);
}
}

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using Ombi.Api.Models.Emby;
namespace Ombi.Api.Interfaces
{
public interface IEmbyApi
{
EmbyItemContainer<EmbyMovieItem> GetAllMovies(string apiKey, string userId, Uri baseUri);
EmbyItemContainer<EmbySeriesItem> GetAllShows(string apiKey, string userId, Uri baseUri);
EmbyItemContainer<EmbyEpisodeItem> GetAllEpisodes(string apiKey, string userId, Uri baseUri);
EmbyItemContainer<EmbyMovieInformation> GetCollection(string mediaId, string apiKey, string userId, Uri baseUrl);
List<EmbyUser> GetUsers(Uri baseUri, string apiKey);
EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri);
EmbyInformation GetInformation(string mediaId, EmbyMediaType type, string apiKey, string userId, Uri baseUri);
EmbyUser LogIn(string username, string password, string apiKey, Uri baseUri);
EmbySystemInfo GetSystemInformation(string apiKey, Uri baseUrl);
}
}

@ -8,8 +8,9 @@ namespace Ombi.Api.Interfaces
public interface IRadarrApi
{
RadarrAddMovie AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, Uri baseUrl, bool searchNow = false);
List<RadarrMovieResponse> GetMovies(string apiKey, Uri baseUrl);
RadarrMovieContainer GetMovies(string apiKey, Uri baseUrl);
List<SonarrProfile> GetProfiles(string apiKey, Uri baseUrl);
SystemStatus SystemStatus(string apiKey, Uri baseUrl);
List<SonarrRootFolder> GetRootFolders(string apiKey, Uri baseUrl);
}
}

@ -54,8 +54,10 @@
</ItemGroup>
<ItemGroup>
<Compile Include="IApiRequest.cs" />
<Compile Include="IAppveyorApi.cs" />
<Compile Include="ICouchPotatoApi.cs" />
<Compile Include="IDiscordApi.cs" />
<Compile Include="IEmbyApi.cs" />
<Compile Include="IHeadphonesApi.cs" />
<Compile Include="IMusicBrainzApi.cs" />
<Compile Include="INetflixApi.cs" />

@ -0,0 +1,114 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: AppveyorProject.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.Models.Appveyor
{
public class AppveyorProjects
{
public Project project { get; set; }
public Build[] builds { get; set; }
}
public class Project
{
public int projectId { get; set; }
public int accountId { get; set; }
public string accountName { get; set; }
public object[] builds { get; set; }
public string name { get; set; }
public string slug { get; set; }
public string repositoryType { get; set; }
public string repositoryScm { get; set; }
public string repositoryName { get; set; }
public bool isPrivate { get; set; }
public bool skipBranchesWithoutAppveyorYml { get; set; }
public bool enableSecureVariablesInPullRequests { get; set; }
public bool enableSecureVariablesInPullRequestsFromSameRepo { get; set; }
public bool enableDeploymentInPullRequests { get; set; }
public bool rollingBuilds { get; set; }
public bool alwaysBuildClosedPullRequests { get; set; }
public string tags { get; set; }
public Securitydescriptor securityDescriptor { get; set; }
public DateTime created { get; set; }
public DateTime updated { get; set; }
}
public class Securitydescriptor
{
public Accessrightdefinition[] accessRightDefinitions { get; set; }
public Roleace[] roleAces { get; set; }
}
public class Accessrightdefinition
{
public string name { get; set; }
public string description { get; set; }
}
public class Roleace
{
public int roleId { get; set; }
public string name { get; set; }
public bool isAdmin { get; set; }
public Accessright[] accessRights { get; set; }
}
public class Accessright
{
public string name { get; set; }
public bool allowed { get; set; }
}
public class Build
{
public int buildId { get; set; }
public object[] jobs { get; set; }
public int buildNumber { get; set; }
public string version { get; set; }
public string message { get; set; }
public string messageExtended { get; set; }
public string branch { get; set; }
public bool isTag { get; set; }
public string commitId { get; set; }
public string authorName { get; set; }
public string authorUsername { get; set; }
public string committerName { get; set; }
public string committerUsername { get; set; }
public DateTime committed { get; set; }
public object[] messages { get; set; }
public string status { get; set; }
public DateTime started { get; set; }
public DateTime finished { get; set; }
public DateTime created { get; set; }
public DateTime updated { get; set; }
public string pullRequestId { get; set; }
public string pullRequestName { get; set; }
}
}

@ -0,0 +1,37 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyChapter
{
public long StartPositionTicks { get; set; }
public string Name { get; set; }
}
}

@ -0,0 +1,47 @@
#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
namespace Ombi.Api.Models.Emby
{
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; }
}
}

@ -0,0 +1,97 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyEpisodeInformation.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.Models.Emby
{
public class EmbyEpisodeInformation
{
public string Name { get; set; }
public string ServerId { get; set; }
public string Id { get; set; }
public string Etag { get; set; }
public DateTime DateCreated { get; set; }
public bool CanDelete { get; set; }
public bool CanDownload { get; set; }
public bool SupportsSync { get; set; }
public string Container { get; set; }
public string SortName { get; set; }
public DateTime PremiereDate { get; set; }
public EmbyExternalurl[] ExternalUrls { get; set; }
public EmbyMediasource[] MediaSources { get; set; }
public string Path { get; set; }
public string Overview { get; set; }
public object[] Taglines { get; set; }
public object[] Genres { get; set; }
public string[] SeriesGenres { get; set; }
public float CommunityRating { get; set; }
public int VoteCount { get; set; }
public long RunTimeTicks { get; set; }
public string PlayAccess { get; set; }
public int ProductionYear { get; set; }
public bool IsPlaceHolder { get; set; }
public int IndexNumber { get; set; }
public int ParentIndexNumber { get; set; }
public object[] RemoteTrailers { get; set; }
public EmbyProviderids ProviderIds { get; set; }
public bool IsHD { get; set; }
public bool IsFolder { get; set; }
public string ParentId { get; set; }
public string Type { get; set; }
public object[] People { get; set; }
public object[] Studios { get; set; }
public string ParentLogoItemId { get; set; }
public string ParentBackdropItemId { get; set; }
public string[] ParentBackdropImageTags { get; set; }
public int LocalTrailerCount { get; set; }
public EmbyUserdata UserData { get; set; }
public string SeriesName { get; set; }
public string SeriesId { get; set; }
public string SeasonId { get; set; }
public string DisplayPreferencesId { get; set; }
public object[] Tags { get; set; }
public object[] Keywords { get; set; }
public string SeriesPrimaryImageTag { get; set; }
public string SeasonName { get; set; }
public EmbyMediastream[] MediaStreams { get; set; }
public string VideoType { get; set; }
public EmbyImagetags ImageTags { get; set; }
public object[] BackdropImageTags { get; set; }
public object[] ScreenshotImageTags { get; set; }
public string ParentLogoImageTag { get; set; }
public string SeriesStudio { get; set; }
public EmbySeriesstudioinfo SeriesStudioInfo { get; set; }
public string ParentThumbItemId { get; set; }
public string ParentThumbImageTag { get; set; }
public EmbyChapter[] Chapters { get; set; }
public string LocationType { get; set; }
public string MediaType { get; set; }
public object[] LockedFields { get; set; }
public bool LockData { get; set; }
}
}

@ -0,0 +1,69 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyEpisodeItem.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.Models.Emby
{
public class EmbyEpisodeItem
{
public string Name { get; set; }
public string ServerId { get; set; }
public string Id { get; set; }
public string Container { get; set; }
public DateTime PremiereDate { get; set; }
public float CommunityRating { get; set; }
public long RunTimeTicks { get; set; }
public string PlayAccess { get; set; }
public int ProductionYear { get; set; }
public bool IsPlaceHolder { get; set; }
public int IndexNumber { get; set; }
public int ParentIndexNumber { get; set; }
public bool IsHD { get; set; }
public bool IsFolder { get; set; }
public string Type { get; set; }
public string ParentLogoItemId { get; set; }
public string ParentBackdropItemId { get; set; }
public string[] ParentBackdropImageTags { get; set; }
public int LocalTrailerCount { get; set; }
public EmbyUserdata UserData { get; set; }
public string SeriesName { get; set; }
public string SeriesId { get; set; }
public string SeasonId { get; set; }
public string SeriesPrimaryImageTag { get; set; }
public string SeasonName { get; set; }
public string VideoType { get; set; }
public EmbyImagetags ImageTags { get; set; }
public object[] BackdropImageTags { get; set; }
public string ParentLogoImageTag { get; set; }
public string ParentThumbItemId { get; set; }
public string ParentThumbImageTag { get; set; }
public string LocationType { get; set; }
public string MediaType { get; set; }
public bool HasSubtitles { get; set; }
}
}

@ -0,0 +1,42 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyExternalurl
{
public string Name { get; set; }
public string Url { get; set; }
}
}

@ -0,0 +1,37 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyLibrary.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.Models.Emby
{
public class EmbyImagetags
{
public string Primary { get; set; }
public string Logo { get; set; }
public string Thumb { get; set; }
public string Banner { get; set; }
}
}

@ -0,0 +1,35 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyInformation.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.Models.Emby
{
public class EmbyInformation
{
public EmbySeriesInformation SeriesInformation { get; set; }
public EmbyMovieInformation MovieInformation { get; set; }
public EmbyEpisodeInformation EpisodeInformation { get; set; }
}
}

@ -0,0 +1,47 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyLibrary.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.Models.Emby
{
public class EmbyLibrary
{
public string Name { get; set; }
public string ServerId { get; set; }
public string Id { get; set; }
public bool HasDynamicCategories { get; set; }
public string PlayAccess { get; set; }
public bool IsFolder { get; set; }
public string Type { get; set; }
public EmbyUserdata UserData { get; set; }
public int ChildCount { get; set; }
public string CollectionType { get; set; }
public string OriginalCollectionType { get; set; }
public EmbyImagetags ImageTags { get; set; }
public object[] BackdropImageTags { get; set; }
public string LocationType { get; set; }
}
}

@ -0,0 +1,37 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyItemContainer.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System.Collections.Generic;
namespace Ombi.Api.Models.Emby
{
public class EmbyItemContainer<T>
{
public List<T> Items { get; set; }
public int TotalRecordCount { get; set; }
}
}

@ -0,0 +1,36 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyMediaType.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.Models.Emby
{
public enum EmbyMediaType
{
Movie = 0,
Series = 1,
Music = 2,
Episode = 3
}
}

@ -0,0 +1,59 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyMediasource
{
public string Protocol { get; set; }
public string Id { get; set; }
public string Path { get; set; }
public string Type { get; set; }
public string Container { get; set; }
public string Name { get; set; }
public bool IsRemote { get; set; }
public string ETag { get; set; }
public long RunTimeTicks { get; set; }
public bool ReadAtNativeFramerate { get; set; }
public bool SupportsTranscoding { get; set; }
public bool SupportsDirectStream { get; set; }
public bool SupportsDirectPlay { get; set; }
public bool IsInfiniteStream { get; set; }
public bool RequiresOpening { get; set; }
public bool RequiresClosing { get; set; }
public bool SupportsProbing { get; set; }
public string VideoType { get; set; }
public EmbyMediastream[] MediaStreams { get; set; }
public object[] PlayableStreamFileNames { get; set; }
public object[] Formats { get; set; }
public int Bitrate { get; set; }
public EmbyRequiredhttpheaders RequiredHttpHeaders { get; set; }
public int DefaultAudioStreamIndex { get; set; }
}
}

@ -0,0 +1,64 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyMediastream
{
public string Codec { get; set; }
public string Language { get; set; }
public string TimeBase { get; set; }
public string CodecTimeBase { get; set; }
public string NalLengthSize { get; set; }
public bool IsInterlaced { get; set; }
public bool IsAVC { get; set; }
public int BitRate { get; set; }
public int BitDepth { get; set; }
public int RefFrames { get; set; }
public bool IsDefault { get; set; }
public bool IsForced { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public float AverageFrameRate { get; set; }
public float RealFrameRate { get; set; }
public string Profile { get; set; }
public string Type { get; set; }
public string AspectRatio { get; set; }
public int Index { get; set; }
public bool IsExternal { get; set; }
public bool IsTextSubtitleStream { get; set; }
public bool SupportsExternalStream { get; set; }
public string PixelFormat { get; set; }
public int Level { get; set; }
public bool IsAnamorphic { get; set; }
public string DisplayTitle { get; set; }
public string ChannelLayout { get; set; }
public int Channels { get; set; }
public int SampleRate { get; set; }
}
}

@ -0,0 +1,87 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyMovieInformation
{
public string Name { get; set; }
public string OriginalTitle { get; set; }
public string ServerId { get; set; }
public string Id { get; set; }
public string Etag { get; set; }
public DateTime DateCreated { get; set; }
public bool CanDelete { get; set; }
public bool CanDownload { get; set; }
public bool SupportsSync { get; set; }
public string Container { get; set; }
public string SortName { get; set; }
public DateTime PremiereDate { get; set; }
public EmbyExternalurl[] ExternalUrls { get; set; }
public EmbyMediasource[] MediaSources { get; set; }
public string[] ProductionLocations { get; set; }
public string Path { get; set; }
public string OfficialRating { get; set; }
public string Overview { get; set; }
public string[] Taglines { get; set; }
public string[] Genres { get; set; }
public float CommunityRating { get; set; }
public int VoteCount { get; set; }
public long RunTimeTicks { get; set; }
public string PlayAccess { get; set; }
public int ProductionYear { get; set; }
public bool IsPlaceHolder { get; set; }
public EmbyRemotetrailer[] RemoteTrailers { get; set; }
public EmbyProviderids ProviderIds { get; set; }
public bool IsHD { get; set; }
public bool IsFolder { get; set; }
public string ParentId { get; set; }
public string Type { get; set; }
public EmbyPerson[] People { get; set; }
public EmbyStudio[] Studios { get; set; }
public int LocalTrailerCount { get; set; }
public EmbyUserdata UserData { get; set; }
public string DisplayPreferencesId { get; set; }
public object[] Tags { get; set; }
public string[] Keywords { get; set; }
public EmbyMediastream[] MediaStreams { get; set; }
public string VideoType { get; set; }
public EmbyImagetags ImageTags { get; set; }
public string[] BackdropImageTags { get; set; }
public object[] ScreenshotImageTags { get; set; }
public EmbyChapter[] Chapters { get; set; }
public string LocationType { get; set; }
public string MediaType { get; set; }
public string HomePageUrl { get; set; }
public int Budget { get; set; }
public int Revenue { get; set; }
public object[] LockedFields { get; set; }
public bool LockData { get; set; }
}
}

@ -0,0 +1,59 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyMovieItem.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.Models.Emby
{
public class EmbyMovieItem
{
public string Name { get; set; }
public string ServerId { get; set; }
public string Id { get; set; }
public string Container { get; set; }
public DateTime PremiereDate { get; set; }
public object[] ProductionLocations { get; set; }
public string OfficialRating { get; set; }
public float CommunityRating { get; set; }
public long RunTimeTicks { get; set; }
public string PlayAccess { get; set; }
public int ProductionYear { get; set; }
public bool IsPlaceHolder { get; set; }
public bool IsHD { get; set; }
public bool IsFolder { get; set; }
public string Type { get; set; }
public int LocalTrailerCount { get; set; }
public EmbyUserdata UserData { get; set; }
public string VideoType { get; set; }
public EmbyImagetags ImageTags { get; set; }
public string[] BackdropImageTags { get; set; }
public string LocationType { get; set; }
public string MediaType { get; set; }
public bool HasSubtitles { get; set; }
public int CriticRating { get; set; }
}
}

@ -0,0 +1,39 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyPerson
{
public string Name { get; set; }
public string Id { get; set; }
public string Role { get; set; }
public string Type { get; set; }
public string PrimaryImageTag { get; set; }
}
}

@ -0,0 +1,63 @@
#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
namespace Ombi.Api.Models.Emby
{
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; }
}
}

@ -0,0 +1,41 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyProviderids
{
public string Tmdb { get; set; }
public string Imdb { get; set; }
public string TmdbCollection { get; set; }
public string Tvdb { get; set; }
public string Zap2It { get; set; }
public string TvRage { get; set; }
}
}

@ -0,0 +1,36 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyRemotetrailer
{
public string Url { get; set; }
public string Name { get; set; }
}
}

@ -0,0 +1,36 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyRequiredhttpheaders
{
}
}

@ -0,0 +1,83 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbySeriesInformation.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.Models.Emby
{
public class EmbySeriesInformation
{
public string Name { get; set; }
public string ServerId { get; set; }
public string Id { get; set; }
public string Etag { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateLastMediaAdded { get; set; }
public bool CanDelete { get; set; }
public bool CanDownload { get; set; }
public bool SupportsSync { get; set; }
public string SortName { get; set; }
public DateTime PremiereDate { get; set; }
public EmbyExternalurl[] ExternalUrls { get; set; }
public string Path { get; set; }
public string OfficialRating { get; set; }
public string Overview { get; set; }
public string ShortOverview { get; set; }
public object[] Taglines { get; set; }
public string[] Genres { get; set; }
public float CommunityRating { get; set; }
public int VoteCount { get; set; }
public long CumulativeRunTimeTicks { get; set; }
public long RunTimeTicks { get; set; }
public string PlayAccess { get; set; }
public int ProductionYear { get; set; }
public EmbyRemotetrailer[] RemoteTrailers { get; set; }
public EmbyProviderids ProviderIds { get; set; }
public bool IsFolder { get; set; }
public string ParentId { get; set; }
public string Type { get; set; }
public EmbyPerson[] People { get; set; }
public EmbyStudio[] Studios { get; set; }
public int LocalTrailerCount { get; set; }
public EmbyUserdata UserData { get; set; }
public int RecursiveItemCount { get; set; }
public int ChildCount { get; set; }
public string DisplayPreferencesId { get; set; }
public string Status { get; set; }
public string AirTime { get; set; }
public string[] AirDays { get; set; }
public object[] Tags { get; set; }
public object[] Keywords { get; set; }
public EmbyImagetags ImageTags { get; set; }
public string[] BackdropImageTags { get; set; }
public object[] ScreenshotImageTags { get; set; }
public string LocationType { get; set; }
public string HomePageUrl { get; set; }
public object[] LockedFields { get; set; }
public bool LockData { get; set; }
}
}

@ -0,0 +1,56 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbySeriesItem.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.Models.Emby
{
public class EmbySeriesItem
{
public string Name { get; set; }
public string ServerId { get; set; }
public string Id { get; set; }
public DateTime PremiereDate { get; set; }
public string OfficialRating { get; set; }
public float CommunityRating { get; set; }
public long RunTimeTicks { get; set; }
public string PlayAccess { get; set; }
public int ProductionYear { get; set; }
public bool IsFolder { get; set; }
public string Type { get; set; }
public int LocalTrailerCount { get; set; }
public EmbyUserdata UserData { get; set; }
public int ChildCount { get; set; }
public string Status { get; set; }
public string AirTime { get; set; }
public string[] AirDays { get; set; }
public EmbyImagetags ImageTags { get; set; }
public string[] BackdropImageTags { get; set; }
public string LocationType { get; set; }
public DateTime EndDate { get; set; }
}
}

@ -0,0 +1,37 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyEpisodeInformation.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.Models.Emby
{
public class EmbySeriesstudioinfo
{
public string Name { get; set; }
public string Id { get; set; }
}
}

@ -0,0 +1,37 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieInformation.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.Models.Emby
{
public class EmbyStudio
{
public string Name { get; set; }
public string Id { get; set; }
}
}

@ -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.Models.Emby
{
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; }
}
}

@ -0,0 +1,53 @@
#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.Models.Emby
{
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; }
}
public class EmbyUserLogin
{
public EmbyUser User { get; set; }
}
}

@ -0,0 +1,42 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyLibrary.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.Models.Emby
{
public class EmbyUserdata
{
public double PlaybackPositionTicks { get; set; }
public int PlayCount { get; set; }
public bool IsFavorite { get; set; }
public bool Played { get; set; }
public string Key { get; set; }
public DateTime LastPlayedDate { get; set; }
public int UnplayedItemCount { get; set; }
}
}

@ -49,6 +49,33 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Appveyor\AppveyorProject.cs" />
<Compile Include="Emby\EmbyChapter.cs" />
<Compile Include="Emby\EmbyConfiguration.cs" />
<Compile Include="Emby\EmbyEpisodeInformation.cs" />
<Compile Include="Emby\EmbyEpisodeItem.cs" />
<Compile Include="Emby\EmbyExternalurl.cs" />
<Compile Include="Emby\EmbyImagetags.cs" />
<Compile Include="Emby\EmbyInformation.cs" />
<Compile Include="Emby\EmbyItem.cs" />
<Compile Include="Emby\EmbyItemContainer.cs" />
<Compile Include="Emby\EmbyMediasource.cs" />
<Compile Include="Emby\EmbyMediastream.cs" />
<Compile Include="Emby\EmbyMediaType.cs" />
<Compile Include="Emby\EmbyMovieItem.cs" />
<Compile Include="Emby\EmbyPerson.cs" />
<Compile Include="Emby\EmbyPolicy.cs" />
<Compile Include="Emby\EmbyProviderids.cs" />
<Compile Include="Emby\EmbyRemotetrailer.cs" />
<Compile Include="Emby\EmbyRequiredhttpheaders.cs" />
<Compile Include="Emby\EmbySeriesInformation.cs" />
<Compile Include="Emby\EmbySeriesItem.cs" />
<Compile Include="Emby\EmbySeriesstudioinfo.cs" />
<Compile Include="Emby\EmbyStudio.cs" />
<Compile Include="Emby\EmbySystemInfo.cs" />
<Compile Include="Emby\EmbyUser.cs" />
<Compile Include="Emby\EmbyUserdata.cs" />
<Compile Include="Emby\EmbyMovieInformation.cs" />
<Compile Include="Movie\CouchPotatoAdd.cs" />
<Compile Include="Movie\CouchPotatoMovies.cs" />
<Compile Include="Movie\CouchPotatoProfiles.cs" />
@ -87,6 +114,7 @@
<Compile Include="Radarr\RadarrAddMovie.cs" />
<Compile Include="Radarr\RadarrAddOptions.cs" />
<Compile Include="Radarr\RadarrError.cs" />
<Compile Include="Radarr\RadarrMovieContainer.cs" />
<Compile Include="Radarr\RadarrMovieResponse.cs" />
<Compile Include="SickRage\SickRageBase.cs" />
<Compile Include="SickRage\SickrageShows.cs" />

@ -0,0 +1,41 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: RadarrMovieContainer.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System.Collections.Generic;
namespace Ombi.Api.Models.Radarr
{
public class RadarrMovieContainer
{
public int page { get; set; }
public int pageSize { get; set; }
public string sortKey { get; set; }
public string sortDirection { get; set; }
public int totalRecords { get; set; }
public List<RadarrMovieResponse> records { get; set; }
}
}

@ -15,7 +15,7 @@ namespace Ombi.Api.Models.Tv
public string language { get; set; }
public List<string> genres { get; set; }
public string status { get; set; }
public int runtime { get; set; }
public double runtime { get; set; }
public string premiered { get; set; }
public Schedule schedule { get; set; }
public Rating rating { get; set; }

@ -49,13 +49,6 @@ namespace Ombi.Api.Models.Watcher
public string requiredwords { get; set; }
}
public class Quality
{
[JsonProperty("Quality")]
public Quality2 quality { get; set; }
public Filters Filters { get; set; }
}
public class WatcherListStatusResult
{
public string status { get; set; }
@ -72,7 +65,7 @@ namespace Ombi.Api.Models.Watcher
public string dvd { get; set; }
public string tomatorating { get; set; }
public string imdbid { get; set; }
public Quality quality { get; set; }
public string quality { get; set; }
}

@ -27,6 +27,7 @@
using System;
using System.IO;
using System.Net;
using System.Xml.Serialization;
using Newtonsoft.Json;
using NLog;
@ -55,72 +56,46 @@ namespace Ombi.Api
public T Execute<T>(IRestRequest request, Uri baseUri) where T : new()
{
var client = new RestClient { BaseUrl = baseUri };
var response = client.Execute<T>(request);
Log.Trace("Api Content Response:");
Log.Trace(response.Content);
Log.Trace($"Request made to {response.ResponseUri} with status code {response.StatusCode}. The response was {response.Content}");
if (response.ErrorException != null)
{
var message = "Error retrieving response. Check inner details for more info.";
Log.Error(response.ErrorException);
throw new ApiRequestException(message, response.ErrorException);
}
if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created)
return response.Data;
else
throw new ApiRequestException($"Got StatusCode={response.StatusCode} for {response.ResponseUri}.");
return response.Data;
}
public IRestResponse Execute(IRestRequest request, Uri baseUri)
{
var client = new RestClient { BaseUrl = baseUri };
var response = client.Execute(request);
if (response.ErrorException != null)
{
Log.Error(response.ErrorException);
var message = "Error retrieving response. Check inner details for more info.";
throw new ApiRequestException(message, response.ErrorException);
}
return response;
}
public T ExecuteXml<T>(IRestRequest request, Uri baseUri) where T : class
{
var client = new RestClient { BaseUrl = baseUri };
var response = client.Execute(request);
Log.Trace($"Request made to {response.ResponseUri} with status code {response.StatusCode}. The response was {response.Content}");
if (response.ErrorException != null)
{
Log.Error(response.ErrorException);
var message = "Error retrieving response. Check inner details for more info.";
throw new ApiRequestException(message, response.ErrorException);
}
if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created)
return DeserializeXml<T>(response.Content);
else
throw new ApiRequestException($"Got StatusCode={response.StatusCode} for {response.ResponseUri}.");
var result = DeserializeXml<T>(response.Content);
return result;}
}
public T ExecuteJson<T>(IRestRequest request, Uri baseUri) where T : new()
{
var client = new RestClient { BaseUrl = baseUri };
var response = client.Execute(request);
Log.Trace("Api Content Response:");
Log.Trace(response.Content);
if (response.ErrorException != null)
{
Log.Error(response.ErrorException);
var message = "Error retrieving response. Check inner details for more info.";
throw new ApiRequestException(message, response.ErrorException);
}
Log.Trace("Deserialzing Object");
var json = JsonConvert.DeserializeObject<T>(response.Content, _settings);
Log.Trace("Finished Deserialzing Object");
Log.Trace($"Request made to {response.ResponseUri} with status code {response.StatusCode}. The response was {response.Content}");
return json;
if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created)
return JsonConvert.DeserializeObject<T>(response.Content, _settings);
else
throw new ApiRequestException($"Got StatusCode={response.StatusCode} for {response.ResponseUri}.");
}
private T DeserializeXml<T>(string input)

@ -0,0 +1,81 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: AppveyorApi.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using NLog;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Appveyor;
using Ombi.Helpers;
using RestSharp;
namespace Ombi.Api
{
public class AppveyorApi : IAppveyorApi
{
private const string AppveyorApiUrl = "https://ci.appveyor.com/api";
private const string Key =
"48Ku58C0794nBrXra8IxWav+dc6NqgkRw+PZB3/bQwbt/D0IrnJQkgtjzo0bd6nkooLMKsC8M+Ab7jyBO+ROjY14VRuxffpDopX9r0iG/fjBl6mZVvqkm+VTDNstDtzp";
public AppveyorApi()
{
Api = new ApiRequest();
}
private ApiRequest Api { get; set; }
private static Logger Log = LogManager.GetCurrentClassLogger();
//https://ci.appveyor.com/api/projects/tidusjar/requestplex/history?recordsNumber=10&branch=eap
public AppveyorProjects GetProjectHistory(string branchName, int records = 10)
{
var request = new RestRequest
{
Resource = "projects/tidusjar/requestplex/history?recordsNumber={records}&branch={branch}",
Method = Method.GET
};
request.AddUrlSegment("records", records.ToString());
request.AddUrlSegment("branch", branchName);
AddHeaders(request);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetProjectHistory for Appveyor, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (1),
});
var obj = policy.Execute(() => Api.ExecuteJson<AppveyorProjects>(request, new Uri(AppveyorApiUrl)));
return obj;
}
private void AddHeaders(IRestRequest request)
{
request.AddHeader("Authorization", $"Bearer {Key}");
request.AddHeader("Content-Type", "application/json");
}
}
}

@ -100,9 +100,9 @@ namespace Ombi.Api
var obj = RetryHandler.Execute<CouchPotatoStatus>(() => Api.Execute<CouchPotatoStatus>(request, url),
(exception, timespan) => Log.Error(exception, "Exception when calling GetStatus for CP, Retrying {0}", timespan), new TimeSpan[] {
TimeSpan.FromSeconds (2),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)});
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(3)});
return obj;
}
@ -140,9 +140,9 @@ namespace Ombi.Api
{
var obj = RetryHandler.Execute(() => Api.Execute<CouchPotatoMovies>(request, baseUrl),
(exception, timespan) => Log.Error(exception, "Exception when calling GetMovies for CP, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (5),
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(30)
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(5)
});
return obj;

@ -0,0 +1,314 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: EmbyApi.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.Net;
using Newtonsoft.Json;
using NLog;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Emby;
using Ombi.Helpers;
using Polly;
using RestSharp;
namespace Ombi.Api
{
public class EmbyApi : IEmbyApi
{
public EmbyApi()
{
Api = new ApiRequest();
}
private ApiRequest Api { get; }
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Returns all users from the Emby Instance
/// </summary>
/// <param name="baseUri"></param>
/// <param name="apiKey"></param>
public List<EmbyUser> GetUsers(Uri baseUri, string apiKey)
{
var request = new RestRequest
{
Resource = "emby/users",
Method = Method.GET
};
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetUsers for Emby, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (1),
});
var obj = policy.Execute(() => Api.ExecuteJson<List<EmbyUser>>(request, baseUri));
return obj;
}
public EmbySystemInfo GetSystemInformation(string apiKey, Uri baseUrl)
{
var request = new RestRequest
{
Resource = "emby/System/Info",
Method = Method.GET
};
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetSystemInformation for Emby, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(5)
});
var obj = policy.Execute(() => Api.ExecuteJson<EmbySystemInfo>(request, baseUrl));
return obj;
}
public EmbyItemContainer<EmbyLibrary> ViewLibrary(string apiKey, string userId, Uri baseUri)
{
var request = new RestRequest
{
Resource = "emby/users/{userId}/items",
Method = Method.GET
};
request.AddUrlSegment("userId", userId);
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling ViewLibrary for Emby, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(5)
});
var obj = policy.Execute(() => Api.ExecuteJson<EmbyItemContainer<EmbyLibrary>>(request, baseUri));
return obj;
}
public EmbyItemContainer<EmbyMovieItem> GetAllMovies(string apiKey, string userId, Uri baseUri)
{
return GetAll<EmbyMovieItem>("Movie", apiKey, userId, baseUri);
}
public EmbyItemContainer<EmbyEpisodeItem> GetAllEpisodes(string apiKey, string userId, Uri baseUri)
{
return GetAll<EmbyEpisodeItem>("Episode", apiKey, userId, baseUri);
}
public EmbyItemContainer<EmbyMovieInformation> GetCollection(string mediaId, string apiKey, string userId, Uri baseUrl)
{
var request = new RestRequest
{
Resource = "emby/users/{userId}/items?parentId={mediaId}",
Method = Method.GET
};
request.AddUrlSegment("userId", userId);
request.AddUrlSegment("mediaId", mediaId);
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetCollections for Emby, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(5)
});
return policy.Execute(() => Api.ExecuteJson<EmbyItemContainer<EmbyMovieInformation>>(request, baseUrl));
}
public EmbyInformation GetInformation(string mediaId, EmbyMediaType type, string apiKey, string userId, Uri baseUri)
{
var request = new RestRequest
{
Resource = "emby/users/{userId}/items/{mediaId}",
Method = Method.GET
};
request.AddUrlSegment("userId", userId);
request.AddUrlSegment("mediaId", mediaId);
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetAll<T>({1}) for Emby, Retrying {0}", timespan, type), new[] {
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(5)
});
IRestResponse response = null;
try
{
switch (type)
{
case EmbyMediaType.Movie:
response = policy.Execute(() => Api.Execute(request, baseUri));
break;
case EmbyMediaType.Series:
response = policy.Execute(() => Api.Execute(request, baseUri));
break;
case EmbyMediaType.Music:
break;
case EmbyMediaType.Episode:
response = policy.Execute(() => Api.Execute(request, baseUri));
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
var info = new EmbyInformation();
switch (type)
{
case EmbyMediaType.Movie:
return new EmbyInformation
{
MovieInformation = JsonConvert.DeserializeObject<EmbyMovieInformation>(response.Content)
};
case EmbyMediaType.Series:
return new EmbyInformation
{
SeriesInformation = JsonConvert.DeserializeObject<EmbySeriesInformation>(response.Content)
};
case EmbyMediaType.Music:
break;
case EmbyMediaType.Episode:
return new EmbyInformation
{
EpisodeInformation = JsonConvert.DeserializeObject<EmbyEpisodeInformation>(response.Content)
};
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
catch (Exception e)
{
Log.Error("Could not get the media item's information");
Log.Error(e);
Log.Debug("ResponseContent");
Log.Debug(response?.Content ?? "Empty");
Log.Debug("ResponseStatusCode");
Log.Debug(response?.StatusCode ?? HttpStatusCode.PreconditionFailed);
Log.Debug("ResponseError");
Log.Debug(response?.ErrorMessage ?? "No Error");
Log.Debug("ResponseException");
Log.Debug(response?.ErrorException ?? new Exception());
throw;
}
return new EmbyInformation();
}
public EmbyItemContainer<EmbySeriesItem> GetAllShows(string apiKey, string userId, Uri baseUri)
{
return GetAll<EmbySeriesItem>("Series", apiKey, userId, baseUri);
}
public EmbyUser LogIn(string username, string password, string apiKey, Uri baseUri)
{
var request = new RestRequest
{
Resource = "emby/users/authenticatebyname",
Method = Method.POST
};
var body = new
{
username,
password = StringHasher.GetSha1Hash(password).ToLower(),
passwordMd5 = StringHasher.CalcuateMd5Hash(password)
};
request.AddJsonBody(body);
request.AddHeader("X-Emby-Authorization",
$"MediaBrowser Client=\"Ombi\", Device=\"Ombi\", DeviceId=\"{AssemblyHelper.GetProductVersion()}\", Version=\"{AssemblyHelper.GetAssemblyVersion()}\"");
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling LogInfor Emby, Retrying {0}", timespan), new[] {
TimeSpan.FromSeconds (1)
});
var obj = policy.Execute(() => Api.Execute(request, baseUri));
if (obj.StatusCode == HttpStatusCode.Unauthorized)
{
return null;
}
return JsonConvert.DeserializeObject<EmbyUserLogin>(obj.Content)?.User;
}
private EmbyItemContainer<T> GetAll<T>(string type, string apiKey, string userId, Uri baseUri)
{
var request = new RestRequest
{
Resource = "emby/users/{userId}/items",
Method = Method.GET
};
request.AddUrlSegment("userId", userId);
request.AddQueryParameter("Recursive", true.ToString());
request.AddQueryParameter("IncludeItemTypes", type);
AddHeaders(request, apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetAll<T>({1}) for Emby, Retrying {0}", timespan, type), new[] {
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(5)
});
var obj = policy.Execute(() => Api.ExecuteJson<EmbyItemContainer<T>>(request, baseUri));
return obj;
}
private static void AddHeaders(IRestRequest req, string apiKey)
{
if (!string.IsNullOrEmpty(apiKey))
{
req.AddHeader("X-MediaBrowser-Token", apiKey);
}
req.AddHeader("Accept", "application/json");
req.AddHeader("Content-Type", "application/json");
req.AddHeader("Device", "Ombi");
}
}
}

@ -70,10 +70,15 @@
<HintPath>..\packages\TraktApiSharp.0.8.0\lib\portable-net45+netcore45+wpa81\TraktApiSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="WebSocket4Net, Version=0.14.1.0, Culture=neutral, PublicKeyToken=eb4e154b696bf72a, processorArchitecture=MSIL">
<HintPath>..\packages\WebSocket4Net.0.14.1\lib\net45\WebSocket4Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ApiRequest.cs" />
<Compile Include="AppveyorApi.cs" />
<Compile Include="DiscordApi.cs" />
<Compile Include="EmbyApi.cs" />
<Compile Include="NetflixRouletteApi.cs" />
<Compile Include="RadarrApi.cs" />
<Compile Include="TraktApi.cs" />

@ -62,6 +62,20 @@ namespace Ombi.Api
return obj;
}
public List<SonarrRootFolder> GetRootFolders(string apiKey, Uri baseUrl)
{
var request = new RestRequest { Resource = "/api/rootfolder", Method = Method.GET };
request.AddHeader("X-Api-Key", apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetRootFolders for Radarr, Retrying {0}", timespan), new TimeSpan[] {
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(2)
});
var obj = policy.Execute(() => Api.ExecuteJson<List<SonarrRootFolder>>(request, baseUrl));
return obj;
}
public RadarrAddMovie AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, Uri baseUrl, bool searchNow = false)
{
@ -94,7 +108,6 @@ namespace Ombi.Api
request.AddHeader("X-Api-Key", apiKey);
request.AddJsonBody(options);
RadarrAddMovie result;
try
{
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling AddSeries for Sonarr, Retrying {0}", timespan), new TimeSpan[] {
@ -139,7 +152,7 @@ namespace Ombi.Api
}
public List<RadarrMovieResponse> GetMovies(string apiKey, Uri baseUrl)
public RadarrMovieContainer GetMovies(string apiKey, Uri baseUrl)
{
var request = new RestRequest { Resource = "/api/movie", Method = Method.GET };
request.AddHeader("X-Api-Key", apiKey);
@ -152,7 +165,7 @@ namespace Ombi.Api
var obj = policy.Execute(() => Api.Execute(request, baseUrl));
return JsonConvert.DeserializeObject<List<RadarrMovieResponse>>(obj.Content);
return JsonConvert.DeserializeObject<RadarrMovieContainer>(obj.Content);
}
}
}

@ -52,9 +52,9 @@ namespace Ombi.Api
request.AddHeader("X-Api-Key", apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetProfiles for Sonarr, Retrying {0}", timespan), new TimeSpan[] {
TimeSpan.FromSeconds (2),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(5)
});
var obj = policy.Execute(() => Api.ExecuteJson<List<SonarrProfile>>(request, baseUrl));
@ -68,9 +68,9 @@ namespace Ombi.Api
request.AddHeader("X-Api-Key", apiKey);
var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling GetRootFolders for Sonarr, Retrying {0}", timespan), new TimeSpan[] {
TimeSpan.FromSeconds (2),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)
TimeSpan.FromSeconds (1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(5)
});
var obj = policy.Execute(() => Api.ExecuteJson<List<SonarrRootFolder>>(request, baseUrl));

@ -37,6 +37,8 @@ using TMDbLib.Objects.General;
using TMDbLib.Objects.Movies;
using TMDbLib.Objects.Search;
using Movie = TMDbLib.Objects.Movies.Movie;
using TMDbLib.Objects.People;
using System.Linq;
namespace Ombi.Api
{
@ -69,6 +71,11 @@ namespace Ombi.Api
return movies?.Results ?? new List<MovieResult>();
}
private async Task<Movie> GetMovie(int id)
{
return await Client.GetMovie(id);
}
public TmdbMovieDetails GetMovieInformationWithVideos(int tmdbId)
{
var request = new RestRequest { Resource = "movie/{movieId}", Method = Method.GET };
@ -100,5 +107,49 @@ namespace Ombi.Api
var movies = await Client.GetMovie(imdbId);
return movies ?? new Movie();
}
public async Task<List<Movie>> SearchPerson(string searchTerm)
{
return await SearchPerson(searchTerm, null);
}
public async Task<List<Movie>> SearchPerson(string searchTerm, Func<int, string, string, Task<bool>> alreadyAvailable)
{
SearchContainer<SearchPerson> result = await Client.SearchPerson(searchTerm);
var people = result?.Results ?? new List<SearchPerson>();
var person = (people.Count != 0 ? people[0] : null);
var movies = new List<Movie>();
var counter = 0;
try
{
if (person != null)
{
var credits = await Client.GetPersonMovieCredits(person.Id);
// grab results from both cast and crew, prefer items in cast. we can handle directors like this.
List<Movie> movieResults = (from MovieRole role in credits.Cast select new Movie() { Id = role.Id, Title = role.Title, ReleaseDate = role.ReleaseDate }).ToList();
movieResults.AddRange((from MovieJob job in credits.Crew select new Movie() { Id = job.Id, Title = job.Title, ReleaseDate = job.ReleaseDate }).ToList());
//only get the first 10 movies and delay a bit between each request so we don't overload the API
foreach (var m in movieResults)
{
if (counter == 10)
break;
if (alreadyAvailable == null || !(await alreadyAvailable(m.Id, m.Title, m.ReleaseDate.Value.Year.ToString())))
{
movies.Add(await GetMovie(m.Id));
counter++;
}
await Task.Delay(50);
}
}
}
catch (Exception e)
{
Log.Log(LogLevel.Error, e);
}
return movies;
}
}
}

@ -28,6 +28,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using NLog;
using Ombi.Api.Models.Tv;
using RestSharp;
@ -90,21 +91,29 @@ namespace Ombi.Api
};
request.AddUrlSegment("id", theTvDbId.ToString());
request.AddHeader("Content-Type", "application/json");
try
{
var result = Api.Execute(request, new Uri(Uri));
var obj = JsonConvert.DeserializeObject<TvMazeShow>(result.Content);
var obj = Api.Execute<TvMazeShow>(request, new Uri(Uri));
var episodes = EpisodeLookup(obj.id).ToList();
var episodes = EpisodeLookup(obj.id).ToList();
foreach (var e in episodes)
{
obj.Season.Add(new TvMazeCustomSeason
foreach (var e in episodes)
{
SeasonNumber = e.season,
EpisodeNumber = e.number
});
obj.Season.Add(new TvMazeCustomSeason
{
SeasonNumber = e.season,
EpisodeNumber = e.number
});
}
return obj;
}
return obj;
catch (Exception e)
{
Log.Error(e);
return null;
}
}
public List<TvMazeSeasons> GetSeasons(int id)

@ -9,4 +9,5 @@
<package id="System.Net.Http" version="4.0.0" targetFramework="net45" />
<package id="TMDbLib" version="0.9.0.0-alpha" targetFramework="net45" />
<package id="TraktApiSharp" version="0.8.0" targetFramework="net45" />
<package id="WebSocket4Net" version="0.14.1" targetFramework="net45" />
</packages>

@ -0,0 +1,53 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: ContainerBuilder.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.Reflection;
using Ombi.Common.EnvironmentInfo;
namespace Ombi.Common
{
public class ContainerBuilder
{
private readonly List<Type> _loadedTypes;
public ContainerBuilder()
{
_loadedTypes = new List<Type>();
var assemblies = new List<string>();
assemblies.Add(OsInfo.IsWindows ? "Ombi.Windows" : "Ombi.Mono");
assemblies.Add("Ombi.Common");
foreach (var assembly in assemblies)
{
_loadedTypes.AddRange(Assembly.Load(assembly).GetTypes());
}
}
}
}

@ -0,0 +1,88 @@
//#region Copyright
//// /************************************************************************
//// Copyright (c) 2017 Jamie Rees
//// File: DiskTransferService.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.Common.Disk
//{
// public class DiskTransferService
// {
// private readonly IDiskProvider _diskProvider;
// public int MirrorFolder(string sourcePath, string targetPath)
// {
// var filesCopied = 0;
// _logger.Debug("Mirror [{0}] > [{1}]", sourcePath, targetPath);
// if (!_diskProvider.FolderExists(targetPath))
// {
// _diskProvider.CreateFolder(targetPath);
// }
// var sourceFolders = _diskProvider.GetDirectoryInfos(sourcePath);
// var targetFolders = _diskProvider.GetDirectoryInfos(targetPath);
// foreach (var subDir in targetFolders.Where(v => !sourceFolders.Any(d => d.Name == v.Name)))
// {
// if (ShouldIgnore(subDir)) continue;
// _diskProvider.DeleteFolder(subDir.FullName, true);
// }
// foreach (var subDir in sourceFolders)
// {
// if (ShouldIgnore(subDir)) continue;
// filesCopied += MirrorFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name));
// }
// var sourceFiles = _diskProvider.GetFileInfos(sourcePath);
// var targetFiles = _diskProvider.GetFileInfos(targetPath);
// foreach (var targetFile in targetFiles.Where(v => !sourceFiles.Any(d => d.Name == v.Name)))
// {
// if (ShouldIgnore(targetFile)) continue;
// _diskProvider.DeleteFile(targetFile.FullName);
// }
// foreach (var sourceFile in sourceFiles)
// {
// if (ShouldIgnore(sourceFile)) continue;
// var targetFile = Path.Combine(targetPath, sourceFile.Name);
// if (CompareFiles(sourceFile.FullName, targetFile))
// {
// continue;
// }
// TransferFile(sourceFile.FullName, targetFile, TransferMode.Copy, true, true);
// filesCopied++;
// }
// return filesCopied;
// }
// }
//}

@ -0,0 +1,54 @@
using System;
using System.IO;
namespace Ombi.Common.EnvironmentInfo
{
public class OsInfo
{
public static Os Os { get; }
public static bool IsNotWindows => !IsWindows;
public static bool IsLinux => Os == Os.Linux;
public static bool IsOsx => Os == Os.Osx;
public static bool IsWindows => Os == Os.Windows;
static OsInfo()
{
var platform = Environment.OSVersion.Platform;
switch (platform)
{
case PlatformID.Win32NT:
{
Os = Os.Windows;
break;
}
case PlatformID.MacOSX:
case PlatformID.Unix:
{
// Sometimes Mac OS reports itself as Unix
if (Directory.Exists("/System/Library/CoreServices/") &&
(File.Exists("/System/Library/CoreServices/SystemVersion.plist") ||
File.Exists("/System/Library/CoreServices/ServerVersion.plist"))
)
{
Os = Os.Osx;
}
else
{
Os = Os.Linux;
}
break;
}
}
}
}
public enum Os
{
Windows,
Linux,
Osx
}
}

@ -0,0 +1,42 @@
using System;
namespace Ombi.Common.EnvironmentInfo
{
public enum PlatformType
{
DotNet = 0,
Mono = 1
}
public interface IPlatformInfo
{
Version Version { get; }
}
public abstract class PlatformInfo : IPlatformInfo
{
static PlatformInfo()
{
Platform = Type.GetType("Mono.Runtime") != null ? PlatformType.Mono : PlatformType.DotNet;
}
public static PlatformType Platform { get; }
public static bool IsMono => Platform == PlatformType.Mono;
public static bool IsDotNet => Platform == PlatformType.DotNet;
public static string PlatformName
{
get
{
if (IsDotNet)
{
return ".NET";
}
return "Mono";
}
}
public abstract Version Version { get; }
}
}

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BFD45569-90CF-47CA-B575-C7B0FF97F67B}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Ombi.Common</RootNamespace>
<AssemblyName>Ombi.Common</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.3.6\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ContainerBuilder.cs" />
<Compile Include="Disk\DiskTransferService.cs" />
<Compile Include="EnvironmentInfo\OsInfo.cs" />
<Compile Include="EnvironmentInfo\PlatformInfo.cs" />
<Compile Include="Processes\ProcessInfo.cs" />
<Compile Include="Processes\ProcessOutput.cs" />
<Compile Include="Processes\ProcessProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceProvider.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ombi.Common.Processes
{
public class ProcessInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string StartPath { get; set; }
public override string ToString()
{
return string.Format("{0}:{1} [{2}]", Id, Name ?? "Unknown", StartPath ?? "Unknown");
}
}
}

@ -0,0 +1,59 @@

using System;
using System.Collections.Generic;
using System.Linq;
namespace Ombi.Common.Processes
{
public class ProcessOutput
{
public int ExitCode { get; set; }
public List<ProcessOutputLine> Lines { get; set; }
public ProcessOutput()
{
Lines = new List<ProcessOutputLine>();
}
public List<ProcessOutputLine> Standard
{
get
{
return Lines.Where(c => c.Level == ProcessOutputLevel.Standard).ToList();
}
}
public List<ProcessOutputLine> Error
{
get
{
return Lines.Where(c => c.Level == ProcessOutputLevel.Error).ToList();
}
}
}
public class ProcessOutputLine
{
public ProcessOutputLevel Level { get; set; }
public string Content { get; set; }
public DateTime Time { get; set; }
public ProcessOutputLine(ProcessOutputLevel level, string content)
{
Level = level;
Content = content;
Time = DateTime.UtcNow;
}
public override string ToString()
{
return string.Format("{0} - {1} - {2}", Time, Level, Content);
}
}
public enum ProcessOutputLevel
{
Standard = 0,
Error = 1
}
}

@ -0,0 +1,343 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using NLog;
using Ombi.Common.EnvironmentInfo;
namespace Ombi.Common.Processes
{
public interface IProcessProvider
{
int GetCurrentProcessId();
ProcessInfo GetCurrentProcess();
ProcessInfo GetProcessById(int id);
List<ProcessInfo> FindProcessByName(string name);
void OpenDefaultBrowser(string url);
void WaitForExit(System.Diagnostics.Process process);
void SetPriority(int processId, ProcessPriorityClass priority);
void KillAll(string processName);
void Kill(int processId);
bool Exists(int processId);
bool Exists(string processName);
ProcessPriorityClass GetCurrentProcessPriority();
System.Diagnostics.Process Start(string path, string args = null, StringDictionary environmentVariables = null, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null);
System.Diagnostics.Process SpawnNewProcess(string path, string args = null, StringDictionary environmentVariables = null);
ProcessOutput StartAndCapture(string path, string args = null, StringDictionary environmentVariables = null);
}
public class ProcessProvider : IProcessProvider
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public const string OmbiProcessName = "Ombi";
//public ProcessProvider(Logger logger)
//{
// _logger = logger;
//}
public int GetCurrentProcessId()
{
return Process.GetCurrentProcess().Id;
}
public ProcessInfo GetCurrentProcess()
{
return ConvertToProcessInfo(Process.GetCurrentProcess());
}
public bool Exists(int processId)
{
return GetProcessById(processId) != null;
}
public bool Exists(string processName)
{
return GetProcessesByName(processName).Any();
}
public ProcessPriorityClass GetCurrentProcessPriority()
{
return Process.GetCurrentProcess().PriorityClass;
}
public ProcessInfo GetProcessById(int id)
{
_logger.Debug("Finding process with Id:{0}", id);
var processInfo = ConvertToProcessInfo(Process.GetProcesses().FirstOrDefault(p => p.Id == id));
if (processInfo == null)
{
_logger.Warn("Unable to find process with ID {0}", id);
}
else
{
_logger.Debug("Found process {0}", processInfo.ToString());
}
return processInfo;
}
public List<ProcessInfo> FindProcessByName(string name)
{
return GetProcessesByName(name).Select(ConvertToProcessInfo).Where(c => c != null).ToList();
}
public void OpenDefaultBrowser(string url)
{
_logger.Info("Opening URL [{0}]", url);
var process = new Process
{
StartInfo = new ProcessStartInfo(url)
{
UseShellExecute = true
}
};
process.Start();
}
public Process Start(string path, string args = null, StringDictionary environmentVariables = null, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null)
{
if (PlatformInfo.IsMono && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
{
args = GetMonoArgs(path, args);
path = "mono";
}
var logger = LogManager.GetLogger(new FileInfo(path).Name);
var startInfo = new ProcessStartInfo(path, args)
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
RedirectStandardInput = true
};
if (environmentVariables != null)
{
foreach (DictionaryEntry environmentVariable in environmentVariables)
{
startInfo.EnvironmentVariables.Add(environmentVariable.Key.ToString(), environmentVariable.Value.ToString());
}
}
logger.Debug("Starting {0} {1}", path, args);
var process = new Process
{
StartInfo = startInfo
};
process.OutputDataReceived += (sender, eventArgs) =>
{
if (string.IsNullOrWhiteSpace(eventArgs.Data)) return;
logger.Debug(eventArgs.Data);
onOutputDataReceived?.Invoke(eventArgs.Data);
};
process.ErrorDataReceived += (sender, eventArgs) =>
{
if (string.IsNullOrWhiteSpace(eventArgs.Data)) return;
logger.Error(eventArgs.Data);
onErrorDataReceived?.Invoke(eventArgs.Data);
};
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
return process;
}
public Process SpawnNewProcess(string path, string args = null, StringDictionary environmentVariables = null)
{
if (PlatformInfo.IsMono && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
{
args = GetMonoArgs(path, args);
path = "mono";
}
_logger.Debug("Starting {0} {1}", path, args);
var startInfo = new ProcessStartInfo(path, args);
var process = new Process
{
StartInfo = startInfo
};
process.Start();
return process;
}
public ProcessOutput StartAndCapture(string path, string args = null, StringDictionary environmentVariables = null)
{
var output = new ProcessOutput();
var process = Start(path, args, environmentVariables, s => output.Lines.Add(new ProcessOutputLine(ProcessOutputLevel.Standard, s)),
error => output.Lines.Add(new ProcessOutputLine(ProcessOutputLevel.Error, error)));
process.WaitForExit();
output.ExitCode = process.ExitCode;
return output;
}
public void WaitForExit(Process process)
{
_logger.Debug("Waiting for process {0} to exit.", process.ProcessName);
process.WaitForExit();
}
public void SetPriority(int processId, ProcessPriorityClass priority)
{
var process = Process.GetProcessById(processId);
_logger.Info("Updating [{0}] process priority from {1} to {2}",
process.ProcessName,
process.PriorityClass,
priority);
process.PriorityClass = priority;
}
public void Kill(int processId)
{
var process = Process.GetProcesses().FirstOrDefault(p => p.Id == processId);
if (process == null)
{
_logger.Warn("Cannot find process with id: {0}", processId);
return;
}
process.Refresh();
if (process.Id != Process.GetCurrentProcess().Id && process.HasExited)
{
_logger.Debug("Process has already exited");
return;
}
_logger.Info("[{0}]: Killing process", process.Id);
process.Kill();
_logger.Info("[{0}]: Waiting for exit", process.Id);
process.WaitForExit();
_logger.Info("[{0}]: Process terminated successfully", process.Id);
}
public void KillAll(string processName)
{
var processes = GetProcessesByName(processName);
_logger.Debug("Found {0} processes to kill", processes.Count);
foreach (var processInfo in processes)
{
if (processInfo.Id == Process.GetCurrentProcess().Id)
{
_logger.Debug("Tried killing own process, skipping: {0} [{1}]", processInfo.Id, processInfo.ProcessName);
continue;
}
_logger.Debug("Killing process: {0} [{1}]", processInfo.Id, processInfo.ProcessName);
Kill(processInfo.Id);
}
}
private ProcessInfo ConvertToProcessInfo(Process process)
{
if (process == null) return null;
process.Refresh();
ProcessInfo processInfo = null;
try
{
if (process.Id <= 0) return null;
processInfo = new ProcessInfo
{
Id = process.Id,
Name = process.ProcessName,
StartPath = GetExeFileName(process)
};
if (process.Id != Process.GetCurrentProcess().Id && process.HasExited)
{
processInfo = null;
}
}
catch (Win32Exception e)
{
_logger.Warn(e, "Couldn't get process info for " + process.ProcessName);
}
return processInfo;
}
private static string GetExeFileName(Process process)
{
if (process.MainModule.FileName != "mono.exe")
{
return process.MainModule.FileName;
}
return process.Modules.Cast<ProcessModule>().FirstOrDefault(module => module.ModuleName.ToLower().EndsWith(".exe")).FileName;
}
private List<System.Diagnostics.Process> GetProcessesByName(string name)
{
//TODO: move this to an OS specific class
var monoProcesses = Process.GetProcessesByName("mono")
.Union(Process.GetProcessesByName("mono-sgen"))
.Where(process =>
process.Modules.Cast<ProcessModule>()
.Any(module =>
module.ModuleName.ToLower() == name.ToLower() + ".exe"));
var processes = Process.GetProcessesByName(name)
.Union(monoProcesses).ToList();
_logger.Debug("Found {0} processes with the name: {1}", processes.Count, name);
try
{
foreach (var process in processes)
{
_logger.Debug(" - [{0}] {1}", process.Id, process.ProcessName);
}
}
catch
{
// Don't crash on gettings some log data.
}
return processes;
}
private string GetMonoArgs(string path, string args)
{
return string.Format("--debug {0} {1}", path, args);
}
}
}

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Ombi.Common")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Ombi.Common")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bfd45569-90cf-47ca-b575-c7b0ff97f67b")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -0,0 +1,203 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: ServiceProvider.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.Specialized;
using System.Configuration.Install;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using NLog;
using Ombi.Common.Processes;
namespace Ombi.Common
{
public interface IServiceProvider
{
bool ServiceExist(string name);
bool IsServiceRunning(string name);
void Install(string serviceName);
void Run(ServiceBase service);
ServiceController GetService(string serviceName);
void Stop(string serviceName);
void Start(string serviceName);
ServiceControllerStatus GetStatus(string serviceName);
void Restart(string serviceName);
}
public class ServiceProvider : IServiceProvider
{
public const string OmbiServiceName = "Ombi";
private readonly IProcessProvider _processProvider;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public ServiceProvider(IProcessProvider processProvider)
{
_processProvider = processProvider;
}
public virtual bool ServiceExist(string name)
{
_logger.Debug("Checking if service {0} exists.", name);
return
ServiceController.GetServices().Any(
s => string.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
}
public virtual bool IsServiceRunning(string name)
{
_logger.Debug("Checking if '{0}' service is running", name);
var service = ServiceController.GetServices()
.SingleOrDefault(s => string.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
return service != null && (
service.Status != ServiceControllerStatus.Stopped ||
service.Status == ServiceControllerStatus.StopPending ||
service.Status == ServiceControllerStatus.Paused ||
service.Status == ServiceControllerStatus.PausePending);
}
public virtual void Install(string serviceName)
{
_logger.Info("Installing service '{0}'", serviceName);
var installer = new ServiceProcessInstaller
{
Account = ServiceAccount.LocalSystem
};
var serviceInstaller = new ServiceInstaller();
string[] cmdline = { @"/assemblypath=" + Process.GetCurrentProcess().MainModule.FileName };
var context = new InstallContext("service_install.log", cmdline);
serviceInstaller.Context = context;
serviceInstaller.DisplayName = serviceName;
serviceInstaller.ServiceName = serviceName;
serviceInstaller.Description = "Ombi Application Server";
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.ServicesDependedOn = new[] { "EventLog", "Tcpip", "http" };
serviceInstaller.Parent = installer;
serviceInstaller.Install(new ListDictionary());
_logger.Info("Service Has installed successfully.");
}
public virtual void Run(ServiceBase service)
{
ServiceBase.Run(service);
}
public virtual ServiceController GetService(string serviceName)
{
return ServiceController.GetServices().FirstOrDefault(c => string.Equals(c.ServiceName, serviceName, StringComparison.InvariantCultureIgnoreCase));
}
public virtual void Stop(string serviceName)
{
_logger.Info("Stopping {0} Service...", serviceName);
var service = GetService(serviceName);
if (service == null)
{
_logger.Warn("Unable to stop {0}. no service with that name exists.", serviceName);
return;
}
_logger.Info("Service is currently {0}", service.Status);
if (service.Status != ServiceControllerStatus.Stopped)
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60));
service.Refresh();
if (service.Status == ServiceControllerStatus.Stopped)
{
_logger.Info("{0} has stopped successfully.", serviceName);
}
else
{
_logger.Error("Service stop request has timed out. {0}", service.Status);
}
}
else
{
_logger.Warn("Service {0} is already in stopped state.", service.ServiceName);
}
}
public ServiceControllerStatus GetStatus(string serviceName)
{
return GetService(serviceName).Status;
}
public void Start(string serviceName)
{
_logger.Info("Starting {0} Service...", serviceName);
var service = GetService(serviceName);
if (service == null)
{
_logger.Warn("Unable to start '{0}' no service with that name exists.", serviceName);
return;
}
if (service.Status != ServiceControllerStatus.Paused && service.Status != ServiceControllerStatus.Stopped)
{
_logger.Warn("Service is in a state that can't be started. Current status: {0}", service.Status);
}
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(60));
service.Refresh();
if (service.Status == ServiceControllerStatus.Running)
{
_logger.Info("{0} has started successfully.", serviceName);
}
else
{
_logger.Error("Service start request has timed out. {0}", service.Status);
}
}
public void Restart(string serviceName)
{
var args = string.Format("/C net.exe stop \"{0}\" && net.exe start \"{0}\"", serviceName);
_processProvider.Start("cmd.exe", args);
}
}
}

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="4.3.6" targetFramework="net452" />
</packages>

@ -37,6 +37,7 @@ using Ombi.Helpers;
using Ombi.Helpers.Permissions;
using Ombi.Store;
using Ombi.Store.Models;
using Ombi.Store.Models.Plex;
using Ombi.Store.Repository;
namespace Ombi.Core.Migration.Migrations
@ -46,7 +47,7 @@ namespace Ombi.Core.Migration.Migrations
{
public Version1100(IUserRepository userRepo, IRequestService requestService, ISettingsService<LogSettings> log,
IPlexApi plexApi, ISettingsService<PlexSettings> plexService,
IPlexUserRepository plexusers, ISettingsService<PlexRequestSettings> prSettings,
IExternalUserRepository<PlexUsers> plexusers, ISettingsService<PlexRequestSettings> prSettings,
ISettingsService<UserManagementSettings> umSettings,
ISettingsService<ScheduledJobsSettings> sjs, IRepository<UsersToNotify> usersToNotify)
{
@ -69,7 +70,7 @@ namespace Ombi.Core.Migration.Migrations
private ISettingsService<LogSettings> Log { get; }
private IPlexApi PlexApi { get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
private IPlexUserRepository PlexUsers { get; }
private IExternalUserRepository<PlexUsers> PlexUsers { get; }
private ISettingsService<PlexRequestSettings> PlexRequestSettings { get; }
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
private ISettingsService<ScheduledJobsSettings> ScheduledJobSettings { get; }
@ -180,7 +181,7 @@ namespace Ombi.Core.Migration.Migrations
try
{
var settings = PlexSettings.GetSettings();
if (string.IsNullOrEmpty(settings.PlexAuthToken))
if (string.IsNullOrEmpty(settings.PlexAuthToken) || !settings.Enable)
{
return;
}

@ -62,6 +62,7 @@ namespace Ombi.Core.Migration.Migrations
private void UpdateApplicationSettings()
{
var plex = PlexRequestSettings.GetSettings();
var jobSettings = Jobs.GetSettings();
var newsLetter = NewsletterSettings.GetSettings();

@ -27,38 +27,107 @@
#endregion
using System;
using System.Data;
using NLog;
using Ombi.Core.SettingModels;
using Ombi.Store;
using Ombi.Store.Models;
using Ombi.Store.Models.Plex;
using Ombi.Store.Repository;
using Quartz.Collection;
namespace Ombi.Core.Migration.Migrations
{
[Migration(22000, "v2.20.0.0")]
public class Version2200 : BaseMigration, IMigration
{
public Version2200(ISettingsService<CustomizationSettings> custom)
public Version2200(ISettingsService<CustomizationSettings> custom, ISettingsService<PlexSettings> ps, IRepository<RecentlyAddedLog> log,
IRepository<PlexContent> content, IRepository<PlexEpisodes> plexEp)
{
Customization = custom;
PlexSettings = ps;
Log = log;
PlexContent = content;
PlexEpisodes = plexEp;
}
public int Version => 22000;
private ISettingsService<CustomizationSettings> Customization { get; set; }
private ISettingsService<CustomizationSettings> Customization { get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
private IRepository<RecentlyAddedLog> Log { get; }
private IRepository<PlexContent> PlexContent { get; }
private IRepository<PlexEpisodes> PlexEpisodes { get; }
private static Logger Logger = LogManager.GetCurrentClassLogger();
public void Start(IDbConnection con)
{
//UpdateCustomSettings(); Turned off the migration for now until the search has been improved on.
//UpdateSchema(con, Version);
UpdatePlexSettings();
UpdateCustomSettings();
AddNewColumns(con);
UpdateSchema(con, Version);
UpdateRecentlyAdded(con);
}
private void UpdateRecentlyAdded(IDbConnection con)
{
var allContent = PlexContent.GetAll();
var content = new HashSet<RecentlyAddedLog>();
foreach (var plexContent in allContent)
{
content.Add(new RecentlyAddedLog
{
AddedAt = DateTime.UtcNow,
ProviderId = plexContent.ProviderId
});
}
Log.BatchInsert(content, "RecentlyAddedLog");
var allEp = PlexEpisodes.GetAll();
content.Clear();
foreach (var ep in allEp)
{
content.Add(new RecentlyAddedLog
{
AddedAt = DateTime.UtcNow,
ProviderId = ep.ProviderId
});
}
Log.BatchInsert(content, "RecentlyAddedLog");
}
private void AddNewColumns(IDbConnection con)
{
con.AlterTable("EmbyContent", "ADD", "AddedAt", true, "VARCHAR(50)");
con.AlterTable("EmbyEpisodes", "ADD", "AddedAt", true, "VARCHAR(50)");
con.AlterTable("PlexContent", "ADD", "ItemId", true, "VARCHAR(100)");
con.AlterTable("PlexContent", "ADD", "AddedAt", true, "VARCHAR(100)");
}
private void UpdatePlexSettings()
{
#if !DEBUG
var s = PlexSettings.GetSettings();
if (!string.IsNullOrEmpty(s.Ip))
{
s.Enable = true;
PlexSettings.SaveSettings(s);
}
#endif
}
private void UpdateCustomSettings()
{
var settings = Customization.GetSettings();
settings.NewSearch = true; // Use the new search
settings.EnableIssues = true;
Customization.SaveSettings(settings);
}
}
}

@ -0,0 +1,169 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieSenderTests.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Moq;
using NUnit.Framework;
using Ombi.Api;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Radarr;
using Ombi.Api.Models.Sonarr;
using Ombi.Api.Models.Watcher;
using Ombi.Core.SettingModels;
using Ombi.Helpers;
using Ombi.Store;
using Ploeh.AutoFixture;
namespace Ombi.Core.Tests
{
public class MovieSenderTests
{
private MovieSender Sender { get; set; }
private Mock<ISettingsService<CouchPotatoSettings>> CpMock { get; set; }
private Mock<ISettingsService<WatcherSettings>> WatcherMock { get; set; }
private Mock<ISettingsService<RadarrSettings>> RadarrMock { get; set; }
private Mock<ICouchPotatoApi> CpApiMock { get; set; }
private Mock<IWatcherApi> WatcherApiMock { get; set; }
private Mock<IRadarrApi> RadarrApiMock { get; set; }
private Mock<ICacheProvider> CacheMock { get; set; }
private Fixture F { get; set; }
[SetUp]
public void Setup()
{
F = new Fixture();
CpMock = new Mock<ISettingsService<CouchPotatoSettings>>();
WatcherMock = new Mock<ISettingsService<WatcherSettings>>();
RadarrApiMock = new Mock<IRadarrApi>();
RadarrMock = new Mock<ISettingsService<RadarrSettings>>();
CpApiMock = new Mock<ICouchPotatoApi>();
WatcherApiMock = new Mock<IWatcherApi>();
CacheMock = new Mock<ICacheProvider>();
RadarrMock.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(F.Build<RadarrSettings>().With(x => x.Enabled, false).Create());
WatcherMock.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(F.Build<WatcherSettings>().With(x => x.Enabled, false).Create());
CpMock.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(F.Build<CouchPotatoSettings>().With(x => x.Enabled, false).Create());
Sender = new MovieSender(CpMock.Object, WatcherMock.Object, CpApiMock.Object, WatcherApiMock.Object, RadarrApiMock.Object, RadarrMock.Object, CacheMock.Object);
}
[Test]
public async Task SendRadarrMovie()
{
RadarrMock.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(F.Build<RadarrSettings>().With(x => x.Enabled, true).Create());
RadarrApiMock.Setup(x => x.AddMovie(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<Uri>(), It.IsAny<bool>())).Returns(new RadarrAddMovie { title = "Abc" });
CacheMock.Setup(x => x.GetOrSet<List<SonarrRootFolder>>(CacheKeys.RadarrRootFolders, It.IsAny<Func<List<SonarrRootFolder>>>(), It.IsAny<int>()))
.Returns(F.CreateMany<SonarrRootFolder>().ToList());
var model = F.Create<RequestedModel>();
var result = await Sender.Send(model, 2.ToString());
Assert.That(result.Result, Is.True);
Assert.That(result.Error, Is.False);
Assert.That(result.MovieSendingEnabled, Is.True);
RadarrApiMock.Verify(x => x.AddMovie(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<int>(), 2, It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<Uri>(), It.IsAny<bool>()), Times.Once);
}
[Test]
public async Task SendRadarrMovie_SendingFailed()
{
RadarrMock.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(F.Build<RadarrSettings>().With(x => x.Enabled, true).Create());
RadarrApiMock.Setup(x => x.AddMovie(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<Uri>(), It.IsAny<bool>())).Returns(new RadarrAddMovie { Error = new RadarrError{message = "Movie Already Added"}});
CacheMock.Setup(x => x.GetOrSet<List<SonarrRootFolder>>(CacheKeys.RadarrRootFolders, It.IsAny<Func<List<SonarrRootFolder>>>(), It.IsAny<int>()))
.Returns(F.CreateMany<SonarrRootFolder>().ToList());
var model = F.Create<RequestedModel>();
var result = await Sender.Send(model, 2.ToString());
Assert.That(result.Result, Is.False);
Assert.That(result.Error, Is.True);
Assert.That(result.MovieSendingEnabled, Is.True);
RadarrApiMock.Verify(x => x.AddMovie(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<int>(), 2, It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<Uri>(), It.IsAny<bool>()), Times.Once);
}
[Test]
public async Task SendCpMovie()
{
CpMock.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(F.Build<CouchPotatoSettings>().With(x => x.Enabled, true).Create());
CpApiMock.Setup(x => x.AddMovie(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<Uri>(), It.IsAny<string>())).Returns(true);
var model = F.Create<RequestedModel>();
var result = await Sender.Send(model);
Assert.That(result.Result, Is.True);
Assert.That(result.Error, Is.False);
Assert.That(result.MovieSendingEnabled, Is.True);
CpApiMock.Verify(x => x.AddMovie(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<Uri>(), It.IsAny<string>()), Times.Once);
}
[Test]
public async Task SendWatcherMovie()
{
WatcherMock.Setup(x => x.GetSettingsAsync())
.ReturnsAsync(F.Build<WatcherSettings>().With(x => x.Enabled, true).Create());
WatcherApiMock.Setup(x => x.AddMovie(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns(F.Create<WatcherAddMovieResult>());
var model = F.Create<RequestedModel>();
var result = await Sender.Send(model);
Assert.That(result.Result, Is.True);
Assert.That(result.Error, Is.False);
Assert.That(result.MovieSendingEnabled, Is.True);
WatcherApiMock.Verify(x => x.AddMovie(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>()), Times.Once);
}
}
}

@ -60,6 +60,7 @@
</Choose>
<ItemGroup>
<Compile Include="AuthenticationSettingsTests.cs" />
<Compile Include="MovieSenderTests.cs" />
<Compile Include="NotificationMessageResolverTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@ -68,6 +69,18 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.Interfaces\Ombi.Api.Interfaces.csproj">
<Project>{95834072-A675-415D-AA8F-877C91623810}</Project>
<Name>Ombi.Api.Interfaces</Name>
</ProjectReference>
<ProjectReference Include="..\Ombi.Api.Models\Ombi.Api.Models.csproj">
<Project>{CB37A5F8-6DFC-4554-99D3-A42B502E4591}</Project>
<Name>Ombi.Api.Models</Name>
</ProjectReference>
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj">
<Project>{8CB8D235-2674-442D-9C6A-35FCAEEB160D}</Project>
<Name>Ombi.Api</Name>
</ProjectReference>
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj">
<Project>{DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}</Project>
<Name>Ombi.Core</Name>
@ -76,6 +89,10 @@
<Project>{1252336D-42A3-482A-804C-836E60173DFA}</Project>
<Name>Ombi.Helpers</Name>
</ProjectReference>
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj">
<Project>{92433867-2B7B-477B-A566-96C382427525}</Project>
<Name>Ombi.Store</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">

@ -45,8 +45,11 @@ namespace Ombi.Core
public const string CouchPotatoQualityProfiles = nameof(CouchPotatoQualityProfiles);
public const string CouchPotatoQueued = nameof(CouchPotatoQueued);
public const string WatcherQueued = nameof(WatcherQueued);
public const string GetCustomizationSettings = nameof(GetCustomizationSettings);
public const string GetEmbySettings = nameof(GetEmbySettings);
public const string GetPlexRequestSettings = nameof(GetPlexRequestSettings);
public const string LastestProductVersion = nameof(LastestProductVersion);
public const string SonarrRootFolders = nameof(SonarrRootFolders);
public const string RadarrRootFolders = nameof(RadarrRootFolders);
}
}

@ -62,7 +62,7 @@ namespace Ombi.Core
// Artist is now active
// Add album
var albumResult = await Api.AddAlbum(Settings.ApiKey, Settings.FullUri, request.MusicBrainzId);
var albumResult = await Api.AddAlbum(Settings.ApiKey, Settings.FullUri, request.ReleaseId);
if (!albumResult)
{
Log.Error("Couldn't add the album to headphones");
@ -79,7 +79,7 @@ namespace Ombi.Core
request.Approved = true;
// Update the record
var updated = RequestService.UpdateRequest(request);
bool updated = RequestService.UpdateRequest(request);
return updated;
}
@ -88,87 +88,20 @@ namespace Ombi.Core
{
var index = await Api.GetIndex(Settings.ApiKey, Settings.FullUri);
var artistExists = index.Any(x => x.ArtistID == request.ArtistId);
bool artistAdd = false;
if (!artistExists)
{
var artistAdd = Api.AddArtist(Settings.ApiKey, Settings.FullUri, request.ArtistId);
Log.Info("Artist add result : {0}", artistAdd);
artistAdd = await Api.AddArtist(Settings.ApiKey, Settings.FullUri, request.ArtistId);
Log.Info("Artist add result for {1}: {0}", artistAdd, request.ArtistName);
}
var counter = 0;
while (index.All(x => x.ArtistID != request.ArtistId))
{
Thread.Sleep(WaitTime);
counter++;
Log.Trace("Artist is still not present in the index. Counter = {0}", counter);
index = await Api.GetIndex(Settings.ApiKey, Settings.FullUri);
if (counter > CounterMax)
{
Log.Trace("Artist is still not present in the index. Counter = {0}. Returning false", counter);
Log.Warn("We have tried adding the artist but it seems they are still not in headphones.");
return false;
}
}
counter = 0;
var artistStatus = index.Where(x => x.ArtistID == request.ArtistId).Select(x => x.Status).FirstOrDefault();
while (artistStatus != "Active")
{
Thread.Sleep(WaitTime);
counter++;
Log.Trace("Artist status {1}. Counter = {0}", counter, artistStatus);
index = await Api.GetIndex(Settings.ApiKey, Settings.FullUri);
artistStatus = index.Where(x => x.ArtistID == request.ArtistId).Select(x => x.Status).FirstOrDefault();
if (counter > CounterMax)
{
Log.Trace("Artist status is still not active. Counter = {0}. Returning false", counter);
Log.Warn("The artist status is still not Active. We have waited long enough, seems to be a big delay in headphones.");
return false;
}
}
var addedArtist = index.FirstOrDefault(x => x.ArtistID == request.ArtistId);
var artistName = addedArtist?.ArtistName ?? string.Empty;
counter = 0;
while (artistName.Contains("Fetch failed"))
{
Thread.Sleep(WaitTime);
await Api.RefreshArtist(Settings.ApiKey, Settings.FullUri, request.ArtistId);
index = await Api.GetIndex(Settings.ApiKey, Settings.FullUri);
artistName = index?.FirstOrDefault(x => x.ArtistID == request.ArtistId)?.ArtistName ?? string.Empty;
counter++;
if (counter > CounterMax)
{
Log.Trace("Artist fetch has failed. Counter = {0}. Returning false", counter);
Log.Warn("Artist in headphones fetch has failed, we have tried refreshing the artist but no luck.");
return false;
}
}
return true;
return artistExists || artistAdd;
}
private async Task<bool> SetAlbumStatus(RequestedModel request)
{
var counter = 0;
var setStatus = await Api.QueueAlbum(Settings.ApiKey, Settings.FullUri, request.MusicBrainzId);
while (!setStatus)
{
Thread.Sleep(WaitTime);
counter++;
Log.Trace("Setting Album status. Counter = {0}", counter);
setStatus = await Api.QueueAlbum(Settings.ApiKey, Settings.FullUri, request.MusicBrainzId);
if (counter > CounterMax)
{
Log.Trace("Album status is still not active. Counter = {0}. Returning false", counter);
Log.Warn("We tried to se the status for the album but headphones didn't want to snatch it.");
return false;
}
}
return true;
bool setStatus = await Api.QueueAlbum(Settings.ApiKey, Settings.FullUri, request.ReleaseId);
return setStatus;
}
}
}

@ -22,7 +22,7 @@ namespace Ombi.Core
Func<NancyContext, Response> HttpStatusCodeIfNot(HttpStatusCode statusCode, Func<NancyContext, bool> test);
bool IsLoggedIn(NancyContext context);
bool IsNormalUser(IUserIdentity user);
bool IsPlexUser(IUserIdentity user);
bool IsExternalUser(IUserIdentity user);
bool HasPermissions(string userName, Permissions perm);
/// <summary>

@ -0,0 +1,43 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: RecentUpdatesModel.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.Core.Models
{
public class RecentUpdatesModel
{
public string Version { get; set; }
public string Message { get; set; }
public bool Installed { get; set; }
public DateTime Date { get; set; }
public string Branch { get; set; }
}
}

@ -26,10 +26,12 @@
#endregion
using System;
using System.Linq;
using System.Threading.Tasks;
using NLog;
using Ombi.Api.Interfaces;
using Ombi.Core.SettingModels;
using Ombi.Helpers;
using Ombi.Store;
namespace Ombi.Core
@ -37,7 +39,8 @@ namespace Ombi.Core
public class MovieSender : IMovieSender
{
public MovieSender(ISettingsService<CouchPotatoSettings> cp, ISettingsService<WatcherSettings> watcher,
ICouchPotatoApi cpApi, IWatcherApi watcherApi, IRadarrApi radarrApi, ISettingsService<RadarrSettings> radarrSettings)
ICouchPotatoApi cpApi, IWatcherApi watcherApi, IRadarrApi radarrApi, ISettingsService<RadarrSettings> radarrSettings,
ICacheProvider cache)
{
CouchPotatoSettings = cp;
WatcherSettings = watcher;
@ -45,6 +48,7 @@ namespace Ombi.Core
WatcherApi = watcherApi;
RadarrSettings = radarrSettings;
RadarrApi = radarrApi;
Cache = cache;
}
private ISettingsService<CouchPotatoSettings> CouchPotatoSettings { get; }
@ -53,6 +57,7 @@ namespace Ombi.Core
private IRadarrApi RadarrApi { get; }
private ICouchPotatoApi CpApi { get; }
private IWatcherApi WatcherApi { get; }
private ICacheProvider Cache { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
public async Task<MovieSenderResult> Send(RequestedModel model, string qualityId = "")
@ -73,7 +78,7 @@ namespace Ombi.Core
if (radarrSettings.Enabled)
{
return SendToRadarr(model, radarrSettings);
return SendToRadarr(model, radarrSettings, qualityId);
}
return new MovieSenderResult { Result = false, MovieSendingEnabled = false };
@ -102,16 +107,26 @@ namespace Ombi.Core
return new MovieSenderResult { Result = result, MovieSendingEnabled = true };
}
private MovieSenderResult SendToRadarr(RequestedModel model, RadarrSettings settings)
private MovieSenderResult SendToRadarr(RequestedModel model, RadarrSettings settings, string qualityId)
{
var qualityProfile = 0;
int.TryParse(settings.QualityProfile, out qualityProfile);
var result = RadarrApi.AddMovie(model.ProviderId, model.Title, model.ReleaseDate.Year, qualityProfile, settings.RootPath, settings.ApiKey, settings.FullUri, true);
if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality
{
int.TryParse(qualityId, out qualityProfile);
}
if (qualityProfile <= 0)
{
int.TryParse(settings.QualityProfile, out qualityProfile);
}
var rootFolderPath = model.RootFolderSelected <= 0 ? settings.FullRootPath : GetRootPath(model.RootFolderSelected, settings);
var result = RadarrApi.AddMovie(model.ProviderId, model.Title, model.ReleaseDate.Year, qualityProfile, rootFolderPath, settings.ApiKey, settings.FullUri, true);
if (!string.IsNullOrEmpty(result.Error?.message))
{
Log.Error(result.Error.message);
return new MovieSenderResult { Result = false, Error = true};
return new MovieSenderResult { Result = false, Error = true , MovieSendingEnabled = true};
}
if (!string.IsNullOrEmpty(result.title))
{
@ -119,5 +134,16 @@ namespace Ombi.Core
}
return new MovieSenderResult { Result = false, MovieSendingEnabled = true };
}
private string GetRootPath(int pathId, RadarrSettings sonarrSettings)
{
var rootFoldersResult = Cache.GetOrSet(CacheKeys.RadarrRootFolders, () => RadarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri));
foreach (var r in rootFoldersResult.Where(r => r.id == pathId))
{
return r.path;
}
return string.Empty;
}
}
}

@ -144,7 +144,7 @@
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td align="center">
<img src="http://i.imgur.com/ROTp8mn.png" text-align="center" />
<img src="http://i.imgur.com/qQsN78U.png" width="400px" text-align="center" />
</td>
</tr>
<tr>

@ -99,6 +99,7 @@
<Compile Include="IPlexReadOnlyDatabase.cs" />
<Compile Include="ISecurityExtensions.cs" />
<Compile Include="IStatusChecker.cs" />
<Compile Include="Models\RecentUpdatesModel.cs" />
<Compile Include="MovieSender.cs" />
<Compile Include="MovieSenderResult.cs" />
<Compile Include="Notification\NotificationMessage.cs" />
@ -123,6 +124,8 @@
<Compile Include="SecurityExtensions.cs" />
<Compile Include="SettingModels\AuthenticationSettings.cs" />
<Compile Include="SettingModels\DiscordNotificationSettings.cs" />
<Compile Include="SettingModels\EmbySettings.cs" />
<Compile Include="SettingModels\MassEmailSettings.cs" />
<Compile Include="SettingModels\RadarrSettings.cs" />
<Compile Include="SettingModels\WatcherSettings.cs" />
<Compile Include="SettingModels\ExternalSettings.cs" />

@ -105,7 +105,7 @@ namespace Ombi.Core.Queue
public IEnumerable<RequestQueue> GetQueue()
{
var items = RequestQueue.GetAll();
return items;
}

@ -36,23 +36,28 @@ using Ombi.Core.SettingModels;
using Ombi.Core.Users;
using Ombi.Helpers;
using Ombi.Helpers.Permissions;
using Ombi.Store.Models.Emby;
using Ombi.Store.Models.Plex;
using Ombi.Store.Repository;
namespace Ombi.Core
{
public class SecurityExtensions : ISecurityExtensions
{
public SecurityExtensions(IUserRepository userRepository, IResourceLinker linker, IPlexUserRepository plexUsers, ISettingsService<UserManagementSettings> umSettings)
public SecurityExtensions(IUserRepository userRepository, IResourceLinker linker, IExternalUserRepository<PlexUsers> plexUsers, ISettingsService<UserManagementSettings> umSettings,
IExternalUserRepository<EmbyUsers> embyUsers)
{
UserRepository = userRepository;
Linker = linker;
PlexUsers = plexUsers;
UserManagementSettings = umSettings;
EmbyUsers = embyUsers;
}
private IUserRepository UserRepository { get; }
private IResourceLinker Linker { get; }
private IPlexUserRepository PlexUsers { get; }
private IExternalUserRepository<PlexUsers> PlexUsers { get; }
private IExternalUserRepository<EmbyUsers> EmbyUsers { get; }
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
public bool IsLoggedIn(NancyContext context)
@ -69,16 +74,18 @@ namespace Ombi.Core
return realUser || plexUser;
}
public bool IsPlexUser(IUserIdentity user)
public bool IsExternalUser(IUserIdentity user)
{
if (user == null)
{
return false;
}
var plexUser = PlexUsers.GetUserByUsername(user.UserName);
return plexUser != null;
}
var embyUser = EmbyUsers.GetUserByUsername(user.UserName);
return plexUser != null || embyUser != null;
}
public bool IsNormalUser(IUserIdentity user)
{
if (user == null)
@ -106,6 +113,12 @@ namespace Ombi.Core
return !string.IsNullOrEmpty(plexUser.UserAlias) ? plexUser.UserAlias : plexUser.Username;
}
var embyUser = EmbyUsers.GetUserByUsername(username);
if (embyUser != null)
{
return !string.IsNullOrEmpty(embyUser.UserAlias) ? embyUser.UserAlias : embyUser.Username;
}
var dbUser = UserRepository.GetUserByUsername(username);
if (dbUser != null)
{
@ -302,6 +315,12 @@ namespace Ombi.Core
return permissions;
}
var embyUsers = EmbyUsers.GetUserByUsername(userName);
if (embyUsers != null)
{
return (Permissions) embyUsers.Permissions;
}
return 0;
}
}

@ -54,6 +54,7 @@ namespace Ombi.Core.SettingModels
public int DefaultLang { get; set; }
public bool NewSearch { get; set; }
public bool EnableIssues { get; set; }
}
}

@ -0,0 +1,37 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: CouchPotatoSettings.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.SettingModels
{
public sealed class EmbySettings : ExternalSettings
{
public bool Enable { get; set; }
public string ApiKey { get; set; }
public string AdministratorId { get; set; }
public bool EnableEpisodeSearching { get; set; }
}
}

@ -0,0 +1,35 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: EmailNotificationSettings.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.SettingModels
{
public sealed class MassEmailSettings : NotificationSettings
{
public string Users { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
}

@ -41,6 +41,7 @@ namespace Ombi.Core.SettingModels
public int Port { get; set; }
public string BaseUrl { get; set; }
public bool SearchForMovies { get; set; }
public bool SearchForActors { get; set; }
public bool SearchForTvShows { get; set; }
public bool SearchForMusic { get; set; }
[Obsolete("Use the user management settings")]

@ -33,6 +33,8 @@ namespace Ombi.Core.SettingModels
{
AdvancedSearch = true;
}
public bool Enable { get; set; }
public bool AdvancedSearch { get; set; }
public bool EnableTvEpisodeSearching { get; set; }

@ -32,6 +32,6 @@ namespace Ombi.Core.SettingModels
public string ApiKey { get; set; }
public string QualityProfile { get; set; }
public string RootPath { get; set; }
public string FullRootPath { get; set; }
}
}

@ -47,5 +47,10 @@ namespace Ombi.Core.SettingModels
public int PlexContentCacher { get; set; }
public int PlexUserChecker { get; set; }
public int RadarrCacher { get; set; }
public int EmbyEpisodeCacher { get; set; }
public int EmbyContentCacher { get; set; }
public int EmbyAvailabilityChecker { get; set; }
public int EmbyUserChecker { get; set; }
}
}

@ -37,7 +37,7 @@ namespace Ombi.Core.SettingModels
public Dictionary<string, string> Qualities => new Dictionary<string, string>
{
{ "default", "Use Deafult" },
{ "default", "Use Default" },
{ "sdtv", "SD TV" },
{ "sddvd", "SD DVD" },
{ "hdtv", "HD TV" },

@ -25,10 +25,12 @@
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using Ombi.Core.Models;
using Ombi.Helpers;
namespace Ombi.Core.SettingModels
{
@ -50,13 +52,15 @@ namespace Ombi.Core.SettingModels
public enum Branches
{
[Display(Name = "Stable")]
[Branch(DisplayName= "Stable", BranchName = "master")]
Stable,
[Display(Name = "Early Access Preview")]
[Branch(DisplayName = "Early Access Preview", BranchName = "eap")]
EarlyAccessPreview,
[Display(Name = "Development")]
[Branch(DisplayName = "Development", BranchName = "dev")]
Dev,
}
}

@ -38,6 +38,7 @@ namespace Ombi.Core.SettingModels
public bool UsersCanViewOnlyOwnRequests { get; set; }
public bool UsersCanViewOnlyOwnIssues { get; set; }
public bool BypassRequestLimit { get; set; }
public bool ViewUsers { get; set; }
// Features
public bool RecentlyAddedNotification { get; set; }

@ -46,7 +46,7 @@ namespace Ombi.Core
{
Db = new DbConfiguration(new SqliteFactory());
var created = Db.CheckDb();
TableCreation.CreateTables(Db.DbConnection());
Db.DbConnection().CreateTables();
if (created)
{
@ -55,7 +55,7 @@ namespace Ombi.Core
else
{
// Shrink DB
TableCreation.Vacuum(Db.DbConnection());
Db.DbConnection().Vacuum();
}
// Add the new 'running' item into the scheduled jobs so we can check if the cachers are running
@ -77,6 +77,7 @@ namespace Ombi.Core
{
SearchForMovies = true,
SearchForTvShows = true,
SearchForActors = true,
BaseUrl = baseUrl ?? string.Empty,
CollectAnalyticData = true,
};
@ -113,6 +114,7 @@ namespace Ombi.Core
try
{
Task.Run(() => { CacheSonarrQualityProfiles(mc); });
Task.Run(() => { CacheRadarrQualityProfiles(mc); });
Task.Run(() => { CacheCouchPotatoQualityProfiles(mc); });
// we don't need to cache sickrage profiles, those are static
}
@ -126,7 +128,6 @@ namespace Ombi.Core
{
try
{
Log.Info("Executing GetSettings call to Sonarr for quality profiles");
var sonarrSettingsService = new SettingsServiceV2<SonarrSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), cacheProvider));
var sonarrSettings = sonarrSettingsService.GetSettings();
if (sonarrSettings.Enabled)
@ -144,11 +145,31 @@ namespace Ombi.Core
}
}
private void CacheRadarrQualityProfiles(ICacheProvider cacheProvider)
{
try
{
var radarrService = new SettingsServiceV2<RadarrSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), cacheProvider));
var radarrSettings = radarrService.GetSettings();
if (radarrSettings.Enabled)
{
Log.Info("Begin executing GetProfiles call to Radarr for quality profiles");
RadarrApi radarrApi = new RadarrApi();
var profiles = radarrApi.GetProfiles(radarrSettings.ApiKey, radarrSettings.FullUri);
cacheProvider.Set(CacheKeys.RadarrQualityProfiles, profiles);
Log.Info("Finished executing GetProfiles call to Radarr for quality profiles");
}
}
catch (Exception ex)
{
Log.Error(ex, "Failed to cache Sonarr quality profiles!");
}
}
private void CacheCouchPotatoQualityProfiles(ICacheProvider cacheProvider)
{
try
{
Log.Info("Executing GetSettings call to CouchPotato for quality profiles");
var cpSettingsService = new SettingsServiceV2<CouchPotatoSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), cacheProvider));
var cpSettings = cpSettingsService.GetSettings();
if (cpSettings.Enabled)

@ -168,7 +168,7 @@ namespace Ombi.Core.StatusChecker
var model = new StatusModel
{
DownloadUri = downloadLink,
ReleaseNotes = $"{branchDisplay} (See recent commits for details)",
ReleaseNotes = $"{branchDisplay} (See Recent Changes tab for more details)",
ReleaseTitle = $"Ombi {branchDisplay}",
NewVersion = branchResult.build.version,
UpdateUri = downloadLink,
@ -202,6 +202,7 @@ namespace Ombi.Core.StatusChecker
public async Task<Uri> OAuth(string url, ISession session)
{
await Task.Yield();
var csrf = StringCipher.Encrypt(Guid.NewGuid().ToString("N"), "CSRF");
session[SessionKeys.CSRF] = csrf;

@ -8,5 +8,6 @@ namespace Ombi.Core.Users
IEnumerable<UserHelperModel> GetUsers();
IEnumerable<UserHelperModel> GetUsersWithPermission(Permissions permission);
IEnumerable<UserHelperModel> GetUsersWithFeature(Features feature);
UserHelperModel GetUser(string username);
}
}

@ -30,30 +30,78 @@ using System.Linq;
using Ombi.Core.Models;
using Ombi.Helpers;
using Ombi.Helpers.Permissions;
using Ombi.Store.Models.Emby;
using Ombi.Store.Models.Plex;
using Ombi.Store.Repository;
namespace Ombi.Core.Users
{
public class UserHelper : IUserHelper
{
public UserHelper(IUserRepository userRepository, IPlexUserRepository plexUsers, ISecurityExtensions security)
public UserHelper(IUserRepository userRepository, IExternalUserRepository<PlexUsers> plexUsers, IExternalUserRepository<EmbyUsers> emby, ISecurityExtensions security)
{
LocalUserRepository = userRepository;
PlexUserRepository = plexUsers;
Security = security;
EmbyUserRepository = emby;
}
private IUserRepository LocalUserRepository { get; }
private IPlexUserRepository PlexUserRepository { get; }
private IExternalUserRepository<PlexUsers> PlexUserRepository { get; }
private ISecurityExtensions Security { get; }
private IExternalUserRepository<EmbyUsers> EmbyUserRepository { get; }
public UserHelperModel GetUser(string username)
{
var localUsers = LocalUserRepository.GetUserByUsername(username);
if (localUsers != null)
{
var props = ByteConverterHelper.ReturnObject<UserProperties>(localUsers.UserProperties);
return new UserHelperModel
{
Type = UserType.LocalUser,
Username = localUsers.UserName,
UserAlias = props.UserAlias,
EmailAddress = props.EmailAddress,
Permissions = (Permissions) localUsers.Permissions
};
}
var plexUsers = PlexUserRepository.GetUserByUsername(username);
if (plexUsers != null)
{
return new UserHelperModel
{
Type = UserType.PlexUser,
Username = plexUsers.Username,
UserAlias = plexUsers.UserAlias,
EmailAddress = plexUsers.EmailAddress,
Permissions = (Permissions)plexUsers.Permissions
};
}
var embyUsers = EmbyUserRepository.GetUserByUsername(username);
if (embyUsers != null)
{
return new UserHelperModel
{
Type = UserType.EmbyUser,
Username = embyUsers.Username,
UserAlias = embyUsers.UserAlias,
EmailAddress = embyUsers.EmailAddress,
Permissions = (Permissions)embyUsers.Permissions
};
}
return null;
}
public IEnumerable<UserHelperModel> GetUsers()
{
var model = new List<UserHelperModel>();
var localUsers = LocalUserRepository.GetAll();
var plexUsers = PlexUserRepository.GetAll();
var plexUsers = PlexUserRepository.GetAll().ToList();
var embyUsers = EmbyUserRepository.GetAll().ToList();
foreach (var user in localUsers)
{
@ -68,14 +116,30 @@ namespace Ombi.Core.Users
});
}
model.AddRange(plexUsers.Select(user => new UserHelperModel
if (plexUsers.Any())
{
Type = UserType.LocalUser,
Username = user.Username,
UserAlias = user.UserAlias,
EmailAddress = user.EmailAddress,
Permissions = (Permissions)user.Permissions
}));
model.AddRange(plexUsers.Select(user => new UserHelperModel
{
Type = UserType.PlexUser,
Username = user.Username,
UserAlias = user.UserAlias,
EmailAddress = user.EmailAddress,
Permissions = (Permissions) user.Permissions
}));
}
if (embyUsers.Any())
{
model.AddRange(embyUsers.Select(user => new UserHelperModel
{
Type = UserType.EmbyUser,
Username = user.Username,
UserAlias = user.UserAlias,
EmailAddress = user.EmailAddress,
Permissions = (Permissions)user.Permissions
}));
}
return model;
}
@ -86,9 +150,11 @@ namespace Ombi.Core.Users
var localUsers = LocalUserRepository.GetAll().ToList();
var plexUsers = PlexUserRepository.GetAll().ToList();
var embyUsers = EmbyUserRepository.GetAll().ToList();
var filteredLocal = localUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
var filteredPlex = plexUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
var filteredEmby = embyUsers.Where(x => ((Permissions)x.Permissions).HasFlag(permission));
foreach (var user in filteredLocal)
@ -107,7 +173,7 @@ namespace Ombi.Core.Users
model.AddRange(filteredPlex.Select(user => new UserHelperModel
{
Type = UserType.LocalUser,
Type = UserType.PlexUser,
Username = user.Username,
UserAlias = user.UserAlias,
EmailAddress = user.EmailAddress,
@ -115,6 +181,17 @@ namespace Ombi.Core.Users
Features = (Features)user.Features
}));
model.AddRange(filteredEmby.Select(user => new UserHelperModel
{
Type = UserType.EmbyUser,
Username = user.Username,
UserAlias = user.UserAlias,
EmailAddress = user.EmailAddress,
Permissions = (Permissions)user.Permissions,
Features = (Features)user.Features
}));
return model;
}
@ -124,9 +201,11 @@ namespace Ombi.Core.Users
var localUsers = LocalUserRepository.GetAll().ToList();
var plexUsers = PlexUserRepository.GetAll().ToList();
var embyUsers = PlexUserRepository.GetAll().ToList();
var filteredLocal = localUsers.Where(x => ((Features)x.Features).HasFlag(features));
var filteredPlex = plexUsers.Where(x => ((Features)x.Features).HasFlag(features));
var filteredEmby = embyUsers.Where(x => ((Features)x.Features).HasFlag(features));
foreach (var user in filteredLocal)
@ -145,7 +224,17 @@ namespace Ombi.Core.Users
model.AddRange(filteredPlex.Select(user => new UserHelperModel
{
Type = UserType.LocalUser,
Type = UserType.PlexUser,
Username = user.Username,
UserAlias = user.UserAlias,
EmailAddress = user.EmailAddress,
Permissions = (Permissions)user.Permissions,
Features = (Features)user.Features
}));
model.AddRange(filteredEmby.Select(user => new UserHelperModel
{
Type = UserType.EmbyUser,
Username = user.Username,
UserAlias = user.UserAlias,
EmailAddress = user.EmailAddress,

@ -48,7 +48,7 @@ namespace Ombi.Helpers.Tests
var consts = typeof(UserClaims).GetConstantsValues<string>();
Assert.That(consts.Contains("Admin"),Is.True);
Assert.That(consts.Contains("PowerUser"),Is.True);
Assert.That(consts.Contains("User"),Is.True);
Assert.That(consts.Contains("RegularUser"),Is.True);
}
private static IEnumerable<TestCaseData> TypeData
@ -59,14 +59,7 @@ namespace Ombi.Helpers.Tests
yield return new TestCaseData(typeof(int)).Returns(new string[0]).SetName("NoPropeties Class");
yield return new TestCaseData(typeof(IEnumerable<>)).Returns(new string[0]).SetName("Interface");
yield return new TestCaseData(typeof(string)).Returns(new[] { "Chars", "Length" }).SetName("String");
yield return new TestCaseData(typeof(RequestedModel)).Returns(
new[]
{
"ProviderId", "ImdbId", "TvDbId", "Overview", "Title", "PosterPath", "ReleaseDate", "Type",
"Status", "Approved", "RequestedBy", "RequestedDate", "Available", "Issues", "OtherMessage", "AdminNote",
"SeasonList", "SeasonCount", "SeasonsRequested", "MusicBrainzId", "RequestedUsers","ArtistName",
"ArtistId","IssueId","Episodes", "Denied", "DeniedReason", "AllUsers","CanApprove","Id",
}).SetName("Requested Model");
}
}

@ -82,6 +82,19 @@ namespace Ombi.Helpers
if (descriptionAttributes == null) return string.Empty;
return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString();
}
public static BranchAttribute GetBranchValue<U>(T value) where U : BranchAttribute
{
var fieldInfo = value.GetType().GetField(value.ToString());
var descriptionAttributes = fieldInfo.GetCustomAttributes(
typeof(BranchAttribute), false) as BranchAttribute[];
return descriptionAttributes?.FirstOrDefault();
}
public static string GetDisplayDescription(T value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
@ -127,4 +140,9 @@ namespace Ombi.Helpers
return Enum.GetValues(typeof(T)).Cast<int>().Sum();
}
}
public class BranchAttribute : Attribute
{
public string DisplayName { get; set; }
public string BranchName { get; set; }
}
}

@ -73,6 +73,9 @@ namespace Ombi.Helpers.Permissions
UsersCanViewOnlyOwnIssues = 2048,
[Display(Name = "Bypass the request limit")]
BypassRequestLimit = 4096
BypassRequestLimit = 4096,
[Display(Name = "User can see who requested")]
ViewUsers = 8192
}
}

@ -99,7 +99,7 @@ namespace Ombi.Helpers
public static string GetPlexMediaUrl(string machineId, string mediaId)
{
var url =
$"https://app.plex.tv/web/app#!/server/{machineId}/details/%2Flibrary%2Fmetadata%2F{mediaId}";
$"https://app.plex.tv/web/app#!/server/{machineId}/details?key=library%2Fmetadata%2F{mediaId}";
return url;
}
@ -116,4 +116,4 @@ namespace Ombi.Helpers
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
}
}
}

@ -25,6 +25,7 @@
// ************************************************************************/
#endregion
using System.Linq;
using System.Security.Cryptography;
using System.Text;
@ -34,6 +35,10 @@ namespace Ombi.Helpers
{
public static string CalcuateMd5Hash(string input)
{
if (string.IsNullOrEmpty(input))
{
return string.Empty;
}
using (var md5 = MD5.Create())
{
var inputBytes = Encoding.UTF8.GetBytes(input);
@ -49,5 +54,10 @@ namespace Ombi.Helpers
return sb.ToString();
}
}
public static string GetSha1Hash(string input)
{
return string.Join("", (new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input))).Select(x => x.ToString("x2")).ToArray());
}
}
}

@ -30,6 +30,7 @@ namespace Ombi.Helpers
public enum UserType
{
PlexUser,
LocalUser
LocalUser,
EmbyUser
}
}

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ombi.Mono
{
public class Class1
{
}
}

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>96c89180-1fb5-48b7-9d35-6eb5f11c9d95</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Ombi.Mono</RootNamespace>
<AssemblyName>Ombi.Mono</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Xml.Linq"/>
<Reference Include="System.Data.DataSetExtensions"/>
<Reference Include="Microsoft.CSharp"/>
<Reference Include="System.Data"/>
<Reference Include="System.Net.Http"/>
<Reference Include="System.Xml"/>
</ItemGroup>
<ItemGroup>
<Compile Include="Class1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Ombi.Mono")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Ombi.Mono")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("96c89180-1fb5-48b7-9d35-6eb5f11c9d95")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -249,7 +249,7 @@
// });
// CacheMock.Setup(x => x.Get<List<PlexSearch>>(CacheKeys.PlexLibaries)).Returns(cachedMovies);
// SettingsMock.Setup(x => x.GetSettings()).Returns(F.Create<PlexSettings>());
// var movies = Checker.GetPlexMovies();
// var movies = Checker.GetEmbyMovies();
// Assert.That(movies.Any(x => x.ProviderId == "1212"));
// }
@ -267,7 +267,7 @@
// });
// SettingsMock.Setup(x => x.GetSettings()).Returns(F.Create<PlexSettings>());
// CacheMock.Setup(x => x.Get<List<PlexSearch>>(CacheKeys.PlexLibaries)).Returns(cachedTv);
// var movies = Checker.GetPlexTvShows();
// var movies = Checker.GetEmbyTvShows();
// Assert.That(movies.Any(x => x.ProviderId == "1212"));
// }

@ -37,15 +37,15 @@ namespace Ombi.Services.Interfaces
void Start();
void CheckAndUpdateAll();
IEnumerable<PlexContent> GetPlexMovies(IEnumerable<PlexContent> content);
bool IsMovieAvailable(PlexContent[] plexMovies, string title, string year, string providerId = null);
bool IsMovieAvailable(IEnumerable<PlexContent> plexMovies, string title, string year, string providerId = null);
IEnumerable<PlexContent> GetPlexTvShows(IEnumerable<PlexContent> content);
bool IsTvShowAvailable(PlexContent[] plexShows, string title, string year, string providerId = null, int[] seasons = null);
bool IsTvShowAvailable(IEnumerable<PlexContent> plexShows, string title, string year, string providerId = null, int[] seasons = null);
IEnumerable<PlexContent> GetPlexAlbums(IEnumerable<PlexContent> content);
bool IsAlbumAvailable(PlexContent[] plexAlbums, string title, string year, string artist);
bool IsAlbumAvailable(IEnumerable<PlexContent> plexAlbums, string title, string year, string artist);
bool IsEpisodeAvailable(string theTvDbId, int season, int episode);
PlexContent GetAlbum(PlexContent[] plexAlbums, string title, string year, string artist);
PlexContent GetMovie(PlexContent[] plexMovies, string title, string year, string providerId = null);
PlexContent GetTvShow(PlexContent[] plexShows, string title, string year, string providerId = null, int[] seasons = null);
PlexContent GetAlbum(IEnumerable<PlexContent> plexAlbums, string title, string year, string artist);
PlexContent GetMovie(IEnumerable<PlexContent> plexMovies, string title, string year, string providerId = null);
PlexContent GetTvShow(IEnumerable<PlexContent> plexShows, string title, string year, string providerId = null, int[] seasons = null);
/// <summary>
/// Gets the episode's stored in the cache.
/// </summary>

@ -0,0 +1,6 @@
namespace Ombi.Services.Interfaces
{
public interface IEmbyNotificationEngine : INotificationEngine
{
}
}

@ -0,0 +1,12 @@
using Quartz;
namespace Ombi.Services.Jobs
{
public interface IMassEmail
{
void Execute(IJobExecutionContext context);
void MassEmailAdminTest(string html, string subject);
void SendMassEmail(string html, string subject);
}
}

@ -34,7 +34,7 @@ namespace Ombi.Services.Interfaces
{
public interface INotificationEngine
{
Task NotifyUsers(IEnumerable<RequestedModel> modelChanged, string apiKey, NotificationType type);
Task NotifyUsers(RequestedModel modelChanged, string apiKey, NotificationType type);
Task NotifyUsers(IEnumerable<RequestedModel> modelChanged, NotificationType type);
Task NotifyUsers(RequestedModel modelChanged, NotificationType type);
}
}

@ -0,0 +1,6 @@
namespace Ombi.Services.Interfaces
{
public interface IPlexNotificationEngine : INotificationEngine
{
}
}

@ -5,7 +5,7 @@ namespace Ombi.Services.Jobs
public interface IRecentlyAdded
{
void Execute(IJobExecutionContext context);
void Test();
void Start();
void RecentlyAddedAdminTest();
void StartNewsLetter();
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save