diff --git a/src/Jackett/Content/logos/danishbits.PNG b/src/Jackett/Content/logos/danishbits.PNG new file mode 100644 index 000000000..e2b7c372f Binary files /dev/null and b/src/Jackett/Content/logos/danishbits.PNG differ diff --git a/src/Jackett/Controllers/AdminController.cs b/src/Jackett/Controllers/AdminController.cs index b65eb6485..0fda24052 100644 --- a/src/Jackett/Controllers/AdminController.cs +++ b/src/Jackett/Controllers/AdminController.cs @@ -425,7 +425,7 @@ namespace Jackett.Controllers foreach (var result in results) { var link = result.Link; - result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId); + result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "dl", result.Title + ".torrent"); if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(Engine.Server.Config.BlackholeDir)) result.BlackholeLink = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "bh", string.Empty); diff --git a/src/Jackett/Controllers/DownloadController.cs b/src/Jackett/Controllers/DownloadController.cs index ee3e8373d..e3cdc9686 100644 --- a/src/Jackett/Controllers/DownloadController.cs +++ b/src/Jackett/Controllers/DownloadController.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Http; +using MonoTorrent.BEncoding; namespace Jackett.Controllers { @@ -29,7 +30,7 @@ namespace Jackett.Controllers } [HttpGet] - public async Task Download(string indexerID, string path, string apikey) + public async Task Download(string indexerID, string path, string apikey, string file) { try { @@ -51,9 +52,17 @@ namespace Jackett.Controllers var downloadBytes = await indexer.Download(target); + // This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr. + var torrentDictionary = BEncodedDictionary.DecodeTorrent(downloadBytes); + downloadBytes = torrentDictionary.Encode(); + var result = new HttpResponseMessage(HttpStatusCode.OK); result.Content = new ByteArrayContent(downloadBytes); result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-bittorrent"); + result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") + { + FileName = file + }; return result; } catch (Exception e) diff --git a/src/Jackett/Controllers/PotatoController.cs b/src/Jackett/Controllers/PotatoController.cs index e10662652..86992829c 100644 --- a/src/Jackett/Controllers/PotatoController.cs +++ b/src/Jackett/Controllers/PotatoController.cs @@ -126,7 +126,7 @@ namespace Jackett.Controllers foreach (var r in releases) { var release = Mapper.Map(r); - release.Link = serverService.ConvertToProxyLink(release.Link, serverUrl, indexerID); + release.Link = serverService.ConvertToProxyLink(release.Link, serverUrl, indexerID, "dl", release.Title + ".torrent"); // Only accept torrent links, magnet is not supported if (release.Link != null) diff --git a/src/Jackett/Controllers/TorznabController.cs b/src/Jackett/Controllers/TorznabController.cs index aa5d25671..225066d16 100644 --- a/src/Jackett/Controllers/TorznabController.cs +++ b/src/Jackett/Controllers/TorznabController.cs @@ -116,7 +116,7 @@ namespace Jackett.Controllers foreach(var result in releases) { var clone = Mapper.Map(result); - clone.Link = serverService.ConvertToProxyLink(clone.Link, serverUrl, indexerID); + clone.Link = serverService.ConvertToProxyLink(clone.Link, serverUrl, indexerID, "dl", result.Title + ".torrent"); resultPage.Releases.Add(clone); } diff --git a/src/Jackett/Indexers/DanishBits.cs b/src/Jackett/Indexers/DanishBits.cs new file mode 100644 index 000000000..bb1b9485c --- /dev/null +++ b/src/Jackett/Indexers/DanishBits.cs @@ -0,0 +1,291 @@ +using CsQuery; +using Jackett.Indexers; +using Jackett.Models; +using Jackett.Services; +using Jackett.Utils; +using Jackett.Utils.Clients; +using Newtonsoft.Json.Linq; +using NLog; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web; +using System.Web.UI.WebControls; +using CsQuery.ExtensionMethods; +using Jackett.Models.IndexerConfig; + +namespace Jackett.Indexers +{ + public class DanishBits : BaseIndexer, IIndexer + { + private string LoginUrl { get { return SiteLink + "login.php"; } } + private string SearchUrl { get { return SiteLink + "torrents.php"; } } + + new NxtGnConfigurationData configData + { + get { return (NxtGnConfigurationData)base.configData; } + set { base.configData = value; } + } + + public DanishBits(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps) + : base(name: "DanishBits", + description: "A danish closed torrent tracker", + link: "https://danishbits.org/", + caps: TorznabUtil.CreateDefaultTorznabTVCaps(), + manager: i, + client: c, + logger: l, + p: ps, + configData: new NxtGnConfigurationData()) + { + // Movies Mapping + // DanishBits HD + AddCategoryMapping(2, TorznabCatType.MoviesHD); + AddCategoryMapping(2, TorznabCatType.MoviesWEBDL); + + // Danske film + AddCategoryMapping(3, TorznabCatType.MoviesHD); + AddCategoryMapping(3, TorznabCatType.MoviesWEBDL); + AddCategoryMapping(3, TorznabCatType.MoviesDVD); + AddCategoryMapping(3, TorznabCatType.MoviesForeign); + AddCategoryMapping(3, TorznabCatType.MoviesSD); + + // DVDR Nordic + AddCategoryMapping(10, TorznabCatType.MoviesDVD); + AddCategoryMapping(10, TorznabCatType.MoviesForeign); + + // Custom + AddCategoryMapping(28, TorznabCatType.MoviesHD); + AddCategoryMapping(28, TorznabCatType.MoviesDVD); + + // Custom HD + AddCategoryMapping(29, TorznabCatType.MoviesHD); + AddCategoryMapping(29, TorznabCatType.MoviesWEBDL); + + // Custom Tablet + AddCategoryMapping(31, TorznabCatType.MoviesSD); + + if (!configData.OnlyDanishCategories.Value) + { + // Bluray + AddCategoryMapping(8, TorznabCatType.MoviesBluRay); + + // Boxset + AddCategoryMapping(9, TorznabCatType.MoviesHD); + AddCategoryMapping(9, TorznabCatType.MoviesForeign); + AddCategoryMapping(9, TorznabCatType.MoviesDVD); + + // DVDR + AddCategoryMapping(11, TorznabCatType.MoviesDVD); + + // HDx264 + AddCategoryMapping(22, TorznabCatType.MoviesHD); + + // XviD/MP4/SDx264 + AddCategoryMapping(24, TorznabCatType.MoviesSD); + } + + // TV Mapping + // DanishBits TV + AddCategoryMapping(1, TorznabCatType.TVHD); + AddCategoryMapping(1, TorznabCatType.TVWEBDL); + + // Dansk TV + AddCategoryMapping(4, TorznabCatType.TVHD); + AddCategoryMapping(4, TorznabCatType.TVWEBDL); + AddCategoryMapping(4, TorznabCatType.TVFOREIGN); + AddCategoryMapping(4, TorznabCatType.TVSD); + + // Custom TV + AddCategoryMapping(30, TorznabCatType.TVHD); + AddCategoryMapping(30, TorznabCatType.TVWEBDL); + + if (!configData.OnlyDanishCategories.Value) + { + // TV + AddCategoryMapping(20, TorznabCatType.TVHD); + AddCategoryMapping(20, TorznabCatType.TVSD); + AddCategoryMapping(20, TorznabCatType.TVWEBDL); + + // TV Boxset + AddCategoryMapping(21, TorznabCatType.TVHD); + AddCategoryMapping(21, TorznabCatType.TVSD); + AddCategoryMapping(21, TorznabCatType.TVWEBDL); + } + + // E-book + AddCategoryMapping(12, TorznabCatType.BooksEbook); + // Audiobooks + AddCategoryMapping(6, TorznabCatType.AudioAudiobook); + } + + public async Task ApplyConfiguration(JToken configJson) + { + configData.LoadValuesFromJson(configJson); + var pairs = new Dictionary { + { "username", configData.Username.Value }, + { "password", configData.Password.Value }, + { "langlang", null }, + { "login", "login" } + }; + // Get inital cookies + CookieHeader = string.Empty; + var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, CookieHeader, true, null, LoginUrl); + + await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("logout.php"), () => + { + CQ dom = response.Content; + var messageEl = dom["#loginform .warning"]; + var errorMessage = messageEl.Text().Trim(); + throw new ExceptionWithConfigData(errorMessage, configData); + }); + return IndexerConfigurationStatus.RequiresTesting; + } + + public async Task> PerformQuery(TorznabQuery query) + { + var releasesPerPage = 100; + var releases = new List(); + + var page = (query.Offset/releasesPerPage) + 1; + + string episodeSearchUrl; + if (string.IsNullOrEmpty(query.GetQueryString())) + { + episodeSearchUrl = SearchUrl + "?page=" + page; + } + else + { + var cats = MapTorznabCapsToTrackers(query); + var catsUrlPart = string.Join("&", cats.Select(c => $"filter_{c}=on")); + episodeSearchUrl = $"{SearchUrl}?page={page}&group=0&{catsUrlPart}&search={HttpUtility.UrlEncode(query.GetQueryString())}&pre_type=torrents&type="; + } + var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); + if (string.IsNullOrEmpty(results.Content)) + { + CookieHeader = string.Empty; + var pairs = new Dictionary + { + {"username", configData.Username.Value}, + {"password", configData.Password.Value}, + {"langlang", null}, + {"login", "login"} + }; + var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, CookieHeader, true, null, LoginUrl); + + await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("logout.php"), () => + { + CQ dom = response.Content; + var messageEl = dom["#loginform .warning"]; + var errorMessage = messageEl.Text().Trim(); + throw new ExceptionWithConfigData(errorMessage, configData); + }); + results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); + } + try + { + CQ dom = results.Content; + var rows = dom["#torrent_table tr.torrent"]; + foreach (var row in rows) + { + var qRow = row.Cq(); + var release = new ReleaseInfo + { + MinimumRatio = 1, + MinimumSeedTime = 172800 + }; + + var catAnchor = row.FirstChild.FirstChild; + var catUrl = catAnchor.GetAttribute("href"); + var catStr = Regex.Match(catUrl, "filter_(?[0-9]+)=on").Groups["catNo"].Value; + var catNo = int.Parse(catStr); + var moviesCatsDanish = new[] { 2,3,10,28,29,31 }; + var moviesCatsIntl = new[] { 8,9,11,22,24 }; + var moviesCats = configData.OnlyDanishCategories.Value + ? moviesCatsDanish + : moviesCatsDanish.Concat(moviesCatsIntl); + var seriesCatsDanish = new[] { 1,4,30 }; + var seriesCatsIntl = new[] { 20,21 }; + var seriesCats = configData.OnlyDanishCategories.Value + ? seriesCatsDanish + : seriesCatsDanish.Concat(seriesCatsIntl); + if (moviesCats.Contains(catNo)) + release.Category = TorznabCatType.Movies.ID; + else if (seriesCats.Contains(catNo)) + release.Category = TorznabCatType.TV.ID; + else if (catNo == 12) + release.Category = TorznabCatType.BooksEbook.ID; + else if (catNo == 6) + release.Category = TorznabCatType.AudioAudiobook.ID; + else + continue; + + var titleAnchor = qRow.Find("div.croptorrenttext a").FirstElement(); + var title = titleAnchor.GetAttribute("title"); + release.Title = title; + + var dlUrlAnchor = qRow.Find("span.right a").FirstElement(); + var dlUrl = dlUrlAnchor.GetAttribute("href"); + var authkey = Regex.Match(dlUrl, "authkey=(?[0-9a-zA-Z]+)").Groups["authkey"].Value; + var torrentPass = Regex.Match(dlUrl, "torrent_pass=(?[0-9a-zA-Z]+)").Groups["torrent_pass"].Value; + var torrentId = Regex.Match(dlUrl, "id=(?[0-9]+)").Groups["id"].Value; + release.Link = new Uri($"{SearchUrl}/{title}.torrent/?action=download&authkey={authkey}&torrent_pass={torrentPass}&id={torrentId}"); + + var torrentLink = titleAnchor.GetAttribute("href"); + release.Guid = new Uri(SiteLink + torrentLink); + release.Comments = new Uri(SearchUrl + torrentLink); + + var addedElement = qRow.Find("span.time").FirstElement(); + var addedStr = addedElement.GetAttribute("title"); + release.PublishDate = DateTime.ParseExact(addedStr, "MMM dd yyyy, HH:mm", + CultureInfo.InvariantCulture); + + var columns = qRow.Children(); + var seedersElement = columns.Reverse().Skip(1).First(); + release.Seeders = int.Parse(seedersElement.InnerText); + + var leechersElement = columns.Last().FirstElement(); + release.Peers = release.Seeders + int.Parse(leechersElement.InnerText); + + var sizeElement = columns.Skip(2).First(); + var sizeStr = sizeElement.InnerText; + release.Size = ReleaseInfo.GetBytes(sizeStr); + + var imdbAnchor = qRow.Find(".torrentnotes a") + .FirstOrDefault(a => a.GetAttribute("href").Contains("imdb.com")); + if (imdbAnchor != null) + { + var referrerUrl = imdbAnchor.GetAttribute("href"); + release.Imdb = long.Parse(Regex.Match(referrerUrl, "tt(?[0-9]+)").Groups["imdbId"].Value); + } + releases.Add(release); + } + } + catch (Exception ex) + { + OnParseError(results.Content, ex); + } + return releases; + } + + public class NxtGnConfigurationData : ConfigurationData + { + public NxtGnConfigurationData() + { + Username = new StringItem { Name = "Username" }; + Password = new StringItem { Name = "Password" }; + OnlyDanishCategories = new BoolItem { Name = "Only Danish Categories" }; + } + public StringItem Username { get; private set; } + public StringItem Password { get; private set; } + public BoolItem OnlyDanishCategories { get; private set; } + } + } +} diff --git a/src/Jackett/Indexers/NxtGn.cs b/src/Jackett/Indexers/NxtGn.cs index 899014885..872d50210 100644 --- a/src/Jackett/Indexers/NxtGn.cs +++ b/src/Jackett/Indexers/NxtGn.cs @@ -17,6 +17,7 @@ using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.UI.WebControls; +using CsQuery.ExtensionMethods; using Jackett.Models.IndexerConfig; namespace Jackett.Indexers @@ -27,65 +28,78 @@ namespace Jackett.Indexers private string SearchUrl { get { return SiteLink + "browse.php"; } } private string ProfileUrl { get { return SiteLink + "my.php"; } } - new ConfigurationDataBasicLoginWithRSS configData + new NxtGnConfigurationData configData { - get { return (ConfigurationDataBasicLoginWithRSS)base.configData; } + get { return (NxtGnConfigurationData)base.configData; } set { base.configData = value; } } public NxtGn(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps) : base(name: "NextGen", description: "A danish closed torrent tracker", - link: "https://nxtgn.info/", + link: "https://nxtgn.biz/", caps: TorznabUtil.CreateDefaultTorznabTVCaps(), manager: i, client: c, logger: l, p: ps, - configData: new ConfigurationDataBasicLoginWithRSS()) + configData: new NxtGnConfigurationData()) { //Movies Mapping - AddCategoryMapping(9, TorznabCatType.MoviesHD); - AddCategoryMapping(9, TorznabCatType.Movies); - AddCategoryMapping(9, TorznabCatType.MoviesBluRay); - AddCategoryMapping(47, TorznabCatType.Movies3D); + AddCategoryMapping(38, TorznabCatType.MoviesHD); AddCategoryMapping(38, TorznabCatType.MoviesWEBDL); AddCategoryMapping(38, TorznabCatType.MoviesBluRay); - AddCategoryMapping(5, TorznabCatType.MoviesSD); AddCategoryMapping(23, TorznabCatType.MoviesForeign); AddCategoryMapping(22, TorznabCatType.MoviesSD); AddCategoryMapping(33, TorznabCatType.MoviesHD); AddCategoryMapping(33, TorznabCatType.Movies); AddCategoryMapping(17, TorznabCatType.MoviesForeign); AddCategoryMapping(17, TorznabCatType.MoviesDVD); + if (!configData.OnlyDanishCategories.Value) + { + AddCategoryMapping(9, TorznabCatType.MoviesHD); + AddCategoryMapping(9, TorznabCatType.Movies); + AddCategoryMapping(9, TorznabCatType.MoviesBluRay); + AddCategoryMapping(47, TorznabCatType.Movies3D); + AddCategoryMapping(5, TorznabCatType.MoviesSD); + } //TV Mapping - //Category 4: TV (Working) - AddCategoryMapping(4, TorznabCatType.TVSD); - AddCategoryMapping(4, TorznabCatType.TV); - AddCategoryMapping(4, TorznabCatType.TVHD); - //Category 21: Boxset/SD (Working) - AddCategoryMapping(21, TorznabCatType.TVFOREIGN); - //Category 24: Boxsets/TV (Working) - AddCategoryMapping(24, TorznabCatType.TVFOREIGN); //Category 26: NG Serier WEB-DL (Working) AddCategoryMapping(26, TorznabCatType.TVHD); AddCategoryMapping(26, TorznabCatType.TV); AddCategoryMapping(26, TorznabCatType.TVWEBDL); - //Category 31: TVHD (Working) - AddCategoryMapping(31, TorznabCatType.TVHD); - AddCategoryMapping(31, TorznabCatType.TV); //Category 43: NG WWW HD (Working) AddCategoryMapping(43, TorznabCatType.TVHD); AddCategoryMapping(43, TorznabCatType.TV); AddCategoryMapping(43, TorznabCatType.TVWEBDL); - //Category 45: TV-Misc (Working) - AddCategoryMapping(45, TorznabCatType.TV); - AddCategoryMapping(45, TorznabCatType.TVSD); //Category 46: NG Serier HDTV (Working) AddCategoryMapping(46, TorznabCatType.TVHD); AddCategoryMapping(46, TorznabCatType.TV); + if (!configData.OnlyDanishCategories.Value) + { + //Category 4: TV (Working) + AddCategoryMapping(4, TorznabCatType.TVSD); + AddCategoryMapping(4, TorznabCatType.TV); + AddCategoryMapping(4, TorznabCatType.TVHD); + //Category 21: Boxset/SD (Working) + AddCategoryMapping(21, TorznabCatType.TVFOREIGN); + //Category 24: Boxsets/TV (Working) + AddCategoryMapping(24, TorznabCatType.TVFOREIGN); + //Category 31: TVHD (Working) + AddCategoryMapping(31, TorznabCatType.TVHD); + AddCategoryMapping(31, TorznabCatType.TV); + //Category 45: TV-Misc (Working) + AddCategoryMapping(45, TorznabCatType.TV); + AddCategoryMapping(45, TorznabCatType.TVSD); + } + + // Audio Books + AddCategoryMapping(37, TorznabCatType.AudioAudiobook); + + // Books + AddCategoryMapping(8, TorznabCatType.BooksEbook); } public async Task ApplyConfiguration(JToken configJson) @@ -117,107 +131,121 @@ namespace Jackett.Indexers passKey = passKey.Substring(0, passKey.IndexOf(' ')); configData.RSSKey.Value = passKey; SaveConfig(); - return IndexerConfigurationStatus.RequiresTesting; + return IndexerConfigurationStatus.Completed; } public async Task> PerformQuery(TorznabQuery query) { + var releasesPerPage = 100; var releases = new List(); - var breakWhile = false; - var page = 0; - while (page < 3) + var page = (query.Offset / releasesPerPage); + string episodeSearchUrl; + if (string.IsNullOrEmpty(query.GetQueryString())) { - string episodeSearchUrl; - if (string.IsNullOrEmpty(query.GetQueryString())) - { - episodeSearchUrl = SearchUrl + "?page=" + page; - breakWhile = true; - } - else - { - var cats = MapTorznabCapsToTrackers(query); - var catsUrlPart = string.Join("&", cats.Select(c => $"c{c}=1")); - episodeSearchUrl = string.Format("{0}?search={1}&cat=0&incldead=0&{2}&page={3}", SearchUrl, HttpUtility.UrlEncode(query.GetQueryString()), catsUrlPart, page); - } - page++; - var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); - try - { - CQ dom = results.Content; + episodeSearchUrl = SearchUrl + "?page=" + page; + } + else + { + var cats = MapTorznabCapsToTrackers(query); + var catsUrlPart = string.Join("&", cats.Select(c => $"c{c}=1")); + episodeSearchUrl = string.Format("{0}?search={1}&cat=0&incldead=0&{2}&page={3}", SearchUrl, HttpUtility.UrlEncode(query.GetQueryString()), catsUrlPart, page); + } + var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); + try + { + CQ dom = results.Content; - var rows = dom["#torrent-table-wrapper > div"]; + var rows = dom["#torrent-table-wrapper > div"]; - foreach (var row in rows.Skip(1)) + foreach (var row in rows.Skip(1)) + { + var release = new ReleaseInfo(); + + var qRow = row.Cq(); + var qLink = qRow.Find("#torrent-udgivelse2-users > a").First(); + var qDesc = qRow.Find("#torrent-udgivelse2-users > p").FirstOrDefault(); + + + var moviesCatsDanish = new[] { 38, 23, 22, 33, 17 }; + var moviesCatsIntl = new[] { 47, 5, 9 }; + var moviesCats = configData.OnlyDanishCategories.Value + ? moviesCatsDanish + : moviesCatsDanish.Concat(moviesCatsIntl); + var seriesCatsDanish = new[] { 26, 43, 46 }; + var seriesCatsIntl = new[] { 4, 21, 24, 31, 45 }; + var seriesCats = configData.OnlyDanishCategories.Value + ? seriesCatsDanish + : seriesCatsDanish.Concat(seriesCatsIntl); + var catUrl = qRow.Find(".torrent-icon > a").Attr("href"); + var cat = catUrl.Substring(catUrl.LastIndexOf('=') + 1); + var catNo = int.Parse(cat); + if (moviesCats.Contains(catNo)) + release.Category = TorznabCatType.Movies.ID; + else if (seriesCats.Contains(catNo)) + release.Category = TorznabCatType.TV.ID; + else + continue; + + releases.Add(release); + + var torrentUrl = qLink.Attr("href"); + var torrentId = torrentUrl.Substring(torrentUrl.LastIndexOf('=') + 1); + + release.MinimumRatio = 1; + release.MinimumSeedTime = 172800; + release.Title = qLink.Attr("title"); + release.Description = qDesc != null ? qDesc.InnerText : release.Title; + release.Guid = new Uri(SiteLink + torrentUrl); + release.Comments = new Uri(release.Guid + "#startcomments"); + + var downloadUrl = $"{SiteLink}download.php?id={torrentId}&rss&passkey={configData.RSSKey.Value}"; + release.Link = new Uri(downloadUrl); + + var qAdded = qRow.Find("#torrent-added").First(); + var addedStr = qAdded.Text().Trim(); + release.PublishDate = DateTime.ParseExact(addedStr, "dd-MM-yyyyHH:mm:ss", CultureInfo.InvariantCulture); + + release.Seeders = ParseUtil.CoerceInt(qRow.Find("#torrent-seeders").Text().Trim()); + release.Peers = ParseUtil.CoerceInt(qRow.Find("#torrent-leechers").Text().Trim()) + release.Seeders; + + var sizeStr = qRow.Find("#torrent-size").First().Text(); + release.Size = ReleaseInfo.GetBytes(sizeStr); + + var infoLink = qRow.Find("#infolink"); + var linkContainer = infoLink.Children().First().Children().First(); + var url = linkContainer.Attr("href"); + var img = linkContainer.Children().First(); + var imgUrl = img.Attr("src"); + if (imgUrl == "/pic/imdb.png") { - var release = new ReleaseInfo(); - - var qRow = row.Cq(); - var qLink = qRow.Find("#torrent-udgivelse2-users > a").First(); - var qDesc = qRow.Find("#torrent-udgivelse2-users > p").FirstOrDefault(); - - var moviesCats = new[] { 47, 38, 5, 23, 22, 33, 17, 9 }; - var seriesCats = new[] { 4, 21, 24, 26, 31, 43, 45, 46 }; - var catUrl = qRow.Find(".torrent-icon > a").Attr("href"); - var cat = catUrl.Substring(catUrl.LastIndexOf('=') + 1); - var catNo = int.Parse(cat); - if (moviesCats.Contains(catNo)) - release.Category = TorznabCatType.Movies.ID; - else if (seriesCats.Contains(catNo)) - release.Category = TorznabCatType.TV.ID; - else - continue; - - releases.Add(release); - - var torrentUrl = qLink.Attr("href"); - var torrentId = torrentUrl.Substring(torrentUrl.LastIndexOf('=') + 1); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - release.Title = qLink.Attr("title"); - release.Description = qDesc != null ? qDesc.InnerText : release.Title; - release.Guid = new Uri(SiteLink + torrentUrl); - release.Comments = new Uri(release.Guid + "#startcomments"); - - var downloadUrl = $"{SiteLink}download.php?id={torrentId}&rss&passkey={configData.RSSKey.Value}"; - release.Link = new Uri(downloadUrl); - - var qAdded = qRow.Find("#torrent-added").First(); - var addedStr = qAdded.Text().Trim(); - release.PublishDate = DateTime.ParseExact(addedStr, "dd-MM-yyyyHH:mm:ss", CultureInfo.InvariantCulture); - - release.Seeders = ParseUtil.CoerceInt(qRow.Find("#torrent-seeders").Text().Trim()); - release.Peers = ParseUtil.CoerceInt(qRow.Find("#torrent-leechers").Text().Trim()) + release.Seeders; - - var sizeStr = qRow.Find("#torrent-size").First().Text(); - release.Size = ReleaseInfo.GetBytes(sizeStr); - - var infoLink = qRow.Find("#infolink"); - var linkContainer = infoLink.Children().First().Children().First(); - var url = linkContainer.Attr("href"); - var img = linkContainer.Children().First(); - var imgUrl = img.Attr("src"); - if (imgUrl == "/pic/imdb.png") - { - release.Imdb = long.Parse(url.Substring(url.LastIndexOf('t') + 1)); - } - else if (imgUrl == "/pic/TV.png") - { - release.TVDBId = long.Parse(url.Substring(url.LastIndexOf('=') + 1)); - } + release.Imdb = long.Parse(url.Substring(url.LastIndexOf('t') + 1)); + } + else if (imgUrl == "/pic/TV.png") + { + release.TVDBId = long.Parse(url.Substring(url.LastIndexOf('=') + 1)); } - var nextPage = dom["#torrent-table-wrapper + p[align=center]"].Children().Last(); - if (!nextPage.Is("a")) - breakWhile = true; } - catch (Exception ex) - { - OnParseError(results.Content, ex); - } - if (breakWhile) - break; + } + catch (Exception ex) + { + OnParseError(results.Content, ex); } return releases; } + + public class NxtGnConfigurationData : ConfigurationData + { + public NxtGnConfigurationData() + { + Username = new StringItem { Name = "Username" }; + Password = new StringItem { Name = "Password" }; + RSSKey = new HiddenItem { Name = "RSSKey" }; + OnlyDanishCategories = new BoolItem { Name = "Only Danish Categories" }; + } + public StringItem Username { get; private set; } + public StringItem Password { get; private set; } + public HiddenItem RSSKey { get; private set; } + public BoolItem OnlyDanishCategories { get; private set; } + } } } diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 3e27aa3c8..b9dd78a40 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -110,6 +110,10 @@ ..\packages\Microsoft.Owin.StaticFiles.3.0.1\lib\net45\Microsoft.Owin.StaticFiles.dll True + + ..\packages\MonoTorrent.0.9.0\lib\net20\MonoTorrent.dll + True + ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll True @@ -186,6 +190,7 @@ + @@ -437,6 +442,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -635,4 +643,4 @@ - + \ No newline at end of file diff --git a/src/Jackett/Services/ServerService.cs b/src/Jackett/Services/ServerService.cs index c3a324e9c..f5e90e929 100644 --- a/src/Jackett/Services/ServerService.cs +++ b/src/Jackett/Services/ServerService.cs @@ -32,7 +32,7 @@ namespace Jackett.Services void ReserveUrls(bool doInstall = true); ServerConfig Config { get; } void SaveConfig(); - Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "/t.torrent"); + Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "t.torrent"); } public class ServerService : IServerService @@ -65,13 +65,13 @@ namespace Jackett.Services get { return config; } } - public Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "/t.torrent") + public Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "t.torrent") { if (link == null || (link.IsAbsoluteUri && link.Scheme == "magnet")) return link; - var encodedLink = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(link.ToString())) + file; - var proxyLink = string.Format("{0}{1}/{2}/{3}/{4}", serverUrl, action, indexerId, config.APIKey, encodedLink); + var encodedLink = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(link.ToString())); + var proxyLink = string.Format("{0}{1}/{2}/{3}?path={4}&file={5}", serverUrl, action, indexerId, config.APIKey, encodedLink, file); return new Uri(proxyLink); } diff --git a/src/Jackett/Startup.cs b/src/Jackett/Startup.cs index efa814c37..8e4070d26 100644 --- a/src/Jackett/Startup.cs +++ b/src/Jackett/Startup.cs @@ -111,7 +111,7 @@ namespace Jackett config.Routes.MapHttpRoute( name: "download", - routeTemplate: "dl/{indexerID}/{apikey}/{path}/t.torrent", + routeTemplate: "dl/{indexerID}/{apiKey}", defaults: new { controller = "Download", action = "Download" } ); diff --git a/src/Jackett/packages.config b/src/Jackett/packages.config index b602742aa..427976d0d 100644 --- a/src/Jackett/packages.config +++ b/src/Jackett/packages.config @@ -22,6 +22,7 @@ +