From 943776569728f95386f28b2ef03225e6cab5bb72 Mon Sep 17 00:00:00 2001 From: KZ Date: Tue, 22 Sep 2015 21:29:44 +0100 Subject: [PATCH] Implement Shazbat #151 --- README.md | 1 + src/Jackett/Content/logos/shazbat.png | Bin 0 -> 3318 bytes src/Jackett/Indexers/BaseIndexer.cs | 9 +- src/Jackett/Indexers/Shazbat.cs | 153 ++++++++++++++++++++++++++ src/Jackett/Jackett.csproj | 4 + 5 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 src/Jackett/Content/logos/shazbat.png create mode 100644 src/Jackett/Indexers/Shazbat.cs diff --git a/README.md b/README.md index e317f4708..c98f0d151 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ We were previously focused on TV but are working on extending searches to allow * [RuTor](http://rutor.org/) * [SceneAccess](https://sceneaccess.eu/login) * [SceneTime](https://www.scenetime.com/) + * [Shazbat](www.shazbat.tv/login) * [ShowRSS](https://showrss.info/) * [Strike](https://getstrike.net/) * [T411](http://www.t411.io/) diff --git a/src/Jackett/Content/logos/shazbat.png b/src/Jackett/Content/logos/shazbat.png new file mode 100644 index 0000000000000000000000000000000000000000..0af7e914d7fc1e59baeed63fb0b1b68125a4b536 GIT binary patch literal 3318 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 literal 0 HcmV?d00001 diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs index 1b0f4ab43..17aa321cf 100644 --- a/src/Jackett/Indexers/BaseIndexer.cs +++ b/src/Jackett/Indexers/BaseIndexer.cs @@ -311,26 +311,27 @@ namespace Jackett.Indexers return await webclient.GetBytes(request); } - protected async Task PostDataWithCookies(string url, IEnumerable> data, string cookieOverride = null) + protected async Task PostDataWithCookies(string url, IEnumerable> data, string cookieOverride = null, string referer = null) { var request = new Utils.Clients.WebRequest() { Url = url, Type = RequestType.POST, Cookies = cookieOverride ?? CookieHeader, - PostData = data + PostData = data, + Referer = referer }; return await webclient.GetString(request); } - protected async Task PostDataWithCookiesAndRetry(string url, IEnumerable> data, string cookieOverride = null) + protected async Task PostDataWithCookiesAndRetry(string url, IEnumerable> data, string cookieOverride = null, string referer = null) { Exception lastException = null; for (int i = 0; i < 3; i++) { try { - return await PostDataWithCookies(url, data, cookieOverride); + return await PostDataWithCookies(url, data, cookieOverride, referer); } catch (Exception e) { diff --git a/src/Jackett/Indexers/Shazbat.cs b/src/Jackett/Indexers/Shazbat.cs new file mode 100644 index 000000000..a9a636ee1 --- /dev/null +++ b/src/Jackett/Indexers/Shazbat.cs @@ -0,0 +1,153 @@ +using CsQuery; +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.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using Jackett.Models.IndexerConfig; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace Jackett.Indexers +{ + public class Shazbat : BaseIndexer, IIndexer + { + private string LoginUrl { get { return SiteLink + "login"; } } + private string SearchUrl { get { return SiteLink + "search"; } } + private string TorrentsUrl { get { return SiteLink + "torrents"; } } + + new ConfigurationDataBasicLogin configData + { + get { return (ConfigurationDataBasicLogin)base.configData; } + set { base.configData = value; } + } + + public Shazbat(IIndexerManagerService i, IWebClient c, Logger l, IProtectionService ps) + : base(name: "Shazbat", + description: "Modern indexer", + link: "http://www.shazbat.tv/", + caps: new TorznabCapabilities(TorznabCatType.TV, + TorznabCatType.TVHD, + TorznabCatType.TVSD), + manager: i, + client: c, + logger: l, + p: ps, + configData: new ConfigurationDataBasicLogin()) + { + } + + public async Task ApplyConfiguration(JToken configJson) + { + configData.LoadValuesFromJson(configJson); + var pairs = new Dictionary { + { "referer", "login"}, + { "query", ""}, + { "tv_login", configData.Username.Value }, + { "tv_password", configData.Password.Value }, + { "email", "" } + }; + + // Get cookie + var firstRequest = await RequestStringWithCookiesAndRetry(LoginUrl); + + var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl); + await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("glyphicon-log-out"), () => + { + throw new ExceptionWithConfigData("The username and password entered do not match.", configData); + }); + + return IndexerConfigurationStatus.RequiresTesting; + } + + public async Task> PerformQuery(TorznabQuery query) + { + var releases = new List(); + + var queryString = query.GetQueryString(); + var url = TorrentsUrl; + + WebClientStringResult results = null; + + if (!string.IsNullOrWhiteSpace(queryString)) + { + var pairs = new Dictionary { + { "search", queryString}, + { "portlet", "true"} + }; + + results = await PostDataWithCookiesAndRetry(SearchUrl, pairs, null, TorrentsUrl); + } + else + { + var pairs = new Dictionary { + { "portlet", "true"} + }; + + results = await PostDataWithCookiesAndRetry(TorrentsUrl, pairs, null, TorrentsUrl); + } + + try + { + CQ dom = results.Content; + var rows = dom["#torrent-table tr"]; + foreach (var row in rows.Skip(1)) + { + var release = new ReleaseInfo(); + var qRow = row.Cq(); + var titleRow = qRow.Find("td:eq(2)").First(); + titleRow.Children().Remove(); + release.Title = titleRow.Text().Trim(); + if (string.IsNullOrWhiteSpace(release.Title)) + continue; + release.Description = release.Title; + + var qLink = row.Cq().Find("td:eq(4) a:eq(0)"); + release.Link = new Uri(SiteLink + qLink.Attr("href")); + release.Guid = release.Link; + var qLinkComm = row.Cq().Find("td:eq(4) a:eq(1)"); + release.Comments = new Uri(SiteLink + qLinkComm.Attr("href")); + + // 07-22-2015 11:08 AM + var dateString = qRow.Find(".datetime").Attr("data-timestamp"); + release.PublishDate = DateTimeUtil.UnixTimestampToDateTime(ParseUtil.CoerceDouble(dateString)); + var infoString = row.Cq().Find("td:eq(3)").Text(); + + release.Size = ParseUtil.CoerceLong(Regex.Match(infoString, "\\((\\d+)\\)").Value.Replace("(","").Replace(")", "")); + + var infosplit = infoString.Replace("/", string.Empty).Split(":".ToCharArray()); + release.Seeders = ParseUtil.CoerceInt(infosplit[1]); + release.Peers = release.Seeders + ParseUtil.CoerceInt(infosplit[2]); + + // var tags = row.Cq().Find(".label-tag").Text(); These don't see to parse - bad tags? + + if(release.Title.Contains("1080p") || release.Title.Contains("720p")) + { + release.Category = TorznabCatType.TVHD.ID; + } else + { + release.Category = TorznabCatType.TVSD.ID; + } + + releases.Add(release); + } + } + catch (Exception ex) + { + OnParseError(results.Content, ex); + } + + return releases; + } + } +} diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 2075278de..81e2cde6d 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -185,6 +185,7 @@ + @@ -473,6 +474,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest