You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Ombi/PlexRequests.UI/Modules/SearchModule.cs

984 lines
43 KiB

9 years ago
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: SearchModule.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.Globalization;
using System.Linq;
9 years ago
using Nancy;
using Nancy.Responses.Negotiation;
9 years ago
using NLog;
9 years ago
using PlexRequests.Api;
using PlexRequests.Api.Interfaces;
using PlexRequests.Api.Models.Music;
9 years ago
using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
9 years ago
using PlexRequests.Helpers;
9 years ago
using PlexRequests.Helpers.Exceptions;
using PlexRequests.Services.Interfaces;
using PlexRequests.Services.Notification;
9 years ago
using PlexRequests.Store;
using PlexRequests.UI.Helpers;
using PlexRequests.UI.Models;
using System.Threading.Tasks;
using Nancy.Extensions;
using Nancy.Responses;
using PlexRequests.Api.Models.Tv;
using PlexRequests.Core.Models;
using PlexRequests.Store.Models;
using PlexRequests.Store.Repository;
using TMDbLib.Objects.General;
9 years ago
9 years ago
namespace PlexRequests.UI.Modules
9 years ago
{
public class SearchModule : BaseAuthModule
9 years ago
{
public SearchModule(ICacheProvider cache, ISettingsService<CouchPotatoSettings> cpSettings,
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings,
ISettingsService<SickRageSettings> sickRageService, ICouchPotatoApi cpApi, ISickRageApi srApi,
INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi, ISettingsService<HeadphonesSettings> hpService,
ICouchPotatoCacher cpCacher, ISonarrCacher sonarrCacher, ISickRageCacher sickRageCacher, IPlexApi plexApi,
ISettingsService<PlexSettings> plexService, ISettingsService<AuthenticationSettings> auth, IRepository<UsersToNotify> u, ISettingsService<EmailNotificationSettings> email,
IIssueService issue) : base("search", prSettings)
9 years ago
{
Auth = auth;
PlexService = plexService;
PlexApi = plexApi;
CpService = cpSettings;
PrService = prSettings;
MovieApi = new TheMovieDbApi();
Cache = cache;
Checker = checker;
CpCacher = cpCacher;
SonarrCacher = sonarrCacher;
SickRageCacher = sickRageCacher;
RequestService = request;
SonarrApi = sonarrApi;
SonarrService = sonarrSettings;
CouchPotatoApi = cpApi;
SickRageService = sickRageService;
SickrageApi = srApi;
NotificationService = notify;
MusicBrainzApi = mbApi;
HeadphonesApi = hpApi;
HeadphonesService = hpService;
UsersToNotifyRepo = u;
EmailNotificationSettings = email;
IssueService = issue;
Get["/", true] = async (x, ct) => await RequestLoad();
9 years ago
Get["movie/{searchTerm}", true] = async (x, ct) => await SearchMovie((string)x.searchTerm);
Get["tv/{searchTerm}", true] = async (x, ct) => await SearchTvShow((string)x.searchTerm);
Get["music/{searchTerm}", true] = async (x, ct) => await SearchMusic((string)x.searchTerm);
Get["music/coverArt/{id}"] = p => GetMusicBrainzCoverArt((string)p.id);
9 years ago
Get["movie/upcoming", true] = async (x, ct) => await UpcomingMovies();
Get["movie/playing", true] = async (x, ct) => await CurrentlyPlayingMovies();
9 years ago
Post["request/movie", true] = async (x, ct) => await RequestMovie((int)Request.Form.movieId);
Post["request/tv", true] = async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId);
Post["/notifyuser", true] = async (x, ct) => await NotifyUser((bool)Request.Form.notify);
Get["/notifyuser", true] = async (x, ct) => await GetUserNotificationSettings();
Get["/seasons"] = x => GetSeasons();
9 years ago
}
private IPlexApi PlexApi { get; }
private TheMovieDbApi MovieApi { get; }
private INotificationService NotificationService { get; }
private ICouchPotatoApi CouchPotatoApi { get; }
private ISonarrApi SonarrApi { get; }
private ISickRageApi SickrageApi { get; }
private IRequestService RequestService { get; }
private ICacheProvider Cache { get; }
private ISettingsService<AuthenticationSettings> Auth { get; }
private ISettingsService<PlexSettings> PlexService { get; }
private ISettingsService<CouchPotatoSettings> CpService { get; }
private ISettingsService<PlexRequestSettings> PrService { get; }
private ISettingsService<SonarrSettings> SonarrService { get; }
private ISettingsService<SickRageSettings> SickRageService { get; }
private ISettingsService<HeadphonesSettings> HeadphonesService { get; }
private ISettingsService<EmailNotificationSettings> EmailNotificationSettings { get; }
private IAvailabilityChecker Checker { get; }
private ICouchPotatoCacher CpCacher { get; }
private ISonarrCacher SonarrCacher { get; }
private ISickRageCacher SickRageCacher { get; }
private IMusicBrainzApi MusicBrainzApi { get; }
private IHeadphonesApi HeadphonesApi { get; }
private IRepository<UsersToNotify> UsersToNotifyRepo { get; }
private IIssueService IssueService { get; }
9 years ago
private static Logger Log = LogManager.GetCurrentClassLogger();
9 years ago
private async Task<Negotiator> RequestLoad()
{
var settings = await PrService.GetSettingsAsync();
9 years ago
Log.Trace("Loading Index");
return View["Search/Index", settings];
9 years ago
}
private async Task<Response> UpcomingMovies()
{
Log.Trace("Loading upcoming movies");
return await ProcessMovies(MovieSearchType.Upcoming, string.Empty);
}
private async Task<Response> CurrentlyPlayingMovies()
{
Log.Trace("Loading currently playing movies");
return await ProcessMovies(MovieSearchType.CurrentlyPlaying, string.Empty);
}
private async Task<Response> SearchMovie(string searchTerm)
9 years ago
{
9 years ago
Log.Trace("Searching for Movie {0}", searchTerm);
return await ProcessMovies(MovieSearchType.Search, searchTerm);
}
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
{
var apiMovies = new List<MovieResult>();
await Task.Factory.StartNew(
() =>
{
switch (searchType)
{
case MovieSearchType.Search:
return
MovieApi.SearchMovie(searchTerm)
.Result.Select(
x =>
new MovieResult()
{
Adult = x.Adult,
BackdropPath = x.BackdropPath,
GenreIds = x.GenreIds,
Id = x.Id,
OriginalLanguage = x.OriginalLanguage,
OriginalTitle = x.OriginalTitle,
Overview = x.Overview,
Popularity = x.Popularity,
PosterPath = x.PosterPath,
ReleaseDate = x.ReleaseDate,
Title = x.Title,
Video = x.Video,
VoteAverage = x.VoteAverage,
VoteCount = x.VoteCount
})
.ToList();
case MovieSearchType.CurrentlyPlaying:
return MovieApi.GetCurrentPlayingMovies().Result.ToList();
case MovieSearchType.Upcoming:
return MovieApi.GetUpcomingMovies().Result.ToList();
default:
return new List<MovieResult>();
}
}).ContinueWith(
(t) =>
{
apiMovies = t.Result;
});
var allResults = await RequestService.GetAllAsync();
allResults = allResults.Where(x => x.Type == RequestType.Movie);
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
var dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
var cpCached = CpCacher.QueuedIds();
var plexMovies = Checker.GetPlexMovies();
var settings = await PrService.GetSettingsAsync();
var viewMovies = new List<SearchMovieViewModel>();
foreach (MovieResult movie in apiMovies)
{
var viewMovie = new SearchMovieViewModel
{
Adult = movie.Adult,
BackdropPath = movie.BackdropPath,
GenreIds = movie.GenreIds,
Id = movie.Id,
OriginalLanguage = movie.OriginalLanguage,
OriginalTitle = movie.OriginalTitle,
Overview = movie.Overview,
Popularity = movie.Popularity,
PosterPath = movie.PosterPath,
ReleaseDate = movie.ReleaseDate,
Title = movie.Title,
Video = movie.Video,
VoteAverage = movie.VoteAverage,
VoteCount = movie.VoteCount
};
var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies);
if (Checker.IsMovieAvailable(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString()))
{
viewMovie.Available = true;
}
else if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db
{
var dbm = dbMovies[movie.Id];
viewMovie.Requested = true;
viewMovie.Approved = dbm.Approved;
viewMovie.Available = dbm.Available;
}
else if (cpCached.Contains(movie.Id) && canSee) // compare to the couchpotato db
{
viewMovie.Requested = true;
}
viewMovies.Add(viewMovie);
}
return Response.AsJson(viewMovies);
9 years ago
}
private bool CanUserSeeThisRequest(int movieId, bool usersCanViewOnlyOwnRequests, Dictionary<int, RequestedModel> moviesInDb)
{
if (usersCanViewOnlyOwnRequests)
{
var result = moviesInDb.FirstOrDefault(x => x.Value.ProviderId == movieId);
9 years ago
return result.Value == null || result.Value.UserHasRequested(Username);
}
return true;
}
private async Task<Response> SearchTvShow(string searchTerm)
9 years ago
{
var plexSettings = await PlexService.GetSettingsAsync();
9 years ago
Log.Trace("Searching for TV Show {0}", searchTerm);
9 years ago
var apiTv = new List<TvMazeSearch>();
await Task.Factory.StartNew(() => new TvMazeApi().Search(searchTerm)).ContinueWith((t) =>
{
apiTv = t.Result;
});
var allResults = await RequestService.GetAllAsync();
allResults = allResults.Where(x => x.Type == RequestType.TvShow);
var dbTv = allResults.ToDictionary(x => x.ProviderId);
if (!apiTv.Any())
{
Log.Trace("TV Show data is null");
return Response.AsJson("");
}
var sonarrCached = SonarrCacher.QueuedIds();
var sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays
var plexTvShows = Checker.GetPlexTvShows();
var viewTv = new List<SearchTvShowViewModel>();
foreach (var t in apiTv)
{
9 years ago
var banner = t.show.image?.medium;
if (!string.IsNullOrEmpty(banner))
{
banner = banner.Replace("http", "https");
}
var viewT = new SearchTvShowViewModel
{
9 years ago
Banner = banner,
FirstAired = t.show.premiered,
Id = t.show.externals?.thetvdb ?? 0,
ImdbId = t.show.externals?.imdb,
Network = t.show.network?.name,
NetworkId = t.show.network?.id.ToString(),
Overview = t.show.summary.RemoveHtml(),
Rating = t.score.ToString(CultureInfo.CurrentUICulture),
Runtime = t.show.runtime.ToString(),
SeriesId = t.show.id,
SeriesName = t.show.name,
Status = t.show.status
};
var providerId = string.Empty;
if (plexSettings.AdvancedSearch)
{
providerId = viewT.Id.ToString();
}
if (Checker.IsTvShowAvailable(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId))
{
viewT.Available = true;
}
else if (t.show?.externals?.thetvdb != null)
{
int tvdbid = (int)t.show.externals.thetvdb;
if (dbTv.ContainsKey(tvdbid))
{
var dbt = dbTv[tvdbid];
viewT.Requested = true;
viewT.Approved = dbt.Approved;
viewT.Available = dbt.Available;
}
else if (sonarrCached.Contains(tvdbid) || sickRageCache.Contains(tvdbid)) // compare to the sonarr/sickrage db
{
viewT.Requested = true;
}
}
viewTv.Add(viewT);
}
return Response.AsJson(viewTv);
9 years ago
}
private async Task<Response> SearchMusic(string searchTerm)
{
var apiAlbums = new List<Release>();
await Task.Run(() => MusicBrainzApi.SearchAlbum(searchTerm)).ContinueWith((t) =>
{
apiAlbums = t.Result.releases ?? new List<Release>();
});
var allResults = await RequestService.GetAllAsync();
allResults = allResults.Where(x => x.Type == RequestType.Album);
var dbAlbum = allResults.ToDictionary(x => x.MusicBrainzId);
var plexAlbums = Checker.GetPlexAlbums();
var viewAlbum = new List<SearchMusicViewModel>();
foreach (var a in apiAlbums)
{
var viewA = new SearchMusicViewModel
{
Title = a.title,
Id = a.id,
Artist = a.ArtistCredit?.Select(x => x.artist?.name).FirstOrDefault(),
Overview = a.disambiguation,
ReleaseDate = a.date,
TrackCount = a.TrackCount,
ReleaseType = a.status,
Country = a.country
};
DateTime release;
DateTimeHelper.CustomParse(a.ReleaseEvents?.FirstOrDefault()?.date, out release);
var artist = a.ArtistCredit?.FirstOrDefault()?.artist;
if (Checker.IsAlbumAvailable(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name))
{
viewA.Available = true;
}
if (!string.IsNullOrEmpty(a.id) && dbAlbum.ContainsKey(a.id))
{
var dba = dbAlbum[a.id];
9 years ago
viewA.Requested = true;
viewA.Approved = dba.Approved;
viewA.Available = dba.Available;
}
viewAlbum.Add(viewA);
}
return Response.AsJson(viewAlbum);
9 years ago
}
private async Task<Response> RequestMovie(int movieId)
9 years ago
{
var movieInfo = MovieApi.GetMovieInformation(movieId).Result;
var fullMovieName = $"{movieInfo.Title}{(movieInfo.ReleaseDate.HasValue ? $" ({movieInfo.ReleaseDate.Value.Year})" : string.Empty)}";
Log.Trace("Getting movie info from TheMovieDb");
var settings = await PrService.GetSettingsAsync();
// check if the movie has already been requested
Log.Info("Requesting movie with id {0}", movieId);
var existingRequest = await RequestService.CheckRequestAsync(movieId);
if (existingRequest != null)
{
// check if the current user is already marked as a requester for this movie, if not, add them
if (!existingRequest.UserHasRequested(Username))
{
existingRequest.RequestedUsers.Add(Username);
await RequestService.UpdateRequestAsync(existingRequest);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullMovieName} was successfully added!" : $"{fullMovieName} has already been requested!" });
}
Log.Debug("movie with id {0} doesnt exists", movieId);
9 years ago
9 years ago
try
{
var movies = Checker.GetPlexMovies();
if (Checker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
9 years ago
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullMovieName} is already in Plex!" });
9 years ago
}
}
catch (Exception e)
{
Log.Error(e);
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"We could not check if {fullMovieName} is in Plex, are you sure it's correctly setup?" });
}
//#endif
var model = new RequestedModel
{
ProviderId = movieInfo.Id,
Type = RequestType.Movie,
Overview = movieInfo.Overview,
ImdbId = movieInfo.ImdbId,
PosterPath = "https://image.tmdb.org/t/p/w150/" + movieInfo.PosterPath,
Title = movieInfo.Title,
ReleaseDate = movieInfo.ReleaseDate ?? DateTime.MinValue,
Status = movieInfo.Status,
RequestedDate = DateTime.UtcNow,
Approved = false,
RequestedUsers = new List<string> { Username },
Issues = IssueState.None,
};
if (ShouldAutoApprove(RequestType.Movie, settings))
{
var cpSettings = await CpService.GetSettingsAsync();
9 years ago
if (cpSettings.Enabled)
{
Log.Info("Adding movie to CP (No approval required)");
var result = CouchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title,
cpSettings.FullUri, cpSettings.ProfileId);
Log.Debug("Adding movie to CP result {0}", result);
if (result)
{
model.Approved = true;
Log.Info("Adding movie to database (No approval required)");
await RequestService.AddRequestAsync(model);
if (ShouldSendNotification())
{
var notificationModel = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest
};
await NotificationService.Publish(notificationModel);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" });
}
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message =
"Something went wrong adding the movie to CouchPotato! Please check your settings."
});
}
else
{
model.Approved = true;
Log.Info("Adding movie to database (No approval required)");
await RequestService.AddRequestAsync(model);
if (ShouldSendNotification())
{
var notificationModel = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest
};
await NotificationService.Publish(notificationModel);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" });
}
}
try
{
Log.Info("Adding movie to database");
var id = await RequestService.AddRequestAsync(model);
var notificationModel = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest };
await NotificationService.Publish(notificationModel);
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" });
}
catch (Exception e)
{
Log.Fatal(e);
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something went wrong adding the movie to CouchPotato! Please check your settings." });
}
9 years ago
}
/// <summary>
/// Requests the tv show.
/// </summary>
/// <param name="showId">The show identifier.</param>
/// <param name="seasons">The seasons.</param>
/// <returns></returns>
private async Task<Response> RequestTvShow(int showId, string seasons)
9 years ago
{
var tvApi = new TvMazeApi();
var showInfo = tvApi.ShowLookupByTheTvDbId(showId);
DateTime firstAir;
DateTime.TryParse(showInfo.premiered, out firstAir);
string fullShowName = $"{showInfo.name} ({firstAir.Year})";
//#if !DEBUG
var settings = await PrService.GetSettingsAsync();
// check if the show has already been requested
Log.Info("Requesting tv show with id {0}", showId);
var existingRequest = await RequestService.CheckRequestAsync(showId);
if (existingRequest != null)
{
// check if the current user is already marked as a requester for this show, if not, add them
if (!existingRequest.UserHasRequested(Username))
{
existingRequest.RequestedUsers.Add(Username);
await RequestService.UpdateRequestAsync(existingRequest);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullShowName} was successfully added!" : $"{fullShowName} has already been requested!" });
}
9 years ago
try
{
var shows = Checker.GetPlexTvShows();
var providerId = string.Empty;
var plexSettings = await PlexService.GetSettingsAsync();
if (plexSettings.AdvancedSearch)
{
providerId = showId.ToString();
}
if (Checker.IsTvShowAvailable(shows.ToArray(), showInfo.name, showInfo.premiered?.Substring(0, 4), providerId))
9 years ago
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullShowName} is already in Plex!" });
9 years ago
}
}
9 years ago
catch (Exception)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = $"We could not check if {fullShowName} is in Plex, are you sure it's correctly setup?" });
}
//#endif
var model = new RequestedModel
{
ProviderId = showInfo.externals?.thetvdb ?? 0,
Type = RequestType.TvShow,
Overview = showInfo.summary.RemoveHtml(),
PosterPath = showInfo.image?.medium,
Title = showInfo.name,
ReleaseDate = firstAir,
Status = showInfo.status,
RequestedDate = DateTime.UtcNow,
Approved = false,
RequestedUsers = new List<string> { Username },
Issues = IssueState.None,
ImdbId = showInfo.externals?.imdb ?? string.Empty,
9 years ago
SeasonCount = showInfo.seasonCount,
TvDbId = showId.ToString()
};
9 years ago
var seasonsList = new List<int>();
switch (seasons)
9 years ago
{
case "first":
seasonsList.Add(1);
model.SeasonsRequested = "First";
break;
case "latest":
seasonsList.Add(model.SeasonCount);
model.SeasonsRequested = "Latest";
break;
9 years ago
case "all":
model.SeasonsRequested = "All";
break;
9 years ago
default:
9 years ago
model.SeasonsRequested = seasons;
9 years ago
var split = seasons.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var seasonsCount = new int[split.Length];
for (var i = 0; i < split.Length; i++)
{
int tryInt;
int.TryParse(split[i], out tryInt);
seasonsCount[i] = tryInt;
}
seasonsList.AddRange(seasonsCount);
break;
9 years ago
}
9 years ago
model.SeasonList = seasonsList.ToArray();
if (ShouldAutoApprove(RequestType.TvShow, settings))
{
var sonarrSettings = await SonarrService.GetSettingsAsync();
var sender = new TvSender(SonarrApi, SickrageApi);
if (sonarrSettings.Enabled)
{
var result = sender.SendToSonarr(sonarrSettings, model);
if (!string.IsNullOrEmpty(result?.title))
{
model.Approved = true;
Log.Debug("Adding tv to database requests (No approval required & Sonarr)");
await RequestService.AddRequestAsync(model);
if (ShouldSendNotification())
{
var notify1 = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest
};
await NotificationService.Publish(notify1);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
}
return Response.AsJson(ValidationHelper.SendSonarrError(result?.ErrorMessages));
}
var srSettings = SickRageService.GetSettings();
if (srSettings.Enabled)
{
var result = sender.SendToSickRage(srSettings, model);
if (result?.result == "success")
{
model.Approved = true;
Log.Debug("Adding tv to database requests (No approval required & SickRage)");
await RequestService.AddRequestAsync(model);
if (ShouldSendNotification())
{
var notify2 = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest
};
await NotificationService.Publish(notify2);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = result?.message != null ? "<b>Message From SickRage: </b>" + result.message : "Something went wrong adding the movie to SickRage! Please check your settings." });
}
9 years ago
if (!srSettings.Enabled && !sonarrSettings.Enabled)
{
model.Approved = true;
Log.Debug("Adding tv to database requests (No approval required) and Sonarr/Sickrage not setup");
await RequestService.AddRequestAsync(model);
9 years ago
if (ShouldSendNotification())
{
var notify2 = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest
};
await NotificationService.Publish(notify2);
9 years ago
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = "The request of TV Shows is not correctly set up. Please contact your admin." });
}
await RequestService.AddRequestAsync(model);
var notificationModel = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest };
await NotificationService.Publish(notificationModel);
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" });
9 years ago
}
private bool ShouldSendNotification()
{
var sendNotification = true;
var claims = Context.CurrentUser?.Claims;
if (claims != null)
{
var enumerable = claims as string[] ?? claims.ToArray();
if (enumerable.Contains(UserClaims.Admin) || enumerable.Contains(UserClaims.PowerUser))
{
sendNotification = false; // Don't bother sending a notification if the user is an admin
}
}
return sendNotification;
}
private async Task<Response> RequestAlbum(string releaseId)
{
var settings = await PrService.GetSettingsAsync();
var existingRequest = await RequestService.CheckRequestAsync(releaseId);
Log.Debug("Checking for an existing request");
if (existingRequest != null)
{
Log.Debug("We do have an existing album request");
if (!existingRequest.UserHasRequested(Username))
{
Log.Debug("Not in the requested list so adding them and updating the request. User: {0}", Username);
existingRequest.RequestedUsers.Add(Username);
await RequestService.UpdateRequestAsync(existingRequest);
}
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{existingRequest.Title} was successfully added!" : $"{existingRequest.Title} has already been requested!" });
}
Log.Debug("This is a new request");
var albumInfo = MusicBrainzApi.GetAlbum(releaseId);
9 years ago
DateTime release;
DateTimeHelper.CustomParse(albumInfo.ReleaseEvents?.FirstOrDefault()?.date, out release);
var artist = albumInfo.ArtistCredits?.FirstOrDefault()?.artist;
if (artist == null)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "We could not find the artist on MusicBrainz. Please try again later or contact your admin" });
}
var albums = Checker.GetPlexAlbums();
var alreadyInPlex = Checker.IsAlbumAvailable(albums.ToArray(), albumInfo.title, release.ToString("yyyy"), artist.name);
if (alreadyInPlex)
{
return Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"{albumInfo.title} is already in Plex!"
});
}
var img = GetMusicBrainzCoverArt(albumInfo.id);
var model = new RequestedModel
{
Title = albumInfo.title,
MusicBrainzId = albumInfo.id,
Overview = albumInfo.disambiguation,
PosterPath = img,
Type = RequestType.Album,
ProviderId = 0,
RequestedUsers = new List<string> { Username },
Status = albumInfo.status,
9 years ago
Issues = IssueState.None,
RequestedDate = DateTime.UtcNow,
ReleaseDate = release,
ArtistName = artist.name,
ArtistId = artist.id
};
if (ShouldAutoApprove(RequestType.Album, settings))
{
Log.Debug("We don't require approval OR the user is in the whitelist");
var hpSettings = HeadphonesService.GetSettings();
if (!hpSettings.Enabled)
{
await RequestService.AddRequestAsync(model);
return
Response.AsJson(new JsonResponseModel
{
Result = true,
Message = $"{model.Title} was successfully added!"
});
}
var sender = new HeadphonesSender(HeadphonesApi, hpSettings, RequestService);
await sender.AddAlbum(model);
model.Approved = true;
await RequestService.AddRequestAsync(model);
if (ShouldSendNotification())
{
var notify2 = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest
};
await NotificationService.Publish(notify2);
}
return
Response.AsJson(new JsonResponseModel
{
Result = true,
Message = $"{model.Title} was successfully added!"
});
}
if (ShouldSendNotification())
{
var notify2 = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest
};
await NotificationService.Publish(notify2);
}
await RequestService.AddRequestAsync(model);
return Response.AsJson(new JsonResponseModel
{
Result = true,
Message = $"{model.Title} was successfully added!"
});
}
private string GetMusicBrainzCoverArt(string id)
{
var coverArt = MusicBrainzApi.GetCoverArt(id);
var firstImage = coverArt?.images?.FirstOrDefault();
var img = string.Empty;
if (firstImage != null)
{
img = firstImage.thumbnails?.small ?? firstImage.image;
}
return img;
}
private bool ShouldAutoApprove(RequestType requestType, PlexRequestSettings prSettings)
{
// if the user is an admin or they are whitelisted, they go ahead and allow auto-approval
if (IsAdmin || prSettings.ApprovalWhiteList.Any(x => x.Equals(Username, StringComparison.OrdinalIgnoreCase))) return true;
// check by request type if the category requires approval or not
switch (requestType)
{
case RequestType.Movie:
return !prSettings.RequireMovieApproval;
case RequestType.TvShow:
return !prSettings.RequireTvShowApproval;
case RequestType.Album:
return !prSettings.RequireMusicApproval;
default:
return false;
}
}
private async Task<Response> NotifyUser(bool notify)
{
var authSettings = await Auth.GetSettingsAsync();
var auth = authSettings.UserAuthentication;
var emailSettings = await EmailNotificationSettings.GetSettingsAsync();
var email = emailSettings.EnableUserEmailNotifications;
if (!auth)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, but this functionality is currently only for users with Plex accounts" });
}
if (!email)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, but your administrator has not yet enabled this functionality." });
}
var username = Username;
var originalList = await UsersToNotifyRepo.GetAllAsync();
if (!notify)
{
if (originalList == null)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "We could not remove this notification because you never had it!" });
}
var userToRemove = originalList.FirstOrDefault(x => x.Username == username);
if (userToRemove != null)
{
await UsersToNotifyRepo.DeleteAsync(userToRemove);
}
return Response.AsJson(new JsonResponseModel { Result = true });
}
if (originalList == null)
{
var userModel = new UsersToNotify { Username = username };
var insertResult = await UsersToNotifyRepo.InsertAsync(userModel);
return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Could not save, please try again" });
}
var existingUser = originalList.FirstOrDefault(x => x.Username == username);
if (existingUser != null)
{
return Response.AsJson(new JsonResponseModel { Result = true }); // It's already enabled
}
else
{
var userModel = new UsersToNotify { Username = username };
var insertResult = await UsersToNotifyRepo.InsertAsync(userModel);
return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Could not save, please try again" });
}
}
private async Task<Response> GetUserNotificationSettings()
{
var all = await UsersToNotifyRepo.GetAllAsync();
var retVal = all.FirstOrDefault(x => x.Username == Username);
return Response.AsJson(retVal != null);
}
private Response GetSeasons()
{
var tv = new TvMazeApi();
var seriesId = (int)Request.Query.tvId;
var show = tv.ShowLookupByTheTvDbId(seriesId);
var seasons = tv.GetSeasons(show.id);
var model = seasons.Select(x => x.number);
return Response.AsJson(model);
}
9 years ago
}
}