diff --git a/src/Jackett/Content/logos/demonoid.png b/src/Jackett/Content/logos/demonoid.png new file mode 100644 index 000000000..d211b9f0f Binary files /dev/null and b/src/Jackett/Content/logos/demonoid.png differ diff --git a/src/Jackett/Indexers/Demonoid.cs b/src/Jackett/Indexers/Demonoid.cs new file mode 100644 index 000000000..bd0da646b --- /dev/null +++ b/src/Jackett/Indexers/Demonoid.cs @@ -0,0 +1,133 @@ +using CsQuery; +using Jackett.Models; +using Jackett.Models.IndexerConfig; +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.Text; +using System.Threading.Tasks; +using System.Web; + +namespace Jackett.Indexers +{ + public class Demonoid : BaseIndexer, IIndexer + { + private string LoginUrl { get { return SiteLink + "account_handler.php"; } } + private string SearchUrl { get { return SiteLink + "files/?category=3&subcategory=All&quality=All&seeded=0&to=1&query={0}"; } } + + new ConfigurationDataBasicLogin configData + { + get { return (ConfigurationDataBasicLogin)base.configData; } + set { base.configData = value; } + } + + public Demonoid(IIndexerManagerService i, Logger l, IWebClient wc) + : base(name: "Demonoid", + description: "Demonoid", + link: "http://www.demonoid.pw/", + caps: TorznabCapsUtil.CreateDefaultTorznabTVCaps(), + manager: i, + client: wc, + logger: l, + configData: new ConfigurationDataBasicLogin()) + { + } + + public async Task ApplyConfiguration(JToken configJson) + { + configData.LoadValuesFromJson(configJson); + var pairs = new Dictionary { + { "nickname", configData.Username.Value }, + { "password", configData.Password.Value }, + { "returnpath", "/" }, + { "withq", "0" }, + { "Submit", "Submit" } + }; + + var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, SiteLink); + await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("user_control_panel.php"), () => + { + CQ dom = result.Content; + var errorMessage = dom[".red"].ElementAt(1).Cq().Text().Trim(); + throw new ExceptionWithConfigData(errorMessage, configData); + }); + } + + public async Task> PerformQuery(TorznabQuery query) + { + var releases = new List(); + var searchString = query.SanitizedSearchTerm + " " + query.GetEpisodeSearchString(); + var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); + var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); + + if (results.Content.Contains("No torrents found")) + { + return releases; + } + + try + { + CQ dom = results.Content; + var rows = dom[".ctable_content_no_pad > table > tbody > tr"].ToArray(); + DateTime lastDateTime = default(DateTime); + for (var i = 0; i < rows.Length; i++) + { + var rowA = rows[i]; + var rAlign = rowA.Attributes["align"]; + if (rAlign == "right" || rAlign == "center") + continue; + if (rAlign == "left") + { + // ex: "Monday, Jun 01, 2015", "Monday, Aug 03, 2015" + var dateStr = rowA.Cq().Text().Trim().Replace("Added on ", ""); + if (dateStr.ToLowerInvariant().Contains("today")) + lastDateTime = DateTime.Now; + else + lastDateTime = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dddd, MMM dd, yyyy", CultureInfo.InvariantCulture), DateTimeKind.Utc).ToLocalTime(); + continue; + } + if (rowA.ChildElements.Count() < 2) + continue; + + var rowB = rows[++i]; + + var release = new ReleaseInfo(); + release.MinimumRatio = 1; + release.MinimumSeedTime = 172800; + + release.PublishDate = lastDateTime; + + var qLink = rowA.ChildElements.ElementAt(1).FirstElementChild.Cq(); + release.Title = qLink.Text().Trim(); + release.Description = release.Title; + + release.Comments = new Uri(SiteLink + qLink.Attr("href")); + release.Guid = release.Comments; + + var qDownload = rowB.ChildElements.ElementAt(2).ChildElements.ElementAt(1).Cq(); + release.Link = new Uri(SiteLink + qDownload.Attr("href")); + + var sizeStr = rowB.ChildElements.ElementAt(3).Cq().Text(); + release.Size = ReleaseInfo.GetBytes(sizeStr); + + release.Seeders = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text()); + release.Peers = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text()) + release.Seeders; + + 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 4b3a48955..ddceac403 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -181,6 +181,7 @@ + @@ -384,6 +385,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest