private void GenerateTvHtml(List <RecentlyAddedChild> tv, PlexSettings plexSettings, StringBuilder sb) { var orderedTv = tv.OrderByDescending(x => x?.addedAt.UnixTimeStampToDateTime()).ToList(); // TV sb.Append("<h1>New Episodes:</h1><br/><br/>"); sb.Append( "<table border=\"0\" cellpadding=\"0\" align=\"center\" cellspacing=\"0\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;\" width=\"100%\">"); foreach (var t in orderedTv) { var plexGUID = string.Empty; try { var parentMetaData = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, t.parentRatingKey.ToString()); plexGUID = parentMetaData.Directory.Guid; var info = TvApi.ShowLookupByTheTvDbId(int.Parse(PlexHelper.GetProviderIdFromPlexGuid(plexGUID))); var banner = info.image?.original; if (!string.IsNullOrEmpty(banner)) { banner = banner.Replace("http", "https"); // Always use the Https banners } AddImageInsideTable(sb, banner); sb.Append("<tr>"); sb.Append( "<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">"); var title = $"{t.grandparentTitle} - {t.title} {t.originallyAvailableAt?.Substring(0, 4)}"; Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/"); Header(sb, 3, title); EndTag(sb, "a"); AddParagraph(sb, $"Season: {t.parentIndex}, Episode: {t.index}"); if (info.genres.Any()) { AddParagraph(sb, $"Genre: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); } AddParagraph(sb, string.IsNullOrEmpty(t.summary) ? info.summary : t.summary); } catch (Exception e) { Log.Error(e); Log.Error( "Exception when trying to process a TV Show, either in getting the metadata from Plex OR getting the information from TVMaze, Plex GUID = {0}", plexGUID); } finally { EndLoopHtml(sb); } } sb.Append("</table><br/><br/>"); }
public async Task <SearchTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token) { var show = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid, async() => await TvMazeApi.ShowLookupByTheTvDbId(int.Parse(tvdbid)), DateTime.Now.AddHours(12)); if (show == null) { // We don't have enough information return(null); } var episodes = await Cache.GetOrAdd("TvMazeEpisodeLookup" + show.id, async() => await TvMazeApi.EpisodeLookup(show.id), DateTime.Now.AddHours(12)); if (episodes == null || !episodes.Any()) { // We don't have enough information return(null); } var mapped = Mapper.Map <SearchTvShowViewModel>(show); foreach (var e in episodes) { var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); if (season == null) { var newSeason = new SeasonRequests { SeasonNumber = e.season, Episodes = new List <EpisodeRequests>() }; newSeason.Episodes.Add(new EpisodeRequests { Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, }); mapped.SeasonRequests.Add(newSeason); } else { // We already have the season, so just add the episode season.Episodes.Add(new EpisodeRequests { Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, }); } } return(await ProcessResult(mapped, false)); }
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)); }
public async Task <SearchTvShowViewModel> GetShowInformation(int tvdbid) { var show = await TvMazeApi.ShowLookupByTheTvDbId(tvdbid); if (show == null) { // We don't have enough information return(null); } var episodes = await TvMazeApi.EpisodeLookup(show.id); if (episodes == null || !episodes.Any()) { // We don't have enough information return(null); } var mapped = Mapper.Map <SearchTvShowViewModel>(show); foreach (var e in episodes) { var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); if (season == null) { var newSeason = new SeasonRequests { SeasonNumber = e.season, Episodes = new List <EpisodeRequests>() }; newSeason.Episodes.Add(new EpisodeRequests { Url = e.url, Title = e.name, AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, }); mapped.SeasonRequests.Add(newSeason); } else { // We already have the season, so just add the episode season.Episodes.Add(new EpisodeRequests { Url = e.url, Title = e.name, AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, }); } } return(await ProcessResult(mapped)); }
/// <summary> /// Requests the tv show. /// </summary> /// <param name="showId">The show identifier.</param> /// <param name="seasons">The seasons.</param> /// <param name="notify">if set to <c>true</c> [notify].</param> /// <returns></returns> private Response RequestTvShow(int showId, string seasons) { 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 = PrService.GetSettings(); // check if the show has already been requested Log.Info("Requesting tv show with id {0}", showId); var existingRequest = RequestService.CheckRequest(showId); if (existingRequest != null) { // check if the current user is already marked as a requester for this show, if not, add them if (!existingRequest.UserHasRequested(Username)) { existingRequest.RequestedUsers.Add(Username); RequestService.UpdateRequest(existingRequest); } return(Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullShowName} was successfully added!" : $"{fullShowName} has already been requested!" })); } try { var shows = Checker.GetPlexTvShows(); if (Checker.IsTvShowAvailable(shows.ToArray(), showInfo.name, showInfo.premiered?.Substring(0, 4))) { return(Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullShowName} is already in Plex!" })); } } catch (ApplicationSettingsException) { 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, SeasonCount = showInfo.seasonCount }; var seasonsList = new List <int>(); switch (seasons) { case "first": seasonsList.Add(1); model.SeasonsRequested = "First"; break; case "latest": seasonsList.Add(model.SeasonCount); model.SeasonsRequested = "Latest"; break; case "all": model.SeasonsRequested = "All"; break; default: 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; } model.SeasonList = seasonsList.ToArray(); if (ShouldAutoApprove(RequestType.TvShow, settings)) { var sonarrSettings = SonarrService.GetSettings(); var sender = new TvSender(SonarrApi, SickrageApi); if (sonarrSettings.Enabled) { var result = sender.SendToSonarr(sonarrSettings, model); if (result != null && !string.IsNullOrEmpty(result.title)) { model.Approved = true; Log.Debug("Adding tv to database requests (No approval required & Sonarr)"); RequestService.AddRequest(model); if (ShouldSendNotification()) { var notify1 = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; 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)"); RequestService.AddRequest(model); if (ShouldSendNotification()) { var notify2 = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; 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." })); } return(Response.AsJson(new JsonResponseModel { Result = false, Message = "The request of TV Shows is not correctly set up. Please contact your admin." })); } RequestService.AddRequest(model); var notificationModel = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; NotificationService.Publish(notificationModel); return(Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" })); }
private async Task <Response> ReportNonRequestIssue(int providerId, string type, IssueState issue, string comment) { var currentIssues = await IssuesService.GetAllAsync(); var notifyModel = new NotificationModel { User = Username, NotificationType = NotificationType.Issue, DateTime = DateTime.Now, Body = issue == IssueState.Other ? comment : issue.ToString().ToCamelCaseWords() }; var model = new IssueModel { Issue = issue, UserReported = Username, UserNote = !string.IsNullOrEmpty(comment) ? $"{Username} - {comment}" : string.Empty, }; var existing = currentIssues.FirstOrDefault(x => x.ProviderId == providerId && !x.Deleted && x.IssueStatus == IssueStatus.PendingIssue); if (existing != null) { existing.Issues.Add(model); await IssuesService.UpdateIssueAsync(existing); return(Response.AsJson(new JsonResponseModel { Result = true })); } if (type == "movie") { var movieApi = new TheMovieDbApi(); var result = await movieApi.GetMovieInformation(providerId); if (result != null) { notifyModel.Title = result.Title; // New issue var issues = new IssuesModel { Title = result.Title, PosterUrl = "https://image.tmdb.org/t/p/w150/" + result.PosterPath, ProviderId = providerId, Type = RequestType.Movie, IssueStatus = IssueStatus.PendingIssue }; issues.Issues.Add(model); var issueId = await IssuesService.AddIssueAsync(issues); await NotificationService.Publish(notifyModel); return(Response.AsJson(new JsonResponseModel { Result = true })); } } if (type == "tv") { var tv = new TvMazeApi(); var result = tv.ShowLookupByTheTvDbId(providerId); if (result != null) { var banner = result.image?.medium; if (!string.IsNullOrEmpty(banner)) { banner = banner.Replace("http", "https"); } notifyModel.Title = result.name; // New issue var issues = new IssuesModel { Title = result.name, PosterUrl = banner, ProviderId = providerId, Type = RequestType.TvShow, IssueStatus = IssueStatus.PendingIssue }; issues.Issues.Add(model); var issueId = await IssuesService.AddIssueAsync(issues); await NotificationService.Publish(notifyModel); return(Response.AsJson(new JsonResponseModel { Result = true })); } } return(Response.AsJson(new JsonResponseModel { Result = false, Message = "Album Reports are not supported yet!" })); }
private void MigrateDbFrom1300() // TODO: Remove in v1.7 { var result = new List <long>(); RequestedModel[] requestedModels; var repo = new GenericRepository <RequestedModel>(Db, new MemoryCacheProvider()); try { var records = repo.GetAll(); requestedModels = records as RequestedModel[] ?? records.ToArray(); } catch (SqliteException) { // There is no requested table so they do not have an old version of the DB return; } if (!requestedModels.Any()) { return; } var jsonRepo = new JsonRequestService(new RequestJsonRepository(Db, new MemoryCacheProvider())); var api = new TvMazeApi(); foreach (var r in requestedModels.Where(x => x.Type == RequestType.TvShow)) { var show = api.ShowLookupByTheTvDbId(r.ProviderId); var model = new RequestedModel { Title = show.name, PosterPath = show.image?.medium, Type = RequestType.TvShow, ProviderId = show.externals.thetvdb ?? 0, ReleaseDate = r.ReleaseDate, AdminNote = r.AdminNote, Approved = r.Approved, Available = r.Available, ImdbId = show.externals.imdb, Issues = r.Issues, OtherMessage = r.OtherMessage, Overview = show.summary.RemoveHtml(), RequestedUsers = r.AllUsers, // should pull in the RequestedBy property and merge with RequestedUsers RequestedDate = r.ReleaseDate, Status = show.status }; var id = jsonRepo.AddRequest(model); result.Add(id); } foreach (var source in requestedModels.Where(x => x.Type == RequestType.Movie)) { var id = jsonRepo.AddRequest(source); result.Add(id); } if (result.Any(x => x == -1)) { throw new SqliteException("Could not migrate the DB!"); } if (result.Count != requestedModels.Length) { throw new SqliteException("Could not migrate the DB! count is different"); } // Now delete the old requests foreach (var oldRequest in requestedModels) { repo.Delete(oldRequest); } }