diff --git a/src/Jackett/BrowserUtil.cs b/src/Jackett/BrowserUtil.cs new file mode 100644 index 000000000..82154b176 --- /dev/null +++ b/src/Jackett/BrowserUtil.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Jackett +{ + public static class BrowserUtil + { + public static string ChromeUserAgent + { + get { return "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; } + } + } +} diff --git a/src/Jackett/Indexers/AlphaRatio.cs b/src/Jackett/Indexers/AlphaRatio.cs index 1be0bf14d..e4c3c93ec 100644 --- a/src/Jackett/Indexers/AlphaRatio.cs +++ b/src/Jackett/Indexers/AlphaRatio.cs @@ -45,7 +45,7 @@ namespace Jackett.Indexers static string GuidUrl = BaseUrl + "/torrents.php?torrentid="; - static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; CookieContainer cookies; HttpClientHandler handler; diff --git a/src/Jackett/Indexers/AnimeBytes.cs b/src/Jackett/Indexers/AnimeBytes.cs index f271e28db..282d2a590 100644 --- a/src/Jackett/Indexers/AnimeBytes.cs +++ b/src/Jackett/Indexers/AnimeBytes.cs @@ -22,7 +22,7 @@ namespace Jackett.Indexers public event Action OnResultParsingError; public event Action OnSaveConfigurationRequested; - static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; public string DisplayName { diff --git a/src/Jackett/Indexers/Freshon.cs b/src/Jackett/Indexers/Freshon.cs index 37bbde239..29fcca3f2 100644 --- a/src/Jackett/Indexers/Freshon.cs +++ b/src/Jackett/Indexers/Freshon.cs @@ -23,7 +23,7 @@ namespace Jackett static string LoginPostUrl = BaseUrl + "/login.php?action=makelogin"; static string SearchUrl = BaseUrl + "/browse.php"; - static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; CookieContainer cookies; HttpClientHandler handler; diff --git a/src/Jackett/Indexers/HDTorrents.cs b/src/Jackett/Indexers/HDTorrents.cs new file mode 100644 index 000000000..243c2a17f --- /dev/null +++ b/src/Jackett/Indexers/HDTorrents.cs @@ -0,0 +1,229 @@ +using CsQuery; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Web; + +namespace Jackett.Indexers +{ + public class HDTorrents : IndexerInterface + { + public event Action OnSaveConfigurationRequested; + + public event Action OnResultParsingError; + + const string DefaultUrl = "https://hd-torrents.org"; + string BaseUrl = DefaultUrl; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; + private string SearchUrl = "https://hd-torrents.org/torrents.php?search={0}&active=1&options=0&category%5B%5D=59&category%5B%5D=60&category%5B%5D=30&category%5B%5D=38&page={1}"; + private static string LoginUrl = DefaultUrl + "/login.php"; + private static string LoginPostUrl = DefaultUrl + "/login.php?returnto=index.php"; + private const int MAXPAGES = 3; + + CookieContainer cookies; + HttpClientHandler handler; + HttpClient client; + + public HDTorrents() + { + IsConfigured = false; + cookies = new CookieContainer(); + handler = new HttpClientHandler + { + CookieContainer = cookies, + AllowAutoRedirect = true, + UseCookies = true, + }; + client = new HttpClient(handler); + } + + public string DisplayName + { + get { return "HD-Torrents"; } + } + + public string DisplayDescription + { + get { return "HD-Torrents is a private torrent website with HD torrents and strict rules on their content."; } + } + + public Uri SiteLink + { + get { return new Uri(DefaultUrl); } + } + + public bool IsConfigured + { + get; + private set; + } + + public Task GetConfigurationForSetup() + { + var config = new ConfigurationDataBasicLogin(); + return Task.FromResult(config); + } + + HttpRequestMessage CreateHttpRequest(string url) + { + var message = new HttpRequestMessage(); + message.Method = HttpMethod.Get; + message.RequestUri = new Uri(url); + message.Headers.UserAgent.ParseAdd(chromeUserAgent); + return message; + } + + public async Task ApplyConfiguration(JToken configJson) + { + var config = new ConfigurationDataBasicLogin(); + config.LoadValuesFromJson(configJson); + + var startMessage = CreateHttpRequest(LoginUrl); + var results = await (await client.SendAsync(startMessage)).Content.ReadAsStringAsync(); + + + var pairs = new Dictionary { + { "uid", config.Username.Value }, + { "pwd", config.Password.Value } + }; + + var content = new FormUrlEncodedContent(pairs); + + var loginRequest = CreateHttpRequest(LoginUrl); + loginRequest.Method = HttpMethod.Post; + loginRequest.Content = content; + loginRequest.Headers.Referrer = new Uri("https://hd-torrents.org/torrents.php"); + + var response = await client.SendAsync(loginRequest); + var responseContent = await response.Content.ReadAsStringAsync(); + + if (!responseContent.Contains("If your browser doesn't have javascript enabled")) + { + var errorMessage = "Couldn't login"; + throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)config); + } + else + { + var configSaveData = new JObject(); + cookies.DumpToJson(SiteLink, configSaveData); + + if (OnSaveConfigurationRequested != null) + OnSaveConfigurationRequested(this, configSaveData); + + IsConfigured = true; + } + } + + public void LoadFromSavedConfiguration(JToken jsonConfig) + { + cookies.FillFromJson(SiteLink, jsonConfig); + IsConfigured = true; + } + + async Task PerformQuery(TorznabQuery query, string baseUrl) + { + List releases = new List(); + List searchurls = new List(); + + foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) + { + var searchString = title + " " + query.GetEpisodeSearchString(); + for (int page = 0; page < MAXPAGES; page++) + searchurls.Add(string.Format(SearchUrl, HttpUtility.UrlEncode(searchString.Trim()), page)); + } + + foreach (string SearchUrl in searchurls) + { + var results = await client.GetStringAsync(SearchUrl); + try + { + CQ dom = results; + ReleaseInfo release; + + int rowCount = 0; + var rows = dom[".mainblockcontenttt > tbody > tr"]; + foreach (var row in rows) + { + CQ qRow = row.Cq(); + if (rowCount < 2 || qRow.Children().Count() != 12) //skip 2 rows because there's an empty row & a title/sort row + { + rowCount++; + continue; + } + + release = new ReleaseInfo(); + long? size; + + release.Title = qRow.Find("td.mainblockcontent b a").Text(); + release.Description = release.Title; + + if (0 != qRow.Find("td.mainblockcontent u").Length) + release.Imdb = ParseUtil.TryCoerceLong(qRow.Find("td.mainblockcontent u").Parent().First().Attr("href").Replace("http://www.imdb.com/title/tt", "").Replace("/", "")); + + release.MinimumRatio = 1; + release.MinimumSeedTime = 172800; + + release.MagnetUri = new Uri(DefaultUrl + "/" + qRow.Find("td.mainblockcontent").Get(3).FirstChild.GetAttribute("href")); + + release.Seeders = ParseUtil.TryCoerceInt(qRow.Find("td").Get(9).FirstChild.FirstChild.InnerText); + release.Peers = ParseUtil.TryCoerceInt(qRow.Find("td").Get(10).FirstChild.FirstChild.InnerText); + + string fullSize = qRow.Find("td.mainblockcontent").Get(6).InnerText; + string[] sizeSplit = fullSize.Split(' '); + switch (sizeSplit[1].ToLower()) + { + case "kb": + size = ReleaseInfo.BytesFromKB(ParseUtil.CoerceFloat(sizeSplit[0])); + break; + case "mb": + size = ReleaseInfo.BytesFromMB(ParseUtil.CoerceFloat(sizeSplit[0])); + break; + case "gb": + size = ReleaseInfo.BytesFromGB(ParseUtil.CoerceFloat(sizeSplit[0])); + break; + default: + size = null; + break; + } + release.Size = size; + + release.Link = new Uri(DefaultUrl + "/" + qRow.Find("td.mainblockcontent b a").Attr("href")); + release.Guid = release.Link; + + string[] dateSplit = qRow.Find("td.mainblockcontent").Get(5).InnerHTML.Split(','); + string dateString = dateSplit[1].Substring(0, dateSplit[1].IndexOf('>')); + release.PublishDate = DateTime.Parse(dateString, CultureInfo.InvariantCulture); + + release.Comments = new Uri(DefaultUrl + "/" + qRow.Find("td.mainblockcontent").Get(2).FirstChild.GetAttribute("href")); + + releases.Add(release); + } + } + catch (Exception ex) + { + OnResultParsingError(this, results, ex); + throw ex; + } + } + + + return releases.ToArray(); + } + + public async Task PerformQuery(TorznabQuery query) + { + return await PerformQuery(query, BaseUrl); + } + + public Task Download(Uri link) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Jackett/Indexers/IPTorrents.cs b/src/Jackett/Indexers/IPTorrents.cs index a5c0de73f..bcf43b311 100644 --- a/src/Jackett/Indexers/IPTorrents.cs +++ b/src/Jackett/Indexers/IPTorrents.cs @@ -26,7 +26,7 @@ namespace Jackett.Indexers public bool IsConfigured { get; private set; } - static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; static string BaseUrl = "https://iptorrents.com"; diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs index 33bf39b7f..ce40972c7 100644 --- a/src/Jackett/Indexers/Rarbg.cs +++ b/src/Jackett/Indexers/Rarbg.cs @@ -39,7 +39,7 @@ namespace Jackett.Indexers const string SearchTVRageUrl = "/pubapi.php?mode=search&search_tvrage={0}&token={1}&format=json&min_seeders=1"; const string SearchQueryUrl = "/pubapi.php?mode=search&search_string={0}&token={1}&format=json&min_seeders=1"; - static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; string BaseUrl; diff --git a/src/Jackett/Indexers/ShowRSS.cs b/src/Jackett/Indexers/ShowRSS.cs index 50518f893..3702c4e65 100644 --- a/src/Jackett/Indexers/ShowRSS.cs +++ b/src/Jackett/Indexers/ShowRSS.cs @@ -36,7 +36,7 @@ namespace Jackett.Indexers const string DefaultUrl = "http://showrss.info"; const string searchAllUrl = DefaultUrl + "/feeds/all.rss"; string BaseUrl; - static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; CookieContainer cookies; HttpClientHandler handler; @@ -135,7 +135,6 @@ namespace Jackett.Indexers } ReleaseInfo release; - TorrentzHelper td; string serie_title; foreach (XmlNode node in xmlDoc.GetElementsByTagName("item")) diff --git a/src/Jackett/Indexers/TorrentDay.cs b/src/Jackett/Indexers/TorrentDay.cs index 70c2914fc..a270bc3bc 100644 --- a/src/Jackett/Indexers/TorrentDay.cs +++ b/src/Jackett/Indexers/TorrentDay.cs @@ -40,7 +40,7 @@ namespace Jackett.Indexers const string LoginUrl = BaseUrl + "/tak3login.php"; const string SearchUrl = BaseUrl + "/browse.php?search={0}&cata=yes&c2=1&c7=1&c14=1&c24=1&c26=1&c31=1&c32=1&c33=1"; - const string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; CookieContainer cookies; HttpClientHandler handler; diff --git a/src/Jackett/Indexers/Torrentz.cs b/src/Jackett/Indexers/Torrentz.cs index 4fcb136fa..85d019ad5 100644 --- a/src/Jackett/Indexers/Torrentz.cs +++ b/src/Jackett/Indexers/Torrentz.cs @@ -35,7 +35,7 @@ namespace Jackett.Indexers const string DefaultUrl = "https://torrentz.eu"; const string SearchUrl = DefaultUrl + "/feed_verifiedP?f={0}"; string BaseUrl; - static string chromeUserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"; + static string chromeUserAgent = BrowserUtil.ChromeUserAgent; CookieContainer cookies; HttpClientHandler handler; diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index af603b00d..9773b7ea2 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -82,6 +82,7 @@ + @@ -97,6 +98,7 @@ + @@ -162,6 +164,7 @@ PreserveNewest + PreserveNewest diff --git a/src/Jackett/ParseUtil.cs b/src/Jackett/ParseUtil.cs index 7eb7b8fcf..d7dfcdece 100644 --- a/src/Jackett/ParseUtil.cs +++ b/src/Jackett/ParseUtil.cs @@ -24,5 +24,27 @@ namespace Jackett return long.Parse(str, NumberStyles.Any, CultureInfo.InvariantCulture); } + + public static float TryCoerceFloat(string str) + { + float val; + float.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out val); + return val; + } + + public static int TryCoerceInt(string str) + { + int val; + int.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out val); + return val; + } + + public static long TryCoerceLong(string str) + { + long val; + long.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out val); + return val; + } + } } diff --git a/src/Jackett/WebContent/logos/hdtorrents.png b/src/Jackett/WebContent/logos/hdtorrents.png new file mode 100644 index 000000000..31254c372 Binary files /dev/null and b/src/Jackett/WebContent/logos/hdtorrents.png differ