Esempio n. 1
0
        public async Task <IEnumerable <SearchTvShowViewModel> > Search(string searchTerm)
        {
            var searchResult = await TvMazeApi.Search(searchTerm);

            if (searchResult != null)
            {
                var retVal = new List <SearchTvShowViewModel>();
                foreach (var tvMazeSearch in searchResult)
                {
                    if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false))
                    {
                        continue;
                    }
                    var mappedResult = await ProcessResult(tvMazeSearch, false);

                    if (mappedResult == null)
                    {
                        continue;
                    }
                    retVal.Add(mappedResult);
                }
                return(retVal);
            }
            return(null);
        }
Esempio n. 2
0
        new public async Task <IEnumerable <SearchTvShowViewModel> > Search(string search)
        {
            var searchResult = await TvMazeApi.Search(search);

            for (var i = 0; i < searchResult.Count; i++)
            {
                if (!_demoLists.TvShows.Contains(searchResult[i].show?.externals?.thetvdb ?? 0))
                {
                    searchResult.RemoveAt(i);
                }
            }

            if (searchResult != null)
            {
                var retVal = new List <SearchTvShowViewModel>();
                foreach (var tvMazeSearch in searchResult)
                {
                    if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false))
                    {
                        continue;
                    }
                    retVal.Add(await ProcessResult(tvMazeSearch, false));
                }
                return(retVal);
            }
            return(null);
        }
Esempio n. 3
0
        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));
        }
Esempio n. 5
0
        public async Task <IEnumerable <SearchTvShowViewModel> > Search(string searchTerm)
        {
            var searchResult = await TvMazeApi.Search(searchTerm);

            if (searchResult != null)
            {
                return(await ProcessResults(searchResult));
            }
            return(null);
        }
Esempio n. 6
0
        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));
        }
Esempio n. 7
0
        private void ProcessMissingInformation(List <RequestQueue> requests)
        {
            if (!requests.Any())
            {
                return;
            }

            var sonarrSettings   = SonarrSettings.GetSettings();
            var sickrageSettings = SickrageSettings.GetSettings();

            var tv = requests.Where(x => x.Type == RequestType.TvShow);

            // TV
            var tvApi = new TvMazeApi();

            foreach (var t in tv)
            {
                var providerId = int.Parse(t.PrimaryIdentifier);
                var showInfo   = tvApi.ShowLookup(providerId);

                if (showInfo.externals?.thetvdb != null)
                {
                    // We now have the info
                    var tvModel = ByteConverterHelper.ReturnObject <RequestedModel>(t.Content);
                    tvModel.ProviderId = showInfo.externals.thetvdb.Value;
                    var result = ProcessTvShow(tvModel, sonarrSettings, sickrageSettings);

                    if (!result)
                    {
                        // we now have the info but couldn't add it, so add it back into the queue but with a different fault
                        t.Content   = ByteConverterHelper.ReturnBytes(tvModel);
                        t.FaultType = FaultType.RequestFault;
                        t.LastRetry = DateTime.UtcNow;
                        Repo.Update(t);
                    }
                    else
                    {
                        // Make sure it's been requested
                        var existingRequests = RequestService.GetAll();
                        var thisItem         = existingRequests.Any(x => x.Title.Equals(tvModel.Title));
                        if (!thisItem)
                        {
                            tvModel.Approved = true;
                            RequestService.AddRequest(tvModel);
                        }

                        // Successful, remove from the fault queue
                        Repo.Delete(t);
                    }
                }
            }
        }
Esempio n. 8
0
 public PlexRecentlyAddedNewsletter(IPlexApi api, ISettingsService <PlexSettings> plexSettings,
                                    ISettingsService <EmailNotificationSettings> email,
                                    ISettingsService <NewletterSettings> newsletter, IRepository <RecentlyAddedLog> log,
                                    IRepository <PlexContent> embyContent, IRepository <PlexEpisodes> episodes)
 {
     Api                = api;
     PlexSettings       = plexSettings;
     EmailSettings      = email;
     NewsletterSettings = newsletter;
     Content            = embyContent;
     MovieApi           = new TheMovieDbApi();
     TvApi              = new TvMazeApi();
     Episodes           = episodes;
     RecentlyAddedLog   = log;
 }
Esempio n. 9
0
        public async Task IntegratieTest()
        {
            var client  = new HttpClient();
            var storage = new Storage();
            var api     = new TvMazeApi(client, storage);
            await api.StoreShows();

            var query = new GetShowsQuery()
            {
                Page = 1
            };
            var shows = await storage.GetShows(query);

            Assert.NotNull(shows);
            Assert.True(shows.Shows.Length == 10);
        }
Esempio n. 10
0
        public void CheckForUpdates()
        {
            this._logger.LogDebug(message: "Checking tv maze updates..");
            var api = new TvMazeApi(settings: this._settings);
            // in each iteration begin with getting the timestamps of all tvshows in the db.
            // https://www.tvmaze.com/api#updates
            var result = api.GetUpdates();

            // Then consider rate limiting
            // https://www.tvmaze.com/api#rate-limiting
            // Instead of rate limiting directly the execute function of TvMazeApi class, we use rate limiting here to avoid redis timeout failure because of the Parallel foreach.
            //  redis repository could be implemented  to work with bench operations, just didn't want to postpone the actual operation.
            // Rate limit is currently 20 calls in 10 seconds, the RateGate component is chosen because it uses SemaphoreSlim to optimize the call rate with the execution time.
            using (var rateGate = new RateGate(occurrences: this._settings.RateLimitOccurrences,
                                               timeUnit: TimeSpan.FromSeconds(value: this._settings.RateLimitSeconds)))
            {
                // Run a loop for every update in the tv maze database
                // we dont need more thread to start, then wait in the semaphore queue. So we use MaxDegreeOfParallelism property.
                Parallel.ForEach(source: result, parallelOptions: new ParallelOptions
                {
                    MaxDegreeOfParallelism = this._settings.RateLimitOccurrences
                },
                                 body: currentElement =>
                {
                    // Wait for the rate limit...
                    rateGate.WaitToProceed();
                    // check for the timestamp recently obtained matches the value in the redis cache.
                    var isValid = this._repository.IsConcurrencyValueValid(value: currentElement);
                    if (!isValid)
                    {
                        //  if not, get the show details from api,
                        // https://www.tvmaze.com/api#shows
                        var updated = api.GetShowDetail(showId: currentElement.Key);

                        // Create Integration Event to be published through the Event Bus
                        var showUpdatedEvent = new ShowUpdatedIntegrationEvent(payload: updated);
                        // Publish the event so the other projects may know about this change.
                        this._eventBus.Publish(@event: showUpdatedEvent);
                    }
                });
            }
        }
Esempio n. 11
0
        public async Task <IEnumerable <SearchTvShowViewModel> > NowPlayingMovies()
        {
            var rand      = new Random();
            var responses = new List <SearchTvShowViewModel>();

            for (int i = 0; i < 10; i++)
            {
                var item = rand.Next(_demoLists.TvShows.Length);
                var tv   = _demoLists.TvShows[item];
                if (responses.Any(x => x.Id == tv))
                {
                    i--;
                    continue;
                }

                var movieResult = await TvMazeApi.ShowLookup(tv);

                responses.Add(await ProcessResult(movieResult, false));
            }

            return(responses);
        }
        /// <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!"
            }));
        }
Esempio n. 13
0
        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!"
            }));
        }
Esempio n. 14
0
        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);
            }
        }