예제 #1
0
        public async Task TestIndexer(string name)
        {
            var indexer     = GetIndexer(name);
            var browseQuery = new TorznabQuery();
            var results     = await indexer.PerformQuery(browseQuery);

            results = indexer.CleanLinks(results);
            logger.Info(string.Format("Found {0} releases from {1}", results.Count(), indexer.DisplayName));
            if (results.Count() == 0)
            {
                throw new Exception("Found no results while trying to browse this tracker");
            }
            cacheService.CacheRssResults(indexer, results);
        }
예제 #2
0
        public async Task TestIndexer(string name)
        {
            var indexer     = GetIndexer(name);
            var browseQuery = new TorznabQuery();

            browseQuery.QueryType  = "search";
            browseQuery.SearchTerm = "";
            browseQuery.IsTest     = true;
            var result = await indexer.ResultsForQuery(browseQuery);

            logger.Info(string.Format("Found {0} releases from {1}", result.Releases.Count(), indexer.DisplayName));
            if (result.Releases.Count() == 0)
            {
                throw new Exception("Found no results while trying to browse this tracker");
            }
            cacheService.CacheRssResults(indexer, result.Releases);
        }
        public async Task TestIndexer(string name)
        {
            var indexer     = GetIndexer(name);
            var browseQuery = new TorznabQuery
            {
                QueryType  = "search",
                SearchTerm = "",
                IsTest     = true
            };
            var result = await indexer.ResultsForQuery(browseQuery);

            logger.Info($"Found {result.Releases.Count()} releases from {indexer.DisplayName}");
            if (!result.Releases.Any())
            {
                throw new Exception("Found no results while trying to browse this tracker");
            }
            cacheService.CacheRssResults(indexer, result.Releases);
        }
예제 #4
0
        public async Task <HttpResponseMessage> Call(string indexerID)
        {
            var indexer      = indexerService.GetIndexer(indexerID);
            var torznabQuery = TorznabQuery.FromHttpQuery(HttpUtility.ParseQueryString(Request.RequestUri.Query));

            if (string.Equals(torznabQuery.QueryType, "caps", StringComparison.InvariantCultureIgnoreCase))
            {
                return(new HttpResponseMessage()
                {
                    Content = new StringContent(indexer.TorznabCaps.ToXml(), Encoding.UTF8, "application/xml")
                });
            }

            torznabQuery.ExpandCatsToSubCats();
            var allowBadApiDueToDebug = false;

#if DEBUG
            allowBadApiDueToDebug = Debugger.IsAttached;
#endif

            if (!allowBadApiDueToDebug && !string.Equals(torznabQuery.ApiKey, serverService.Config.APIKey, StringComparison.InvariantCultureIgnoreCase))
            {
                logger.Warn(string.Format("A request from {0} was made with an incorrect API key.", Request.GetOwinContext().Request.RemoteIpAddress));
                return(Request.CreateResponse(HttpStatusCode.Forbidden, "Incorrect API key"));
            }

            if (!indexer.IsConfigured)
            {
                logger.Warn(string.Format("Rejected a request to {0} which is unconfigured.", indexer.DisplayName));
                return(Request.CreateResponse(HttpStatusCode.Forbidden, "This indexer is not configured."));
            }

            if (torznabQuery.ImdbID != null)
            {
                if (torznabQuery.QueryType != "movie")
                {
                    logger.Warn(string.Format("A non movie request with an imdbid was made from {0}.", Request.GetOwinContext().Request.RemoteIpAddress));
                    return(GetErrorXML(201, "Incorrect parameter: only movie-search supports the imdbid parameter"));
                }

                if (!string.IsNullOrEmpty(torznabQuery.SearchTerm))
                {
                    logger.Warn(string.Format("A movie-search request from {0} was made contining q and imdbid.", Request.GetOwinContext().Request.RemoteIpAddress));
                    return(GetErrorXML(201, "Incorrect parameter: please specify either imdbid or q"));
                }

                torznabQuery.ImdbID = ParseUtil.GetFullImdbID(torznabQuery.ImdbID); // normalize ImdbID
                if (torznabQuery.ImdbID == null)
                {
                    logger.Warn(string.Format("A movie-search request from {0} was made with an invalid imdbid.", Request.GetOwinContext().Request.RemoteIpAddress));
                    return(GetErrorXML(201, "Incorrect parameter: invalid imdbid format"));
                }

                if (!indexer.TorznabCaps.SupportsImdbSearch)
                {
                    logger.Warn(string.Format("A movie-search request with imdbid from {0} was made but the indexer {1} doesn't support it.", Request.GetOwinContext().Request.RemoteIpAddress, indexer.DisplayName));
                    return(GetErrorXML(203, "Function Not Available: imdbid is not supported by this indexer"));
                }
            }

            var releases = await indexer.PerformQuery(torznabQuery);

            releases = indexer.CleanLinks(releases);

            // Some trackers do not keep their clocks up to date and can be ~20 minutes out!
            foreach (var release in releases.Where(r => r.PublishDate > DateTime.Now))
            {
                release.PublishDate = DateTime.Now;
            }

            // Some trackers do not support multiple category filtering so filter the releases that match manually.
            var filteredReleases = releases = indexer.FilterResults(torznabQuery, releases);
            int?newItemCount     = null;

            // Cache non query results
            if (string.IsNullOrEmpty(torznabQuery.SanitizedSearchTerm))
            {
                newItemCount = cacheService.GetNewItemCount(indexer, filteredReleases);
                cacheService.CacheRssResults(indexer, releases);
            }

            // Log info
            var logBuilder = new StringBuilder();
            if (newItemCount != null)
            {
                logBuilder.AppendFormat(string.Format("Found {0} ({1} new) releases from {2}", releases.Count(), newItemCount, indexer.DisplayName));
            }
            else
            {
                logBuilder.AppendFormat(string.Format("Found {0} releases from {1}", releases.Count(), indexer.DisplayName));
            }

            if (!string.IsNullOrWhiteSpace(torznabQuery.SanitizedSearchTerm))
            {
                logBuilder.AppendFormat(" for: {0}", torznabQuery.GetQueryString());
            }

            logger.Info(logBuilder.ToString());

            var serverUrl  = string.Format("{0}://{1}:{2}{3}", Request.RequestUri.Scheme, Request.RequestUri.Host, Request.RequestUri.Port, serverService.BasePath());
            var resultPage = new ResultPage(new ChannelInfo
            {
                Title            = indexer.DisplayName,
                Description      = indexer.DisplayDescription,
                Link             = new Uri(indexer.SiteLink),
                ImageUrl         = new Uri(serverUrl + "logos/" + indexer.ID + ".png"),
                ImageTitle       = indexer.DisplayName,
                ImageLink        = new Uri(indexer.SiteLink),
                ImageDescription = indexer.DisplayName
            });


            foreach (var result in releases)
            {
                var clone = Mapper.Map <ReleaseInfo>(result);
                clone.Link = serverService.ConvertToProxyLink(clone.Link, serverUrl, indexerID, "dl", result.Title + ".torrent");
                resultPage.Releases.Add(clone);
            }

            var xml = resultPage.ToXml(new Uri(serverUrl));
            // Force the return as XML
            return(new HttpResponseMessage()
            {
                Content = new StringContent(xml, Encoding.UTF8, "application/rss+xml")
            });
        }
예제 #5
0
        public ManualSearchResult Search([FromBody] AdminSearch value)
        {
            var results = new List <TrackerCacheResult>();
            var query   = new TorznabQuery()
            {
                SearchTerm = value.Query,
                Categories = value.Category == 0 ? new int[0] : new int[1] {
                    value.Category
                }
            };

            query.ExpandCatsToSubCats();

            var trackers = indexerService.GetAllIndexers().Where(t => t.IsConfigured).ToList();

            if (!string.IsNullOrWhiteSpace(value.Tracker))
            {
                trackers = trackers.Where(t => t.ID == value.Tracker).ToList();
            }

            if (value.Category != 0)
            {
                trackers = trackers.Where(t => t.TorznabCaps.Categories.Select(c => c.ID).Contains(value.Category)).ToList();
            }

            Parallel.ForEach(trackers.ToList(), indexer =>
            {
                try
                {
                    var searchResults = indexer.PerformQuery(query).Result;
                    searchResults     = indexer.CleanLinks(searchResults);
                    cacheService.CacheRssResults(indexer, searchResults);
                    searchResults = indexer.FilterResults(query, searchResults);

                    lock (results)
                    {
                        foreach (var result in searchResults)
                        {
                            var item       = Mapper.Map <TrackerCacheResult>(result);
                            item.Tracker   = indexer.DisplayName;
                            item.TrackerId = indexer.ID;
                            item.Peers     = item.Peers - item.Seeders; // Use peers as leechers
                            results.Add(item);
                        }
                    }
                }
                catch (Exception e)
                {
                    logger.Error(e, "An error occured during manual search on " + indexer.DisplayName + ":  " + e.Message);
                }
            });

            ConfigureCacheResults(results);

            if (trackers.Count > 1)
            {
                results = results.OrderByDescending(d => d.PublishDate).ToList();
            }

            var manualResult = new ManualSearchResult()
            {
                Results  = results,
                Indexers = trackers.Select(t => t.DisplayName).ToList()
            };


            if (manualResult.Indexers.Count == 0)
            {
                manualResult.Indexers = new List <string>()
                {
                    "None"
                }
            }
            ;

            logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", query.GetQueryString(), string.Join(", ", manualResult.Indexers), manualResult.Results.Count));
            return(manualResult);
        }
    }
예제 #6
0
        public async Task <IActionResult> Results([FromQuery] ApiSearch requestt)
        {
            //TODO: Better way to parse querystring

            ApiSearch request = new ApiSearch();

            foreach (var t in Request.Query)
            {
                if (t.Key == "Tracker[]")
                {
                    request.Tracker = t.Value.ToString().Split(',');
                }

                if (t.Key == "Category[]")
                {
                    request.Category = t.Value.ToString().Split(',').Select(Int32.Parse).ToArray();
                }

                if (t.Key == "query")
                {
                    request.Query = t.Value.ToString();
                }
            }

            var manualResult = new ManualSearchResult();
            var trackers     = IndexerService.GetAllIndexers().ToList().Where(t => t.IsConfigured);

            if (request.Tracker != null)
            {
                trackers = trackers.Where(t => request.Tracker.Contains(t.ID));
            }

            trackers = trackers.Where(t => t.CanHandleQuery(CurrentQuery));

            var tasks = trackers.ToList().Select(t => t.ResultsForQuery(CurrentQuery)).ToList();

            try
            {
                var   aggregateTask = Task.WhenAll(tasks);
                await aggregateTask;
            }
            catch (AggregateException aex)
            {
                foreach (var ex in aex.InnerExceptions)
                {
                    logger.Error(ex);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }

            manualResult.Indexers = tasks.Select(t =>
            {
                var resultIndexer = new ManualSearchResultIndexer();
                IIndexer indexer  = null;
                if (t.Status == TaskStatus.RanToCompletion)
                {
                    resultIndexer.Status  = ManualSearchResultIndexerStatus.OK;
                    resultIndexer.Results = t.Result.Releases.Count();
                    resultIndexer.Error   = null;
                    indexer = t.Result.Indexer;
                }
                else if (t.Exception.InnerException is IndexerException)
                {
                    resultIndexer.Status  = ManualSearchResultIndexerStatus.Error;
                    resultIndexer.Results = 0;
                    resultIndexer.Error   = ((IndexerException)t.Exception.InnerException).ToString();
                    indexer = ((IndexerException)t.Exception.InnerException).Indexer;
                }
                else
                {
                    resultIndexer.Status  = ManualSearchResultIndexerStatus.Unknown;
                    resultIndexer.Results = 0;
                    resultIndexer.Error   = null;
                }

                if (indexer != null)
                {
                    resultIndexer.ID   = indexer.ID;
                    resultIndexer.Name = indexer.DisplayName;
                }
                return(resultIndexer);
            }).ToList();

            manualResult.Results = tasks.Where(t => t.Status == TaskStatus.RanToCompletion).Where(t => t.Result.Releases.Any()).SelectMany(t =>
            {
                var searchResults = t.Result.Releases;
                var indexer       = t.Result.Indexer;
                cacheService.CacheRssResults(indexer, searchResults);

                return(searchResults.Select(result =>
                {
                    var item = AutoMapper.Mapper.Map <TrackerCacheResult>(result);
                    item.Tracker = indexer.DisplayName;
                    item.TrackerId = indexer.ID;
                    item.Peers = item.Peers - item.Seeders; // Use peers as leechers

                    return item;
                }));
            }).OrderByDescending(d => d.PublishDate).ToList();

            ConfigureCacheResults(manualResult.Results);

            logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", CurrentQuery.SanitizedSearchTerm, string.Join(", ", manualResult.Indexers.Select(i => i.ID)), manualResult.Results.Count()));
            return(Json(manualResult));
        }
예제 #7
0
        public async Task <HttpResponseMessage> Call(string indexerID, [FromUri] TorrentPotatoRequest request)
        {
            var indexer = indexerService.GetIndexer(indexerID);

            var allowBadApiDueToDebug = false;

#if DEBUG
            allowBadApiDueToDebug = Debugger.IsAttached;
#endif

            if (!allowBadApiDueToDebug && !string.Equals(request.passkey, serverService.Config.APIKey, StringComparison.InvariantCultureIgnoreCase))
            {
                logger.Warn(string.Format("A request from {0} was made with an incorrect API key.", Request.GetOwinContext().Request.RemoteIpAddress));
                return(Request.CreateResponse(HttpStatusCode.Forbidden, "Incorrect API key"));
            }

            if (!indexer.IsConfigured)
            {
                logger.Warn(string.Format("Rejected a request to {0} which is unconfigured.", indexer.DisplayName));
                return(Request.CreateResponse(HttpStatusCode.Forbidden, "This indexer is not configured."));
            }

            if (!indexer.TorznabCaps.Categories.Select(c => c.ID).Any(i => MOVIE_CATS.Contains(i)))
            {
                logger.Warn(string.Format("Rejected a request to {0} which does not support searching for movies.", indexer.DisplayName));
                return(Request.CreateResponse(HttpStatusCode.Forbidden, "This indexer does not support movies."));
            }

            var year = 0;

            if (string.IsNullOrWhiteSpace(request.search))
            {
                // We are searching by IMDB id so look up the name
                var response = await webClient.GetString(new Utils.Clients.WebRequest("http://www.omdbapi.com/?type=movie&i=" + request.imdbid));

                if (response.Status == HttpStatusCode.OK)
                {
                    JObject result = JObject.Parse(response.Content);
                    if (result["Title"] != null)
                    {
                        request.search = result["Title"].ToString();
                        year           = ParseUtil.CoerceInt(result["Year"].ToString());
                    }
                }
            }

            var torznabQuery = new TorznabQuery()
            {
                ApiKey     = request.passkey,
                Categories = MOVIE_CATS,
                SearchTerm = request.search
            };

            IEnumerable <ReleaseInfo> releases = new List <ReleaseInfo>();

            if (!string.IsNullOrWhiteSpace(torznabQuery.SanitizedSearchTerm))
            {
                releases = await indexer.PerformQuery(torznabQuery);

                releases = indexer.CleanLinks(releases);
            }

            // Cache non query results
            if (string.IsNullOrEmpty(torznabQuery.SanitizedSearchTerm))
            {
                cacheService.CacheRssResults(indexer, releases);
            }

            releases = indexer.FilterResults(torznabQuery, releases);
            var serverUrl      = string.Format("{0}://{1}:{2}/", Request.RequestUri.Scheme, Request.RequestUri.Host, Request.RequestUri.Port);
            var potatoResponse = new TorrentPotatoResponse();

            releases = TorznabUtil.FilterResultsToTitle(releases, torznabQuery.SanitizedSearchTerm, year);
            releases = TorznabUtil.FilterResultsToImdb(releases, request.imdbid);

            foreach (var r in releases)
            {
                var release = Mapper.Map <ReleaseInfo>(r);
                release.Link = serverService.ConvertToProxyLink(release.Link, serverUrl, indexerID);

                // Only accept torrent links, magnet is not supported
                if (release.Link != null)
                {
                    potatoResponse.results.Add(new TorrentPotatoResponseItem()
                    {
                        release_name = release.Title + "[" + indexer.DisplayName + "]", // Suffix the indexer so we can see which tracker we are using in CPS as it just says torrentpotato >.>
                        torrent_id   = release.Guid.ToString(),
                        details_url  = release.Comments.ToString(),
                        download_url = release.Link.ToString(),
                        imdb_id      = release.Imdb.HasValue ? "tt" + release.Imdb : null,
                        freeleech    = false,
                        type         = "movie",
                        size         = (long)release.Size / (1024 * 1024), // This is in MB
                        leechers     = (int)release.Peers - (int)release.Seeders,
                        seeders      = (int)release.Seeders
                    });
                }
            }

            // Log info
            if (string.IsNullOrWhiteSpace(torznabQuery.SanitizedSearchTerm))
            {
                logger.Info(string.Format("Found {0} torrentpotato releases from {1}", releases.Count(), indexer.DisplayName));
            }
            else
            {
                logger.Info(string.Format("Found {0} torrentpotato releases from {1} for: {2}", releases.Count(), indexer.DisplayName, torznabQuery.GetQueryString()));
            }

            // Force the return as Json
            return(new HttpResponseMessage()
            {
                Content = new JsonContent(potatoResponse)
            });
        }
예제 #8
0
        public ManualSearchResult Search([FromBody] AdminSearch value)
        {
            var results     = new List <TrackerCacheResult>();
            var stringQuery = new TorznabQuery();

            var queryStr = value.Query;

            if (queryStr != null)
            {
                var seasonMatch = Regex.Match(queryStr, @"S(\d{2,4})");
                if (seasonMatch.Success)
                {
                    stringQuery.Season = int.Parse(seasonMatch.Groups[1].Value);
                    queryStr           = queryStr.Remove(seasonMatch.Index, seasonMatch.Length);
                }

                var episodeMatch = Regex.Match(queryStr, @"E(\d{2,4})");
                if (episodeMatch.Success)
                {
                    stringQuery.Episode = episodeMatch.Groups[1].Value;
                    queryStr            = queryStr.Remove(episodeMatch.Index, episodeMatch.Length);
                }
                queryStr = queryStr.Trim();
            }


            stringQuery.SearchTerm = queryStr;
            stringQuery.Categories = value.Category == 0 ? new int[0] : new int[1] {
                value.Category
            };
            stringQuery.ExpandCatsToSubCats();

            // try to build an IMDB Query
            var          imdbID    = ParseUtil.GetFullImdbID(stringQuery.SanitizedSearchTerm);
            TorznabQuery imdbQuery = null;

            if (imdbID != null)
            {
                imdbQuery = new TorznabQuery()
                {
                    ImdbID     = imdbID,
                    Categories = stringQuery.Categories,
                    Season     = stringQuery.Season,
                    Episode    = stringQuery.Episode,
                };
                imdbQuery.ExpandCatsToSubCats();
            }

            var trackers = indexerService.GetAllIndexers().Where(t => t.IsConfigured).ToList();

            if (!string.IsNullOrWhiteSpace(value.Tracker))
            {
                trackers = trackers.Where(t => t.ID == value.Tracker).ToList();
            }

            if (value.Category != 0)
            {
                trackers = trackers.Where(t => t.TorznabCaps.Categories.Select(c => c.ID).Contains(value.Category)).ToList();
            }

            Parallel.ForEach(trackers.ToList(), indexer =>
            {
                try
                {
                    var query = stringQuery;
                    // use imdb Query for trackers which support it
                    if (imdbQuery != null && indexer.TorznabCaps.SupportsImdbSearch)
                    {
                        query = imdbQuery;
                    }

                    var searchResults = indexer.PerformQuery(query).Result;
                    searchResults     = indexer.CleanLinks(searchResults);
                    cacheService.CacheRssResults(indexer, searchResults);
                    searchResults = indexer.FilterResults(query, searchResults);

                    lock (results)
                    {
                        foreach (var result in searchResults)
                        {
                            var item       = Mapper.Map <TrackerCacheResult>(result);
                            item.Tracker   = indexer.DisplayName;
                            item.TrackerId = indexer.ID;
                            item.Peers     = item.Peers - item.Seeders; // Use peers as leechers
                            results.Add(item);
                        }
                    }
                }
                catch (Exception e)
                {
                    logger.Error(e, "An error occured during manual search on " + indexer.DisplayName + ":  " + e.Message);
                }
            });

            ConfigureCacheResults(results);

            if (trackers.Count > 1)
            {
                results = results.OrderByDescending(d => d.PublishDate).ToList();
            }

            var manualResult = new ManualSearchResult()
            {
                Results  = results,
                Indexers = trackers.Select(t => t.DisplayName).ToList()
            };


            if (manualResult.Indexers.Count == 0)
            {
                manualResult.Indexers = new List <string>()
                {
                    "None"
                }
            }
            ;

            logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", stringQuery.GetQueryString(), string.Join(", ", manualResult.Indexers), manualResult.Results.Count));
            return(manualResult);
        }
    }