diff --git a/README.md b/README.md
index c98f0d151..18056f62c 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ We were previously focused on TV but are working on extending searches to allow
* [NextGen](https://nxtgn.org/)
* [pretome](https://pretome.info)
* [PrivateHD](https://privatehd.to/)
- * [RARGB](https://rarbg.to/)
+ * [RARBG](https://rarbg.to/)
* [RuTor](http://rutor.org/)
* [SceneAccess](https://sceneaccess.eu/login)
* [SceneTime](https://www.scenetime.com/)
diff --git a/src/Jackett/Content/custom.js b/src/Jackett/Content/custom.js
index 931da5a68..fa026e9c1 100644
--- a/src/Jackett/Content/custom.js
+++ b/src/Jackett/Content/custom.js
@@ -367,7 +367,7 @@ function bindUIButtons() {
var count = 0;
this.api().columns().every(function () {
count++;
- if (count === 5 || count === 7) {
+ if (count === 5 || count === 9) {
var column = this;
var select = $('')
.appendTo($(column.footer()).empty())
@@ -495,7 +495,7 @@ function bindUIButtons() {
var count = 0;
this.api().columns().every(function () {
count++;
- if (count === 3 || count === 5) {
+ if (count === 3 || count === 7) {
var column = this;
var select = $('')
.appendTo($(column.footer()).empty())
diff --git a/src/Jackett/Content/logos/broadcastthenet.png b/src/Jackett/Content/logos/broadcastthenet.png
new file mode 100644
index 000000000..60379279a
Binary files /dev/null and b/src/Jackett/Content/logos/broadcastthenet.png differ
diff --git a/src/Jackett/Indexers/AnimeBytes.cs b/src/Jackett/Indexers/AnimeBytes.cs
index 6875324da..8a76f7452 100644
--- a/src/Jackett/Indexers/AnimeBytes.cs
+++ b/src/Jackett/Indexers/AnimeBytes.cs
@@ -1,393 +1,394 @@
-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.Concurrent;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Security.Cryptography;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using System.Web;
-
-namespace Jackett.Indexers
-{
- public class AnimeBytes : BaseIndexer, IIndexer
- {
- private string LoginUrl { get { return SiteLink + "user/login"; } }
- private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
- public bool AllowRaws { get { return configData.IncludeRaw.Value; } }
-
- new ConfigurationDataAnimeBytes configData
- {
- get { return (ConfigurationDataAnimeBytes)base.configData; }
- set { base.configData = value; }
- }
-
- public AnimeBytes(IIndexerManagerService i, IWebClient client, Logger l, IProtectionService ps)
- : base(name: "AnimeBytes",
- link: "https://animebytes.tv/",
- description: "Powered by Tentacles",
- manager: i,
- client: client,
- caps: new TorznabCapabilities(TorznabCatType.TVAnime,
- TorznabCatType.Movies,
- TorznabCatType.BooksComics,
- TorznabCatType.ConsolePSP,
- TorznabCatType.ConsoleOther,
- TorznabCatType.PCGames),
- logger: l,
- p: ps,
- configData: new ConfigurationDataAnimeBytes())
- {
-
- }
-
- public async Task ApplyConfiguration(JToken configJson)
- {
- configData.LoadValuesFromJson(configJson);
-
- lock (cache)
- {
- cache.Clear();
- }
-
- // Get the login form as we need the CSRF Token
- var loginPage = await webclient.GetString(new Utils.Clients.WebRequest()
- {
- Url = LoginUrl
- });
-
- CQ loginPageDom = loginPage.Content;
- var csrfToken = loginPageDom["input[name=\"csrf_token\"]"].Last();
-
- // Build login form
- var pairs = new Dictionary {
- { "csrf_token", csrfToken.Attr("value") },
- { "username", configData.Username.Value },
- { "password", configData.Password.Value },
- { "keeplogged_sent", "true" },
- { "keeplogged", "on" },
- { "login", "Log In!" }
- };
-
- // Do the login
- var request = new Utils.Clients.WebRequest()
- {
- Cookies = loginPage.Cookies,
- PostData = pairs,
- Referer = LoginUrl,
- Type = RequestType.POST,
- Url = LoginUrl
- };
- var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, null);
-
- // Follow the redirect
- await FollowIfRedirect(response, request.Url, SearchUrl);
-
- await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("/user/logout"), () =>
- {
- // Their login page appears to be broken and just gives a 500 error.
- throw new ExceptionWithConfigData("Failed to login, 6 failed attempts will get you banned for 6 hours.", configData);
- });
-
- return IndexerConfigurationStatus.RequiresTesting;
- }
-
- // Override to load legacy config format
- public override void LoadFromSavedConfiguration(JToken jsonConfig)
- {
- if (jsonConfig is JObject)
- {
- configData.CookieHeader.Value = jsonConfig.Value("cookies");
- configData.IncludeRaw.Value = jsonConfig.Value("raws");
- SaveConfig();
- IsConfigured = true;
- return;
- }
-
- base.LoadFromSavedConfiguration(jsonConfig);
- }
-
- public async Task> PerformQuery(TorznabQuery query)
- {
- // The result list
- var releases = new List();
-
- foreach (var result in await GetResults(query.SanitizedSearchTerm))
- {
- releases.Add(result);
- }
-
- return releases.ToArray();
- }
-
- public async Task> GetResults(string searchTerm)
- {
- var cleanSearchTerm = HttpUtility.UrlEncode(searchTerm);
-
- // This tracker only deals with full seasons so chop off the episode/season number if we have it D:
- if (!string.IsNullOrWhiteSpace(searchTerm))
- {
- var splitindex = searchTerm.LastIndexOf(' ');
- if (splitindex > -1)
- searchTerm = searchTerm.Substring(0, splitindex);
- }
-
- // The result list
- var releases = new List();
-
- // Check cache first so we don't query the server for each episode when searching for each episode in a series.
- lock (cache)
- {
- // Remove old cache items
- CleanCache();
-
- var cachedResult = cache.Where(i => i.Query == searchTerm).FirstOrDefault();
- if (cachedResult != null)
- return cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray();
- }
-
- var queryUrl = SearchUrl;
- // Only include the query bit if its required as hopefully the site caches the non query page
- if (!string.IsNullOrWhiteSpace(searchTerm))
- {
- queryUrl += string.Format("searchstr={0}&action=advanced&search_type=title&year=&year2=&tags=&tags_type=0&sort=time_added&way=desc&hentai=2&releasegroup=&epcount=&epcount2=&artbooktitle=", cleanSearchTerm);
- }
-
- // Get the content from the tracker
- var response = await RequestStringWithCookiesAndRetry(queryUrl);
- CQ dom = response.Content;
-
- // Parse
- try
- {
- var releaseInfo = "S01";
- var root = dom.Find(".group_cont");
- // We may have got redirected to the series page if we have none of these
- if (root.Count() == 0)
- root = dom.Find(".torrent_table");
-
- foreach (var series in root)
- {
- var seriesCq = series.Cq();
-
- var synonyms = new List();
- var mainTitle = seriesCq.Find(".group_title strong a").First().Text().Trim();
-
- var yearStr = seriesCq.Find(".group_title strong").First().Text().Trim().Replace("]", "").Trim();
- int yearIndex = yearStr.LastIndexOf("[");
- if (yearIndex > -1)
- yearStr = yearStr.Substring(yearIndex + 1);
-
- int year = 0;
- if (!int.TryParse(yearStr, out year))
- year = DateTime.Now.Year;
-
- synonyms.Add(mainTitle);
-
- // If the title contains a comma then we can't use the synonyms as they are comma seperated
- if (!mainTitle.Contains(","))
- {
- var symnomnNames = string.Empty;
- foreach (var e in seriesCq.Find(".group_statbox li"))
- {
- if (e.FirstChild.InnerText == "Synonyms:")
- {
- symnomnNames = e.InnerText;
- }
- }
-
- if (!string.IsNullOrWhiteSpace(symnomnNames))
- {
- foreach (var name in symnomnNames.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
- {
- var theName = name.Trim();
- if (!theName.Contains("") && !string.IsNullOrWhiteSpace(theName))
- {
- synonyms.Add(theName);
- }
- }
- }
- }
-
- foreach (var title in synonyms)
- {
- var releaseRows = seriesCq.Find(".torrent_group tr");
-
- // Skip the first two info rows
- for (int r = 1; r < releaseRows.Count(); r++)
- {
- var row = releaseRows.Get(r);
- var rowCq = row.Cq();
- if (rowCq.HasClass("edition_info"))
- {
- releaseInfo = rowCq.Find("td").Text();
-
- if (string.IsNullOrWhiteSpace(releaseInfo))
- {
- // Single episodes alpha - Reported that this info is missing.
- // It should self correct when availible
- break;
- }
-
- releaseInfo = releaseInfo.Replace("Episode ", "");
- releaseInfo = releaseInfo.Replace("Season ", "S");
- releaseInfo = releaseInfo.Trim();
- }
- else if (rowCq.HasClass("torrent"))
- {
- var links = rowCq.Find("a");
- // Protect against format changes
- if (links.Count() != 2)
- {
- continue;
- }
-
- var release = new ReleaseInfo();
- release.MinimumRatio = 1;
- release.MinimumSeedTime = 259200;
- var downloadLink = links.Get(0);
-
- // We dont know this so try to fake based on the release year
- release.PublishDate = new DateTime(year, 1, 1);
- release.PublishDate = release.PublishDate.AddDays(Math.Min(DateTime.Now.DayOfYear, 365) - 1);
-
- var infoLink = links.Get(1);
- release.Comments = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href"));
- release.Guid = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href") + "&nh=" + StringUtil.Hash(title)); // Sonarr should dedupe on this url - allow a url per name.
- release.Link = new Uri(downloadLink.Attributes.GetAttribute("href"), UriKind.Relative);
-
- var category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
- if (category == "TV Series")
- release.Category = TorznabCatType.TVAnime.ID;
-
- // Ignore these categories as they'll cause hell with the matcher
- // TV Special, OVA, ONA, DVD Special, BD Special
-
- if (category == "Movie")
- release.Category = TorznabCatType.Movies.ID;
-
- if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
- release.Category = TorznabCatType.BooksComics.ID;
-
- if (category == "Novel" || category == "Artbook")
- release.Category = TorznabCatType.BooksComics.ID;
-
- if (category == "Game" || category == "Visual Novel")
- {
- var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
- if (description.Contains(" PSP "))
- release.Category = TorznabCatType.ConsolePSP.ID;
- if (description.Contains("PSX"))
- release.Category = TorznabCatType.ConsoleOther.ID;
- if (description.Contains(" NES "))
- release.Category = TorznabCatType.ConsoleOther.ID;
- if (description.Contains(" PC "))
- release.Category = TorznabCatType.PCGames.ID;
- }
-
-
-
- // We dont actually have a release name >.> so try to create one
- var releaseTags = infoLink.InnerText.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
- for (int i = releaseTags.Count - 1; i >= 0; i--)
- {
- releaseTags[i] = releaseTags[i].Trim();
- if (string.IsNullOrWhiteSpace(releaseTags[i]))
- releaseTags.RemoveAt(i);
- }
-
- var group = releaseTags.Last();
- if (group.Contains("(") && group.Contains(")"))
- {
- // Skip raws if set
- if (group.ToLowerInvariant().StartsWith("raw") && !AllowRaws)
- {
- continue;
- }
-
- var start = group.IndexOf("(");
- group = "[" + group.Substring(start + 1, (group.IndexOf(")") - 1) - start) + "] ";
- }
- else
- {
- group = string.Empty;
- }
-
- var infoString = "";
-
- for (int i = 0; i + 1 < releaseTags.Count(); i++)
- {
- if (releaseTags[i] == "Raw" && !AllowRaws)
- continue;
- infoString += "[" + releaseTags[i] + "]";
- }
-
- if (category == "Movie")
- {
- release.Title = string.Format("{0} {1} {2}{3}", title, year, group, infoString);
- }
- else
- {
- release.Title = string.Format("{0}{1} {2} {3}", group, title, releaseInfo, infoString);
- }
- release.Description = title;
-
- var size = rowCq.Find(".torrent_size");
- if (size.Count() > 0)
- {
- release.Size = ReleaseInfo.GetBytes(size.First().Text());
- }
-
- // Additional 5 hours per GB
- release.MinimumSeedTime += (release.Size / 1000000000) * 18000;
-
- // Peer info
- release.Seeders = ParseUtil.CoerceInt(rowCq.Find(".torrent_seeders").Text());
- release.Peers = release.Seeders + ParseUtil.CoerceInt(rowCq.Find(".torrent_leechers").Text());
-
- if (release.Category != 0)
- releases.Add(release);
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- OnParseError(response.Content, ex);
- }
-
- // Add to the cache
- lock (cache)
- {
- cache.Add(new CachedQueryResult(searchTerm, releases));
- }
-
- return releases.Select(s => (ReleaseInfo)s.Clone());
- }
-
-
- public async override Task Download(Uri link)
- {
- // The urls for this tracker are quite long so append the domain after the incoming request.
- var response = await webclient.GetBytes(new Utils.Clients.WebRequest()
- {
- Url = SiteLink + link.ToString(),
- Cookies = CookieHeader
- });
-
- return response.Content;
- }
- }
-}
+using CsQuery;
+using Jackett.Models;
+using Jackett.Models.IndexerConfig;
+using Jackett.Models.IndexerConfig.Bespoke;
+using Jackett.Services;
+using Jackett.Utils;
+using Jackett.Utils.Clients;
+using Newtonsoft.Json.Linq;
+using NLog;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace Jackett.Indexers
+{
+ public class AnimeBytes : BaseIndexer, IIndexer
+ {
+ private string LoginUrl { get { return SiteLink + "user/login"; } }
+ private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
+ public bool AllowRaws { get { return configData.IncludeRaw.Value; } }
+
+ new ConfigurationDataAnimeBytes configData
+ {
+ get { return (ConfigurationDataAnimeBytes)base.configData; }
+ set { base.configData = value; }
+ }
+
+ public AnimeBytes(IIndexerManagerService i, IWebClient client, Logger l, IProtectionService ps)
+ : base(name: "AnimeBytes",
+ link: "https://animebytes.tv/",
+ description: "Powered by Tentacles",
+ manager: i,
+ client: client,
+ caps: new TorznabCapabilities(TorznabCatType.TVAnime,
+ TorznabCatType.Movies,
+ TorznabCatType.BooksComics,
+ TorznabCatType.ConsolePSP,
+ TorznabCatType.ConsoleOther,
+ TorznabCatType.PCGames),
+ logger: l,
+ p: ps,
+ configData: new ConfigurationDataAnimeBytes())
+ {
+
+ }
+
+ public async Task ApplyConfiguration(JToken configJson)
+ {
+ configData.LoadValuesFromJson(configJson);
+
+ lock (cache)
+ {
+ cache.Clear();
+ }
+
+ // Get the login form as we need the CSRF Token
+ var loginPage = await webclient.GetString(new Utils.Clients.WebRequest()
+ {
+ Url = LoginUrl
+ });
+
+ CQ loginPageDom = loginPage.Content;
+ var csrfToken = loginPageDom["input[name=\"csrf_token\"]"].Last();
+
+ // Build login form
+ var pairs = new Dictionary {
+ { "csrf_token", csrfToken.Attr("value") },
+ { "username", configData.Username.Value },
+ { "password", configData.Password.Value },
+ { "keeplogged_sent", "true" },
+ { "keeplogged", "on" },
+ { "login", "Log In!" }
+ };
+
+ // Do the login
+ var request = new Utils.Clients.WebRequest()
+ {
+ Cookies = loginPage.Cookies,
+ PostData = pairs,
+ Referer = LoginUrl,
+ Type = RequestType.POST,
+ Url = LoginUrl
+ };
+ var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, null);
+
+ // Follow the redirect
+ await FollowIfRedirect(response, request.Url, SearchUrl);
+
+ await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("/user/logout"), () =>
+ {
+ // Their login page appears to be broken and just gives a 500 error.
+ throw new ExceptionWithConfigData("Failed to login, 6 failed attempts will get you banned for 6 hours.", configData);
+ });
+
+ return IndexerConfigurationStatus.RequiresTesting;
+ }
+
+ // Override to load legacy config format
+ public override void LoadFromSavedConfiguration(JToken jsonConfig)
+ {
+ if (jsonConfig is JObject)
+ {
+ configData.CookieHeader.Value = jsonConfig.Value("cookies");
+ configData.IncludeRaw.Value = jsonConfig.Value("raws");
+ SaveConfig();
+ IsConfigured = true;
+ return;
+ }
+
+ base.LoadFromSavedConfiguration(jsonConfig);
+ }
+
+ public async Task> PerformQuery(TorznabQuery query)
+ {
+ // The result list
+ var releases = new List();
+
+ foreach (var result in await GetResults(query.SanitizedSearchTerm))
+ {
+ releases.Add(result);
+ }
+
+ return releases.ToArray();
+ }
+
+ public async Task> GetResults(string searchTerm)
+ {
+ var cleanSearchTerm = HttpUtility.UrlEncode(searchTerm);
+
+ // This tracker only deals with full seasons so chop off the episode/season number if we have it D:
+ if (!string.IsNullOrWhiteSpace(searchTerm))
+ {
+ var splitindex = searchTerm.LastIndexOf(' ');
+ if (splitindex > -1)
+ searchTerm = searchTerm.Substring(0, splitindex);
+ }
+
+ // The result list
+ var releases = new List();
+
+ // Check cache first so we don't query the server for each episode when searching for each episode in a series.
+ lock (cache)
+ {
+ // Remove old cache items
+ CleanCache();
+
+ var cachedResult = cache.Where(i => i.Query == searchTerm).FirstOrDefault();
+ if (cachedResult != null)
+ return cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray();
+ }
+
+ var queryUrl = SearchUrl;
+ // Only include the query bit if its required as hopefully the site caches the non query page
+ if (!string.IsNullOrWhiteSpace(searchTerm))
+ {
+ queryUrl += string.Format("searchstr={0}&action=advanced&search_type=title&year=&year2=&tags=&tags_type=0&sort=time_added&way=desc&hentai=2&releasegroup=&epcount=&epcount2=&artbooktitle=", cleanSearchTerm);
+ }
+
+ // Get the content from the tracker
+ var response = await RequestStringWithCookiesAndRetry(queryUrl);
+ CQ dom = response.Content;
+
+ // Parse
+ try
+ {
+ var releaseInfo = "S01";
+ var root = dom.Find(".group_cont");
+ // We may have got redirected to the series page if we have none of these
+ if (root.Count() == 0)
+ root = dom.Find(".torrent_table");
+
+ foreach (var series in root)
+ {
+ var seriesCq = series.Cq();
+
+ var synonyms = new List();
+ var mainTitle = seriesCq.Find(".group_title strong a").First().Text().Trim();
+
+ var yearStr = seriesCq.Find(".group_title strong").First().Text().Trim().Replace("]", "").Trim();
+ int yearIndex = yearStr.LastIndexOf("[");
+ if (yearIndex > -1)
+ yearStr = yearStr.Substring(yearIndex + 1);
+
+ int year = 0;
+ if (!int.TryParse(yearStr, out year))
+ year = DateTime.Now.Year;
+
+ synonyms.Add(mainTitle);
+
+ // If the title contains a comma then we can't use the synonyms as they are comma seperated
+ if (!mainTitle.Contains(","))
+ {
+ var symnomnNames = string.Empty;
+ foreach (var e in seriesCq.Find(".group_statbox li"))
+ {
+ if (e.FirstChild.InnerText == "Synonyms:")
+ {
+ symnomnNames = e.InnerText;
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(symnomnNames))
+ {
+ foreach (var name in symnomnNames.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
+ {
+ var theName = name.Trim();
+ if (!theName.Contains("") && !string.IsNullOrWhiteSpace(theName))
+ {
+ synonyms.Add(theName);
+ }
+ }
+ }
+ }
+
+ foreach (var title in synonyms)
+ {
+ var releaseRows = seriesCq.Find(".torrent_group tr");
+
+ // Skip the first two info rows
+ for (int r = 1; r < releaseRows.Count(); r++)
+ {
+ var row = releaseRows.Get(r);
+ var rowCq = row.Cq();
+ if (rowCq.HasClass("edition_info"))
+ {
+ releaseInfo = rowCq.Find("td").Text();
+
+ if (string.IsNullOrWhiteSpace(releaseInfo))
+ {
+ // Single episodes alpha - Reported that this info is missing.
+ // It should self correct when availible
+ break;
+ }
+
+ releaseInfo = releaseInfo.Replace("Episode ", "");
+ releaseInfo = releaseInfo.Replace("Season ", "S");
+ releaseInfo = releaseInfo.Trim();
+ }
+ else if (rowCq.HasClass("torrent"))
+ {
+ var links = rowCq.Find("a");
+ // Protect against format changes
+ if (links.Count() != 2)
+ {
+ continue;
+ }
+
+ var release = new ReleaseInfo();
+ release.MinimumRatio = 1;
+ release.MinimumSeedTime = 259200;
+ var downloadLink = links.Get(0);
+
+ // We dont know this so try to fake based on the release year
+ release.PublishDate = new DateTime(year, 1, 1);
+ release.PublishDate = release.PublishDate.AddDays(Math.Min(DateTime.Now.DayOfYear, 365) - 1);
+
+ var infoLink = links.Get(1);
+ release.Comments = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href"));
+ release.Guid = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href") + "&nh=" + StringUtil.Hash(title)); // Sonarr should dedupe on this url - allow a url per name.
+ release.Link = new Uri(downloadLink.Attributes.GetAttribute("href"), UriKind.Relative);
+
+ var category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
+ if (category == "TV Series")
+ release.Category = TorznabCatType.TVAnime.ID;
+
+ // Ignore these categories as they'll cause hell with the matcher
+ // TV Special, OVA, ONA, DVD Special, BD Special
+
+ if (category == "Movie")
+ release.Category = TorznabCatType.Movies.ID;
+
+ if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
+ release.Category = TorznabCatType.BooksComics.ID;
+
+ if (category == "Novel" || category == "Artbook")
+ release.Category = TorznabCatType.BooksComics.ID;
+
+ if (category == "Game" || category == "Visual Novel")
+ {
+ var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
+ if (description.Contains(" PSP "))
+ release.Category = TorznabCatType.ConsolePSP.ID;
+ if (description.Contains("PSX"))
+ release.Category = TorznabCatType.ConsoleOther.ID;
+ if (description.Contains(" NES "))
+ release.Category = TorznabCatType.ConsoleOther.ID;
+ if (description.Contains(" PC "))
+ release.Category = TorznabCatType.PCGames.ID;
+ }
+
+
+
+ // We dont actually have a release name >.> so try to create one
+ var releaseTags = infoLink.InnerText.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
+ for (int i = releaseTags.Count - 1; i >= 0; i--)
+ {
+ releaseTags[i] = releaseTags[i].Trim();
+ if (string.IsNullOrWhiteSpace(releaseTags[i]))
+ releaseTags.RemoveAt(i);
+ }
+
+ var group = releaseTags.Last();
+ if (group.Contains("(") && group.Contains(")"))
+ {
+ // Skip raws if set
+ if (group.ToLowerInvariant().StartsWith("raw") && !AllowRaws)
+ {
+ continue;
+ }
+
+ var start = group.IndexOf("(");
+ group = "[" + group.Substring(start + 1, (group.IndexOf(")") - 1) - start) + "] ";
+ }
+ else
+ {
+ group = string.Empty;
+ }
+
+ var infoString = "";
+
+ for (int i = 0; i + 1 < releaseTags.Count(); i++)
+ {
+ if (releaseTags[i] == "Raw" && !AllowRaws)
+ continue;
+ infoString += "[" + releaseTags[i] + "]";
+ }
+
+ if (category == "Movie")
+ {
+ release.Title = string.Format("{0} {1} {2}{3}", title, year, group, infoString);
+ }
+ else
+ {
+ release.Title = string.Format("{0}{1} {2} {3}", group, title, releaseInfo, infoString);
+ }
+ release.Description = title;
+
+ var size = rowCq.Find(".torrent_size");
+ if (size.Count() > 0)
+ {
+ release.Size = ReleaseInfo.GetBytes(size.First().Text());
+ }
+
+ // Additional 5 hours per GB
+ release.MinimumSeedTime += (release.Size / 1000000000) * 18000;
+
+ // Peer info
+ release.Seeders = ParseUtil.CoerceInt(rowCq.Find(".torrent_seeders").Text());
+ release.Peers = release.Seeders + ParseUtil.CoerceInt(rowCq.Find(".torrent_leechers").Text());
+
+ if (release.Category != 0)
+ releases.Add(release);
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(response.Content, ex);
+ }
+
+ // Add to the cache
+ lock (cache)
+ {
+ cache.Add(new CachedQueryResult(searchTerm, releases));
+ }
+
+ return releases.Select(s => (ReleaseInfo)s.Clone());
+ }
+
+
+ public async override Task Download(Uri link)
+ {
+ // The urls for this tracker are quite long so append the domain after the incoming request.
+ var response = await webclient.GetBytes(new Utils.Clients.WebRequest()
+ {
+ Url = SiteLink + link.ToString(),
+ Cookies = CookieHeader
+ });
+
+ return response.Content;
+ }
+ }
+}
diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs
index 17aa321cf..2c7a34d64 100644
--- a/src/Jackett/Indexers/BaseIndexer.cs
+++ b/src/Jackett/Indexers/BaseIndexer.cs
@@ -311,7 +311,7 @@ namespace Jackett.Indexers
return await webclient.GetBytes(request);
}
- protected async Task PostDataWithCookies(string url, IEnumerable> data, string cookieOverride = null, string referer = null)
+ protected async Task PostDataWithCookies(string url, IEnumerable> data, string cookieOverride = null, string referer = null, Dictionary headers = null, string rawbody = null)
{
var request = new Utils.Clients.WebRequest()
{
@@ -319,19 +319,20 @@ namespace Jackett.Indexers
Type = RequestType.POST,
Cookies = cookieOverride ?? CookieHeader,
PostData = data,
- Referer = referer
+ Referer = referer,
+ Headers = headers
};
return await webclient.GetString(request);
}
- protected async Task PostDataWithCookiesAndRetry(string url, IEnumerable> data, string cookieOverride = null, string referer = null)
+ protected async Task PostDataWithCookiesAndRetry(string url, IEnumerable> data, string cookieOverride = null, string referer = null, Dictionary headers = null, string rawbody = null)
{
Exception lastException = null;
for (int i = 0; i < 3; i++)
{
try
{
- return await PostDataWithCookies(url, data, cookieOverride, referer);
+ return await PostDataWithCookies(url, data, cookieOverride, referer, headers, rawbody);
}
catch (Exception e)
{
diff --git a/src/Jackett/Indexers/BroadcastTheNet.cs b/src/Jackett/Indexers/BroadcastTheNet.cs
new file mode 100644
index 000000000..309dfbb9f
--- /dev/null
+++ b/src/Jackett/Indexers/BroadcastTheNet.cs
@@ -0,0 +1,151 @@
+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.Globalization;
+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.Dynamic;
+
+namespace Jackett.Indexers
+{
+ public class BroadcastTheNet : BaseIndexer, IIndexer
+ {
+ string APIBASE = "http://api.btnapps.net/";
+
+ new ConfigurationDataAPIKey configData
+ {
+ get { return (ConfigurationDataAPIKey)base.configData; }
+ set { base.configData = value; }
+ }
+
+ public BroadcastTheNet(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
+ : base(name: "BroadcastTheNet",
+ description: "Needs no description..",
+ link: "https://broadcasthe.net/",
+ caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
+ manager: i,
+ client: wc,
+ logger: l,
+ p: ps,
+ configData: new ConfigurationDataAPIKey())
+ {
+ }
+
+ public async Task ApplyConfiguration(JToken configJson)
+ {
+ configData.LoadValuesFromJson(configJson);
+
+ IsConfigured = false;
+ try
+ {
+ var results = await PerformQuery(new TorznabQuery());
+ if (results.Count() == 0)
+ throw new Exception("Testing returned no results!");
+ IsConfigured = true;
+ SaveConfig();
+ }
+ catch(Exception e)
+ {
+ throw new ExceptionWithConfigData(e.Message, configData);
+ }
+
+ return IndexerConfigurationStatus.Completed;
+ }
+
+
+ private string JsonRPCRequest(string method, dynamic parameters)
+ {
+ dynamic request = new ExpandoObject();
+ request["jsonrpc"] = "2.0";
+ request["method"] = method;
+ request["params"] = parameters;
+ request["id"] = Guid.NewGuid().ToString().Substring(0, 8);
+ return request.ToString();
+ }
+
+ public async Task> PerformQuery(TorznabQuery query)
+ {
+ var releases = new List();
+
+
+ var response = await PostDataWithCookiesAndRetry(APIBASE, null, null, null, new Dictionary()
+ {
+ { "Accept", "application/json-rpc, application/json"},
+ {"ContentType", "application/json-rpc"}
+ }, JsonRPCRequest("getTorrents", new Object[]
+ {
+ configData.Key.Value
+ }));
+
+ /*
+ var searchUrl = BrowsePage;
+
+ if (!string.IsNullOrWhiteSpace(query.GetQueryString()))
+ {
+ searchUrl += string.Format(QueryString, HttpUtility.UrlEncode(query.GetQueryString()));
+ }
+
+ var results = await RequestStringWithCookiesAndRetry(searchUrl);
+
+ try
+ {
+ CQ dom = results.Content;
+
+ var rows = dom["#sortabletable tr"];
+ foreach (var row in rows.Skip(1))
+ {
+ var release = new ReleaseInfo();
+ var qRow = row.Cq();
+ release.Title = qRow.Find(".tooltip-content div").First().Text();
+ if (string.IsNullOrWhiteSpace(release.Title))
+ continue;
+ release.Description = qRow.Find(".tooltip-content div").Get(1).InnerText.Trim();
+
+ var qLink = row.Cq().Find("td:eq(2) a:eq(1)");
+ release.Link = new Uri(qLink.Attr("href"));
+ release.Guid = release.Link;
+ release.Comments = new Uri(qRow.Find(".tooltip-target a").First().Attr("href"));
+
+ // 07-22-2015 11:08 AM
+ var dateString = qRow.Find("td:eq(1) div").Last().Children().Remove().End().Text().Trim();
+ release.PublishDate = DateTime.ParseExact(dateString, "MM-dd-yyyy hh:mm tt", CultureInfo.InvariantCulture);
+
+ var sizeStr = qRow.Find("td:eq(4)").Text().Trim();
+ release.Size = ReleaseInfo.GetBytes(sizeStr);
+
+ release.Seeders = ParseUtil.CoerceInt(qRow.Find("td:eq(6)").Text().Trim());
+ release.Peers = ParseUtil.CoerceInt(qRow.Find("td:eq(7)").Text().Trim()) + release.Seeders;
+
+ var catLink = row.Cq().Find("td:eq(0) a").First().Attr("href");
+ var catSplit = catLink.IndexOf("category=");
+ if (catSplit > -1)
+ {
+ catLink = catLink.Substring(catSplit + 9);
+ }
+
+ release.Category = MapTrackerCatToNewznab(catLink);
+ releases.Add(release);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(results.Content, ex);
+ }*/
+
+ return releases;
+ }
+
+
+ }
+}
diff --git a/src/Jackett/Indexers/FileList.cs b/src/Jackett/Indexers/FileList.cs
index 9ca4e219f..06d8c090d 100644
--- a/src/Jackett/Indexers/FileList.cs
+++ b/src/Jackett/Indexers/FileList.cs
@@ -1,156 +1,157 @@
-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.Collections.Specialized;
-using System.Globalization;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Text;
-using System.Threading.Tasks;
-using System.Web;
-using Jackett.Models.IndexerConfig;
-
-namespace Jackett.Indexers
-{
- public class FileList : BaseIndexer, IIndexer
- {
- string LoginUrl { get { return SiteLink + "takelogin.php"; } }
- string BrowseUrl { get { return SiteLink + "browse.php"; } }
-
- new ConfigurationDataFileList configData
- {
- get { return (ConfigurationDataFileList)base.configData; }
- set { base.configData = value; }
- }
-
- public FileList(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
- : base(name: "FileList",
- description: "The best Romanian site.",
- link: "http://filelist.ro/",
- caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
- manager: i,
- client: wc,
- logger: l,
- p: ps,
- configData: new ConfigurationDataFileList())
- {
- AddCategoryMapping(24, TorznabCatType.TVAnime);
- AddCategoryMapping(11, TorznabCatType.Audio);
- AddCategoryMapping(15, TorznabCatType.TV);
- //AddCategoryMapping(18, TorznabCatType.); Other
- AddCategoryMapping(16, TorznabCatType.TVDocumentary);
- AddCategoryMapping(25, TorznabCatType.Movies3D);
- AddCategoryMapping(20, TorznabCatType.MoviesBluRay);
- AddCategoryMapping(2, TorznabCatType.MoviesSD);
- AddCategoryMapping(3, TorznabCatType.MoviesForeign); //RO
- AddCategoryMapping(4, TorznabCatType.MoviesHD);
- AddCategoryMapping(19, TorznabCatType.MoviesForeign); // RO
- AddCategoryMapping(1, TorznabCatType.MoviesSD);
- AddCategoryMapping(10, TorznabCatType.Console);
- AddCategoryMapping(9, TorznabCatType.PCGames);
- //AddCategoryMapping(17, TorznabCatType); Linux No cat
- AddCategoryMapping(22, TorznabCatType.PCPhoneOther); //Apps/mobile
- AddCategoryMapping(8, TorznabCatType.PC);
- AddCategoryMapping(21, TorznabCatType.TVHD);
- AddCategoryMapping(23, TorznabCatType.TVSD);
- AddCategoryMapping(13, TorznabCatType.TVSport);
- AddCategoryMapping(14, TorznabCatType.TV);
- AddCategoryMapping(12, TorznabCatType.AudioVideo);
- AddCategoryMapping(7, TorznabCatType.XXX);
- }
-
- public async Task ApplyConfiguration(JToken configJson)
- {
- configData.LoadValuesFromJson(configJson);
- var pairs = new Dictionary {
- { "username", configData.Username.Value },
- { "password", configData.Password.Value }
- };
-
- var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl);
- await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
- {
- CQ dom = result.Content;
- var errorMessage = dom[".main"].Text().Trim();
- throw new ExceptionWithConfigData(errorMessage, configData);
- });
- return IndexerConfigurationStatus.RequiresTesting;
- }
-
- public async Task> PerformQuery(TorznabQuery query)
- {
- var releases = new List();
- var searchUrl = BrowseUrl;
- var searchString = query.GetQueryString();
-
- var cats = MapTorznabCapsToTrackers(query);
- string cat = "0";
- if (cats.Count == 1)
- {
- cat = cats[0];
- }
-
- if (!string.IsNullOrWhiteSpace(searchString) || cat != "0")
- searchUrl += string.Format("?search={0}&cat={1}&searchin=0&sort=0", HttpUtility.UrlEncode(searchString), cat);
-
-
-
- var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);
- var results = response.Content;
- try
- {
- CQ dom = results;
- var rows = dom[".torrentrow"];
- foreach (var row in rows)
- {
- var release = new ReleaseInfo();
- var qRow = row.Cq();
- var qTitleLink = qRow.Find(".torrenttable:eq(1) a").First();
- release.Title = qRow.Find(".torrenttable:eq(1) a b").Text().Trim();
- release.Description = release.Title;
- release.Guid = new Uri(SiteLink + qTitleLink.Attr("href"));
- release.Comments = release.Guid;
-
- //22:05:3716/02/2013
- var dateStr = qRow.Find(".torrenttable:eq(5)").Text().Trim();
- release.PublishDate = DateTime.ParseExact(dateStr, "H:mm:ssdd/MM/yyyy", CultureInfo.InvariantCulture).AddHours(-2);
-
- var qLink = qRow.Find(".torrenttable:eq(2) a").First();
- release.Link = new Uri(SiteLink + qLink.Attr("href"));
-
- var sizeStr = qRow.Find(".torrenttable:eq(6)").Text().Trim();
- release.Size = ReleaseInfo.GetBytes(sizeStr);
-
- release.Seeders = ParseUtil.CoerceInt(qRow.Find(".torrenttable:eq(8)").Text().Trim());
- release.Peers = ParseUtil.CoerceInt(qRow.Find(".torrenttable:eq(9)").Text().Trim()) + release.Seeders;
-
- var catId = qRow.Find(".torrenttable:eq(0) a").First().Attr("href").Substring(15);
- release.Category = MapTrackerCatToNewznab(catId);
-
- // Skip other
- if (release.Category != 0)
- {
- // Skip Romanian releases
- if (release.Category == TorznabCatType.MoviesForeign.ID && !configData.IncludeRomanianReleases.Value)
- continue;
-
- releases.Add(release);
- }
- }
- }
- catch (Exception ex)
- {
- OnParseError(results, ex);
- }
-
- return releases;
- }
- }
-}
+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.Collections.Specialized;
+using System.Globalization;
+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 Jackett.Models.IndexerConfig.Bespoke;
+
+namespace Jackett.Indexers
+{
+ public class FileList : BaseIndexer, IIndexer
+ {
+ string LoginUrl { get { return SiteLink + "takelogin.php"; } }
+ string BrowseUrl { get { return SiteLink + "browse.php"; } }
+
+ new ConfigurationDataFileList configData
+ {
+ get { return (ConfigurationDataFileList)base.configData; }
+ set { base.configData = value; }
+ }
+
+ public FileList(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
+ : base(name: "FileList",
+ description: "The best Romanian site.",
+ link: "http://filelist.ro/",
+ caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
+ manager: i,
+ client: wc,
+ logger: l,
+ p: ps,
+ configData: new ConfigurationDataFileList())
+ {
+ AddCategoryMapping(24, TorznabCatType.TVAnime);
+ AddCategoryMapping(11, TorznabCatType.Audio);
+ AddCategoryMapping(15, TorznabCatType.TV);
+ //AddCategoryMapping(18, TorznabCatType.); Other
+ AddCategoryMapping(16, TorznabCatType.TVDocumentary);
+ AddCategoryMapping(25, TorznabCatType.Movies3D);
+ AddCategoryMapping(20, TorznabCatType.MoviesBluRay);
+ AddCategoryMapping(2, TorznabCatType.MoviesSD);
+ AddCategoryMapping(3, TorznabCatType.MoviesForeign); //RO
+ AddCategoryMapping(4, TorznabCatType.MoviesHD);
+ AddCategoryMapping(19, TorznabCatType.MoviesForeign); // RO
+ AddCategoryMapping(1, TorznabCatType.MoviesSD);
+ AddCategoryMapping(10, TorznabCatType.Console);
+ AddCategoryMapping(9, TorznabCatType.PCGames);
+ //AddCategoryMapping(17, TorznabCatType); Linux No cat
+ AddCategoryMapping(22, TorznabCatType.PCPhoneOther); //Apps/mobile
+ AddCategoryMapping(8, TorznabCatType.PC);
+ AddCategoryMapping(21, TorznabCatType.TVHD);
+ AddCategoryMapping(23, TorznabCatType.TVSD);
+ AddCategoryMapping(13, TorznabCatType.TVSport);
+ AddCategoryMapping(14, TorznabCatType.TV);
+ AddCategoryMapping(12, TorznabCatType.AudioVideo);
+ AddCategoryMapping(7, TorznabCatType.XXX);
+ }
+
+ public async Task ApplyConfiguration(JToken configJson)
+ {
+ configData.LoadValuesFromJson(configJson);
+ var pairs = new Dictionary {
+ { "username", configData.Username.Value },
+ { "password", configData.Password.Value }
+ };
+
+ var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl);
+ await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
+ {
+ CQ dom = result.Content;
+ var errorMessage = dom[".main"].Text().Trim();
+ throw new ExceptionWithConfigData(errorMessage, configData);
+ });
+ return IndexerConfigurationStatus.RequiresTesting;
+ }
+
+ public async Task> PerformQuery(TorznabQuery query)
+ {
+ var releases = new List();
+ var searchUrl = BrowseUrl;
+ var searchString = query.GetQueryString();
+
+ var cats = MapTorznabCapsToTrackers(query);
+ string cat = "0";
+ if (cats.Count == 1)
+ {
+ cat = cats[0];
+ }
+
+ if (!string.IsNullOrWhiteSpace(searchString) || cat != "0")
+ searchUrl += string.Format("?search={0}&cat={1}&searchin=0&sort=0", HttpUtility.UrlEncode(searchString), cat);
+
+
+
+ var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);
+ var results = response.Content;
+ try
+ {
+ CQ dom = results;
+ var rows = dom[".torrentrow"];
+ foreach (var row in rows)
+ {
+ var release = new ReleaseInfo();
+ var qRow = row.Cq();
+ var qTitleLink = qRow.Find(".torrenttable:eq(1) a").First();
+ release.Title = qRow.Find(".torrenttable:eq(1) a b").Text().Trim();
+ release.Description = release.Title;
+ release.Guid = new Uri(SiteLink + qTitleLink.Attr("href"));
+ release.Comments = release.Guid;
+
+ //22:05:3716/02/2013
+ var dateStr = qRow.Find(".torrenttable:eq(5)").Text().Trim();
+ release.PublishDate = DateTime.ParseExact(dateStr, "H:mm:ssdd/MM/yyyy", CultureInfo.InvariantCulture).AddHours(-2);
+
+ var qLink = qRow.Find(".torrenttable:eq(2) a").First();
+ release.Link = new Uri(SiteLink + qLink.Attr("href"));
+
+ var sizeStr = qRow.Find(".torrenttable:eq(6)").Text().Trim();
+ release.Size = ReleaseInfo.GetBytes(sizeStr);
+
+ release.Seeders = ParseUtil.CoerceInt(qRow.Find(".torrenttable:eq(8)").Text().Trim());
+ release.Peers = ParseUtil.CoerceInt(qRow.Find(".torrenttable:eq(9)").Text().Trim()) + release.Seeders;
+
+ var catId = qRow.Find(".torrenttable:eq(0) a").First().Attr("href").Substring(15);
+ release.Category = MapTrackerCatToNewznab(catId);
+
+ // Skip other
+ if (release.Category != 0)
+ {
+ // Skip Romanian releases
+ if (release.Category == TorznabCatType.MoviesForeign.ID && !configData.IncludeRomanianReleases.Value)
+ continue;
+
+ releases.Add(release);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(results, ex);
+ }
+
+ return releases;
+ }
+ }
+}
diff --git a/src/Jackett/Indexers/RUTor.cs b/src/Jackett/Indexers/RUTor.cs
index 91b136437..cbee08d1e 100644
--- a/src/Jackett/Indexers/RUTor.cs
+++ b/src/Jackett/Indexers/RUTor.cs
@@ -1,232 +1,233 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Jackett.Models;
-using Newtonsoft.Json.Linq;
-using NLog;
-using Jackett.Utils;
-using System.Net;
-using System.Net.Http;
-using CsQuery;
-using System.Web;
-using Jackett.Services;
-using Jackett.Utils.Clients;
-using System.Text.RegularExpressions;
-using Jackett.Models.IndexerConfig;
-using System.Globalization;
-using Newtonsoft.Json;
-
-namespace Jackett.Indexers
-{
- public class RuTor : BaseIndexer, IIndexer
- {
- private string SearchUrl { get { return SiteLink + "search/0/{0}/000/0/{1}"; } }
- private string BrowseUrl { get { return SiteLink + "browse/0/{0}/0/0"; } }
- readonly static string defaultSiteLink = "http://rutor.org/";
-
- new ConfigurationDataRuTor configData
- {
- get { return (ConfigurationDataRuTor)base.configData; }
- set { base.configData = value; }
- }
-
- public RuTor(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
- : base(name: "RUTor",
- description: "Свободный торрент трекер",
- link: "http://rutor.org/",
- caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
- manager: i,
- client: wc,
- logger: l,
- p: ps,
- configData: new ConfigurationDataRuTor(defaultSiteLink))
- {
- TorznabCaps.Categories.Add(TorznabCatType.TVAnime);
- TorznabCaps.Categories.Add(TorznabCatType.Movies);
- TorznabCaps.Categories.Add(TorznabCatType.Audio);
- TorznabCaps.Categories.Add(TorznabCatType.Books);
- }
-
- public async Task ApplyConfiguration(JToken configJson)
- {
- configData.LoadValuesFromJson(configJson);
- var oldConfig = configData;
- var releases = await PerformQuery(new TorznabQuery());
-
- await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
- {
- configData = oldConfig;
- throw new Exception("Could not find releases from this URL");
- });
-
- return IndexerConfigurationStatus.RequiresTesting;
- }
-
-
- protected override void SaveConfig()
- {
- indexerService.SaveConfig(this as IIndexer, JsonConvert.SerializeObject(configData));
- }
-
- // Override to load legacy config format
- public override void LoadFromSavedConfiguration(JToken jsonConfig)
- {
- var json = jsonConfig.ToString();
- configData = JsonConvert.DeserializeObject(json);
- IsConfigured = true;
- }
-
- private readonly int CAT_ANY = 0;
- private readonly int CAT_FOREIGN_MOVIE = 1;
- // private readonly int CAT_OUR_MOVIES = 5;
- // private readonly int CAT_POP_SCIFI_MOVIES = 12;
- private readonly int CAT_TV_SERIES = 4;
- // private readonly int CAT_TV = 6;
- // private readonly int CAT_ANIMATION = 7;
- private readonly int CAT_ANIME = 10;
- private readonly int CAT_MUSIC = 2;
- // private readonly int CAT_GAMES = 8;
- // private readonly int CAT_SOFTWARE = 9;
- // private readonly int CAT_SPORTS_HEALTH = 13;
- // private readonly int CAT_HUMOR = 15;
- // private readonly int CAT_ECONOMY_LIFE = 14;
- private readonly int CAT_BOOKS = 11;
- // private readonly int CAT_OTHER = 3;
-
- public async Task> PerformQuery(TorznabQuery query)
- {
- var releases = new List();
- var searchString = query.GetQueryString();
- var searchCategory = CAT_ANY;
-
- if (query.Categories.Contains(TorznabCatType.TV.ID) ||
- query.Categories.Contains(TorznabCatType.TVHD.ID) ||
- query.Categories.Contains(TorznabCatType.TVSD.ID))
- {
- searchCategory = CAT_TV_SERIES;
- }
-
- if ((searchCategory == CAT_ANY) &&
- (query.Categories.Contains(TorznabCatType.Movies.ID) ||
- query.Categories.Contains(TorznabCatType.MoviesForeign.ID) ||
- query.Categories.Contains(TorznabCatType.MoviesHD.ID) ||
- query.Categories.Contains(TorznabCatType.MoviesSD.ID)))
- {
- searchCategory = CAT_FOREIGN_MOVIE;
- }
-
- if ((searchCategory == CAT_ANY) &&
- (query.Categories.Contains(TorznabCatType.TVAnime.ID)))
- {
- searchCategory = CAT_ANIME;
- }
-
- if ((searchCategory == CAT_ANY) &&
- (query.Categories.Contains(TorznabCatType.Books.ID)))
- {
- searchCategory = CAT_BOOKS;
- }
-
- if ((searchCategory == CAT_ANY) &&
- (query.Categories.Contains(TorznabCatType.Audio.ID) ||
- query.Categories.Contains(TorznabCatType.AudioLossless.ID) ||
- query.Categories.Contains(TorznabCatType.AudioMP3.ID)))
- {
- searchCategory = CAT_MUSIC;
- }
-
- string queryUrl = string.Empty;
- if (string.IsNullOrWhiteSpace(searchString))
- {
- queryUrl = string.Format(BrowseUrl, searchCategory);
- }
- else
- {
- queryUrl = string.Format(SearchUrl, searchCategory, HttpUtility.UrlEncode(searchString.Trim()));
- }
-
- var results = await RequestStringWithCookiesAndRetry(queryUrl, string.Empty);
- try
- {
- CQ dom = results.Content;
- var rows = dom["#index table tr"];
- foreach (var row in rows.Skip(1))
- {
- var release = new ReleaseInfo();
-
- release.MinimumRatio = 1;
- release.MinimumSeedTime = 172800;
-
- var date = StringUtil.StripNonAlphaNumeric(row.Cq().Find("td:eq(0)").Text().Trim()
- .Replace("Янв", "01")
- .Replace("Фев", "02")
- .Replace("Мар", "03")
- .Replace("Апр", "04")
- .Replace("Май", "05")
- .Replace("Июн", "06")
- .Replace("Июл", "07")
- .Replace("Авг", "08")
- .Replace("Сен", "09")
- .Replace("Окт", "10")
- .Replace("Ноя", "11")
- .Replace("Дек", "12"));
-
- release.PublishDate = DateTime.ParseExact(date, "ddMMyy", CultureInfo.InvariantCulture);
-
- var hasTorrent = row.Cq().Find("td:eq(1) a").Length == 3;
- var titleIndex = 1;
- if (hasTorrent)
- titleIndex++;
-
- release.Title = row.Cq().Find("td:eq(" + titleIndex + ")").Text().Trim();
- if (configData.StripRussian.Value)
- {
- var split = release.Title.IndexOf('/');
- if (split > -1)
- {
- release.Title = release.Title.Substring(split + 1).Trim();
- }
- }
-
- release.Description = release.Title;
-
- var hasComments = row.Cq().Find("td:eq(2) img").Length > 0;
- var sizeCol = 2;
-
- if (hasComments)
- sizeCol++;
-
- var sizeStr = StringUtil.StripRegex(row.Cq().Find("td:eq(" + sizeCol + ")").Text(), "[^a-zA-Z0-9\\. -]", " ").Trim();
- string[] sizeSplit = sizeStr.Split(' ');
- release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
-
- release.Seeders = ParseUtil.CoerceInt(row.Cq().Find(".green").Text().Trim());
- release.Peers = ParseUtil.CoerceInt(row.Cq().Find(".red").Text().Trim()) + release.Seeders;
-
- release.Guid = new Uri(configData.Url.Value + row.Cq().Find("td:eq(1) a:eq(" + titleIndex + ")").Attr("href").Substring(1));
- release.Comments = release.Guid;
-
- if (hasTorrent)
- {
- release.Link = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href"));
- release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(1)").Attr("href"));
- }
- else
- {
- release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href"));
- }
-
- releases.Add(release);
- }
- }
- catch (Exception ex)
- {
- OnParseError(results.Content, ex);
- }
-
- return releases;
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Jackett.Models;
+using Newtonsoft.Json.Linq;
+using NLog;
+using Jackett.Utils;
+using System.Net;
+using System.Net.Http;
+using CsQuery;
+using System.Web;
+using Jackett.Services;
+using Jackett.Utils.Clients;
+using System.Text.RegularExpressions;
+using Jackett.Models.IndexerConfig;
+using System.Globalization;
+using Newtonsoft.Json;
+using Jackett.Models.IndexerConfig.Bespoke;
+
+namespace Jackett.Indexers
+{
+ public class RuTor : BaseIndexer, IIndexer
+ {
+ private string SearchUrl { get { return SiteLink + "search/0/{0}/000/0/{1}"; } }
+ private string BrowseUrl { get { return SiteLink + "browse/0/{0}/0/0"; } }
+ readonly static string defaultSiteLink = "http://rutor.org/";
+
+ new ConfigurationDataRuTor configData
+ {
+ get { return (ConfigurationDataRuTor)base.configData; }
+ set { base.configData = value; }
+ }
+
+ public RuTor(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
+ : base(name: "RUTor",
+ description: "Свободный торрент трекер",
+ link: "http://rutor.org/",
+ caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
+ manager: i,
+ client: wc,
+ logger: l,
+ p: ps,
+ configData: new ConfigurationDataRuTor(defaultSiteLink))
+ {
+ TorznabCaps.Categories.Add(TorznabCatType.TVAnime);
+ TorznabCaps.Categories.Add(TorznabCatType.Movies);
+ TorznabCaps.Categories.Add(TorznabCatType.Audio);
+ TorznabCaps.Categories.Add(TorznabCatType.Books);
+ }
+
+ public async Task ApplyConfiguration(JToken configJson)
+ {
+ configData.LoadValuesFromJson(configJson);
+ var oldConfig = configData;
+ var releases = await PerformQuery(new TorznabQuery());
+
+ await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
+ {
+ configData = oldConfig;
+ throw new Exception("Could not find releases from this URL");
+ });
+
+ return IndexerConfigurationStatus.RequiresTesting;
+ }
+
+
+ protected override void SaveConfig()
+ {
+ indexerService.SaveConfig(this as IIndexer, JsonConvert.SerializeObject(configData));
+ }
+
+ // Override to load legacy config format
+ public override void LoadFromSavedConfiguration(JToken jsonConfig)
+ {
+ var json = jsonConfig.ToString();
+ configData = JsonConvert.DeserializeObject(json);
+ IsConfigured = true;
+ }
+
+ private readonly int CAT_ANY = 0;
+ private readonly int CAT_FOREIGN_MOVIE = 1;
+ // private readonly int CAT_OUR_MOVIES = 5;
+ // private readonly int CAT_POP_SCIFI_MOVIES = 12;
+ private readonly int CAT_TV_SERIES = 4;
+ // private readonly int CAT_TV = 6;
+ // private readonly int CAT_ANIMATION = 7;
+ private readonly int CAT_ANIME = 10;
+ private readonly int CAT_MUSIC = 2;
+ // private readonly int CAT_GAMES = 8;
+ // private readonly int CAT_SOFTWARE = 9;
+ // private readonly int CAT_SPORTS_HEALTH = 13;
+ // private readonly int CAT_HUMOR = 15;
+ // private readonly int CAT_ECONOMY_LIFE = 14;
+ private readonly int CAT_BOOKS = 11;
+ // private readonly int CAT_OTHER = 3;
+
+ public async Task> PerformQuery(TorznabQuery query)
+ {
+ var releases = new List();
+ var searchString = query.GetQueryString();
+ var searchCategory = CAT_ANY;
+
+ if (query.Categories.Contains(TorznabCatType.TV.ID) ||
+ query.Categories.Contains(TorznabCatType.TVHD.ID) ||
+ query.Categories.Contains(TorznabCatType.TVSD.ID))
+ {
+ searchCategory = CAT_TV_SERIES;
+ }
+
+ if ((searchCategory == CAT_ANY) &&
+ (query.Categories.Contains(TorznabCatType.Movies.ID) ||
+ query.Categories.Contains(TorznabCatType.MoviesForeign.ID) ||
+ query.Categories.Contains(TorznabCatType.MoviesHD.ID) ||
+ query.Categories.Contains(TorznabCatType.MoviesSD.ID)))
+ {
+ searchCategory = CAT_FOREIGN_MOVIE;
+ }
+
+ if ((searchCategory == CAT_ANY) &&
+ (query.Categories.Contains(TorznabCatType.TVAnime.ID)))
+ {
+ searchCategory = CAT_ANIME;
+ }
+
+ if ((searchCategory == CAT_ANY) &&
+ (query.Categories.Contains(TorznabCatType.Books.ID)))
+ {
+ searchCategory = CAT_BOOKS;
+ }
+
+ if ((searchCategory == CAT_ANY) &&
+ (query.Categories.Contains(TorznabCatType.Audio.ID) ||
+ query.Categories.Contains(TorznabCatType.AudioLossless.ID) ||
+ query.Categories.Contains(TorznabCatType.AudioMP3.ID)))
+ {
+ searchCategory = CAT_MUSIC;
+ }
+
+ string queryUrl = string.Empty;
+ if (string.IsNullOrWhiteSpace(searchString))
+ {
+ queryUrl = string.Format(BrowseUrl, searchCategory);
+ }
+ else
+ {
+ queryUrl = string.Format(SearchUrl, searchCategory, HttpUtility.UrlEncode(searchString.Trim()));
+ }
+
+ var results = await RequestStringWithCookiesAndRetry(queryUrl, string.Empty);
+ try
+ {
+ CQ dom = results.Content;
+ var rows = dom["#index table tr"];
+ foreach (var row in rows.Skip(1))
+ {
+ var release = new ReleaseInfo();
+
+ release.MinimumRatio = 1;
+ release.MinimumSeedTime = 172800;
+
+ var date = StringUtil.StripNonAlphaNumeric(row.Cq().Find("td:eq(0)").Text().Trim()
+ .Replace("Янв", "01")
+ .Replace("Фев", "02")
+ .Replace("Мар", "03")
+ .Replace("Апр", "04")
+ .Replace("Май", "05")
+ .Replace("Июн", "06")
+ .Replace("Июл", "07")
+ .Replace("Авг", "08")
+ .Replace("Сен", "09")
+ .Replace("Окт", "10")
+ .Replace("Ноя", "11")
+ .Replace("Дек", "12"));
+
+ release.PublishDate = DateTime.ParseExact(date, "ddMMyy", CultureInfo.InvariantCulture);
+
+ var hasTorrent = row.Cq().Find("td:eq(1) a").Length == 3;
+ var titleIndex = 1;
+ if (hasTorrent)
+ titleIndex++;
+
+ release.Title = row.Cq().Find("td:eq(" + titleIndex + ")").Text().Trim();
+ if (configData.StripRussian.Value)
+ {
+ var split = release.Title.IndexOf('/');
+ if (split > -1)
+ {
+ release.Title = release.Title.Substring(split + 1).Trim();
+ }
+ }
+
+ release.Description = release.Title;
+
+ var hasComments = row.Cq().Find("td:eq(2) img").Length > 0;
+ var sizeCol = 2;
+
+ if (hasComments)
+ sizeCol++;
+
+ var sizeStr = StringUtil.StripRegex(row.Cq().Find("td:eq(" + sizeCol + ")").Text(), "[^a-zA-Z0-9\\. -]", " ").Trim();
+ string[] sizeSplit = sizeStr.Split(' ');
+ release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
+
+ release.Seeders = ParseUtil.CoerceInt(row.Cq().Find(".green").Text().Trim());
+ release.Peers = ParseUtil.CoerceInt(row.Cq().Find(".red").Text().Trim()) + release.Seeders;
+
+ release.Guid = new Uri(configData.Url.Value + row.Cq().Find("td:eq(1) a:eq(" + titleIndex + ")").Attr("href").Substring(1));
+ release.Comments = release.Guid;
+
+ if (hasTorrent)
+ {
+ release.Link = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href"));
+ release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(1)").Attr("href"));
+ }
+ else
+ {
+ release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href"));
+ }
+
+ releases.Add(release);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(results.Content, ex);
+ }
+
+ return releases;
+ }
+ }
+}
diff --git a/src/Jackett/Indexers/Shazbat.cs b/src/Jackett/Indexers/Shazbat.cs
index a9a636ee1..a8ff134e1 100644
--- a/src/Jackett/Indexers/Shazbat.cs
+++ b/src/Jackett/Indexers/Shazbat.cs
@@ -17,6 +17,8 @@ using System.Web;
using Jackett.Models.IndexerConfig;
using System.Globalization;
using System.Text.RegularExpressions;
+using System.Xml.Linq;
+using System.Xml.XPath;
namespace Jackett.Indexers
{
@@ -25,10 +27,11 @@ namespace Jackett.Indexers
private string LoginUrl { get { return SiteLink + "login"; } }
private string SearchUrl { get { return SiteLink + "search"; } }
private string TorrentsUrl { get { return SiteLink + "torrents"; } }
+ private string RSSProfile { get { return SiteLink + "rss_feeds"; } }
- new ConfigurationDataBasicLogin configData
+ new ConfigurationDataBasicLoginWithRSS configData
{
- get { return (ConfigurationDataBasicLogin)base.configData; }
+ get { return (ConfigurationDataBasicLoginWithRSS)base.configData; }
set { base.configData = value; }
}
@@ -43,7 +46,7 @@ namespace Jackett.Indexers
client: c,
logger: l,
p: ps,
- configData: new ConfigurationDataBasicLogin())
+ configData: new ConfigurationDataBasicLoginWithRSS())
{
}
@@ -67,6 +70,15 @@ namespace Jackett.Indexers
throw new ExceptionWithConfigData("The username and password entered do not match.", configData);
});
+ var rssProfile = await RequestStringWithCookiesAndRetry(RSSProfile);
+ CQ rssDom = rssProfile.Content;
+ configData.RSSKey.Value = rssDom.Find(".col-sm-9:eq(0)").Text().Trim();
+ if (string.IsNullOrWhiteSpace(configData.RSSKey.Value))
+ {
+ throw new ExceptionWithConfigData("Failed to find RSS key.", configData);
+ }
+
+ SaveConfig();
return IndexerConfigurationStatus.RequiresTesting;
}
@@ -87,64 +99,115 @@ namespace Jackett.Indexers
};
results = await PostDataWithCookiesAndRetry(SearchUrl, pairs, null, TorrentsUrl);
+
+ try
+ {
+ CQ dom = results.Content;
+ var rows = dom["#torrent-table tr"];
+
+ if (!string.IsNullOrWhiteSpace(queryString))
+ {
+ rows = dom["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"));
+
+ 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?
+
+ releases.Add(release);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(results.Content, ex);
+ }
}
else
{
- var pairs = new Dictionary {
- { "portlet", "true"}
- };
+ var rssUrl = SiteLink + "rss/recent?passkey=" + configData.RSSKey.Value;
- 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))
+ results = await RequestStringWithCookiesAndRetry(rssUrl);
+ try
{
- 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"))
+ var doc = XDocument.Parse(results.Content);
+ foreach (var result in doc.Descendants("item"))
{
- release.Category = TorznabCatType.TVHD.ID;
- } else
- {
- release.Category = TorznabCatType.TVSD.ID;
+ var xTitle = result.Element("title").Value;
+ var xLink = result.Element("link").Value;
+ var xGUID = result.Element("guid").Value;
+ var xDesc = result.Element("description").Value;
+ var xDate = result.Element("pubDate").Value;
+ var release = new ReleaseInfo();
+ release.Guid =release.Link = new Uri(xLink);
+ release.MinimumRatio = 1;
+ release.Seeders = 1; // We are not supplied with peer info so just mark it as one.
+ foreach (var element in xDesc.Split(";".ToCharArray()))
+ {
+ var split = element.IndexOf(':');
+ if (split > -1)
+ {
+ var key = element.Substring(0, split).Trim();
+ var value = element.Substring(split+1).Trim();
+
+ switch (key)
+ {
+ case "Filename":
+ release.Title = release.Description = value;
+ break;
+ }
+ }
+ }
+
+ //"Thu, 24 Sep 2015 18:07:07 +0000"
+ release.PublishDate = DateTime.ParseExact(xDate, "ddd, dd MMM yyyy HH:mm:ss +0000", CultureInfo.InvariantCulture);
+
+ if (!string.IsNullOrWhiteSpace(release.Title))
+ {
+ releases.Add(release);
+ }
}
-
- releases.Add(release);
+ }
+ catch (Exception ex)
+ {
+ OnParseError(results.Content, ex);
}
}
- catch (Exception ex)
+
+ foreach(var release in releases)
{
- OnParseError(results.Content, ex);
+ if (release.Title.Contains("1080p") || release.Title.Contains("720p"))
+ {
+ release.Category = TorznabCatType.TVHD.ID;
+ }
+ else
+ {
+ release.Category = TorznabCatType.TVSD.ID;
+ }
}
return releases;
diff --git a/src/Jackett/Indexers/Strike.cs b/src/Jackett/Indexers/Strike.cs
index 18986602c..74bdf59cd 100644
--- a/src/Jackett/Indexers/Strike.cs
+++ b/src/Jackett/Indexers/Strike.cs
@@ -1,172 +1,173 @@
-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.Text;
-using System.Threading.Tasks;
-using System.Web;
-using Jackett.Models.IndexerConfig;
-using System.Collections.Specialized;
-
-namespace Jackett.Indexers
-{
- public class Strike : BaseIndexer, IIndexer
- {
- readonly static string defaultSiteLink = "https://getstrike.net/";
-
- private Uri BaseUri
- {
- get { return new Uri(configData.Url.Value); }
- set { configData.Url.Value = value.ToString(); }
- }
-
- private string SearchUrl { get { return BaseUri + "api/v2/torrents/search/?phrase={0}"; } }
- private string DownloadUrl { get { return BaseUri + "torrents/api/download/{0}.torrent"; } }
-
- new ConfigurationDataStrike configData
- {
- get { return (ConfigurationDataStrike)base.configData; }
- set { base.configData = value; }
- }
-
-
- public Strike(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
- : base(name: "Strike",
- description: "Torrent search engine",
- link: defaultSiteLink,
- caps: new TorznabCapabilities(),
- manager: i,
- client: wc,
- logger: l,
- p: ps,
- configData: new ConfigurationDataStrike(defaultSiteLink))
- {
- AddCategoryMapping("Anime", TorznabCatType.TVAnime);
- AddCategoryMapping("Applications", TorznabCatType.PC);
- AddCategoryMapping("Books", TorznabCatType.Books);
- AddCategoryMapping("Games", TorznabCatType.PCGames);
- AddCategoryMapping("Movies", TorznabCatType.Movies);
- AddCategoryMapping("TV", TorznabCatType.TV);
- AddCategoryMapping("XXX", TorznabCatType.XXX);
- AddCategoryMapping("Music", TorznabCatType.Audio);
-
- /*AddCategoryMapping("Movies:Highres Movies", TorznabCatType.MoviesHD);
- AddCategoryMapping("Movies:3D Movies", TorznabCatType.Movies3D);
- AddCategoryMapping("Books:Ebooks", TorznabCatType.BooksEbook);
- AddCategoryMapping("Books:Comics", TorznabCatType.BooksComics);
- AddCategoryMapping("Books:Audio Books", TorznabCatType.AudioAudiobook);
- AddCategoryMapping("Games:XBOX360", TorznabCatType.ConsoleXbox360);
- AddCategoryMapping("Games:Wii", TorznabCatType.ConsoleWii);
- AddCategoryMapping("Games:PSP", TorznabCatType.ConsolePSP);
- AddCategoryMapping("Games:PS3", TorznabCatType.ConsolePS3);
- AddCategoryMapping("Games:PC", TorznabCatType.PCGames);
- AddCategoryMapping("Games:Android", TorznabCatType.PCPhoneAndroid);
- AddCategoryMapping("Music:Mp3", TorznabCatType.AudioMP3);*/
- }
-
- public async Task ApplyConfiguration(JToken configJson)
- {
- configData.LoadValuesFromJson(configJson);
- var releases = await PerformQuery(new TorznabQuery());
-
- await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
- {
- throw new Exception("Could not find releases from this URL");
- });
-
- return IndexerConfigurationStatus.Completed;
- }
-
- // Override to load legacy config format
- public override void LoadFromSavedConfiguration(JToken jsonConfig)
- {
- if (jsonConfig is JObject)
- {
- BaseUri = new Uri(jsonConfig.Value("base_url"));
- SaveConfig();
- IsConfigured = true;
- return;
- }
-
- base.LoadFromSavedConfiguration(jsonConfig);
- }
-
- public async Task> PerformQuery(TorznabQuery query)
- {
- List releases = new List();
- var queryString = query.GetQueryString();
- var searchTerm = string.IsNullOrEmpty(queryString) ? DateTime.Now.Year.ToString() : queryString;
- var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchTerm));
-
- var trackerCategories = MapTorznabCapsToTrackers(query, mapChildrenCatsToParent: true);
-
- // This tracker can only search one cat at a time, otherwise search all and filter results
- if (trackerCategories.Count == 1)
- {
- episodeSearchUrl += "&category=" + trackerCategories[0];
- }
-
- var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
- try
- {
- var jResults = JObject.Parse(results.Content);
- foreach (JObject result in (JArray)jResults["torrents"])
- {
- var release = new ReleaseInfo();
-
- release.MinimumRatio = 1;
- release.MinimumSeedTime = 172800;
-
- if (trackerCategories.Count > 0 && !trackerCategories.Contains((string)result["torrent_category"]))
- {
- continue;
- }
- release.Category = MapTrackerCatToNewznab((string)result["torrent_category"]);
-
- release.Title = (string)result["torrent_title"];
- release.Description = release.Title;
- release.Seeders = (int)result["seeds"];
- release.Peers = (int)result["leeches"] + release.Seeders;
- release.Size = (long)result["size"];
-
- // "Apr 2, 2015", "Apr 12, 2015" (note the spacing)
- // some are unix timestamps, some are not.. :/
- var dateString = string.Join(" ", ((string)result["upload_date"]).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
- float dateVal;
- if (ParseUtil.TryCoerceFloat(dateString, out dateVal))
- release.PublishDate = DateTimeUtil.UnixTimestampToDateTime(dateVal);
- else
- release.PublishDate = DateTime.ParseExact(dateString, "MMM d, yyyy", CultureInfo.InvariantCulture);
-
- release.Guid = new Uri((string)result["page"]);
- release.Comments = release.Guid;
-
- release.InfoHash = (string)result["torrent_hash"];
- release.MagnetUri = new Uri((string)result["magnet_uri"]);
- release.Link = new Uri(string.Format(DownloadUrl, release.InfoHash));
-
- releases.Add(release);
- }
- }
- catch (Exception ex)
- {
- OnParseError(results.Content, ex);
- }
-
- return releases;
- }
-
- public override Task Download(Uri link)
- {
- throw new NotImplementedException();
- }
- }
-}
+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.Text;
+using System.Threading.Tasks;
+using System.Web;
+using Jackett.Models.IndexerConfig;
+using System.Collections.Specialized;
+using Jackett.Models.IndexerConfig.Bespoke;
+
+namespace Jackett.Indexers
+{
+ public class Strike : BaseIndexer, IIndexer
+ {
+ readonly static string defaultSiteLink = "https://getstrike.net/";
+
+ private Uri BaseUri
+ {
+ get { return new Uri(configData.Url.Value); }
+ set { configData.Url.Value = value.ToString(); }
+ }
+
+ private string SearchUrl { get { return BaseUri + "api/v2/torrents/search/?phrase={0}"; } }
+ private string DownloadUrl { get { return BaseUri + "torrents/api/download/{0}.torrent"; } }
+
+ new ConfigurationDataStrike configData
+ {
+ get { return (ConfigurationDataStrike)base.configData; }
+ set { base.configData = value; }
+ }
+
+
+ public Strike(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
+ : base(name: "Strike",
+ description: "Torrent search engine",
+ link: defaultSiteLink,
+ caps: new TorznabCapabilities(),
+ manager: i,
+ client: wc,
+ logger: l,
+ p: ps,
+ configData: new ConfigurationDataStrike(defaultSiteLink))
+ {
+ AddCategoryMapping("Anime", TorznabCatType.TVAnime);
+ AddCategoryMapping("Applications", TorznabCatType.PC);
+ AddCategoryMapping("Books", TorznabCatType.Books);
+ AddCategoryMapping("Games", TorznabCatType.PCGames);
+ AddCategoryMapping("Movies", TorznabCatType.Movies);
+ AddCategoryMapping("TV", TorznabCatType.TV);
+ AddCategoryMapping("XXX", TorznabCatType.XXX);
+ AddCategoryMapping("Music", TorznabCatType.Audio);
+
+ /*AddCategoryMapping("Movies:Highres Movies", TorznabCatType.MoviesHD);
+ AddCategoryMapping("Movies:3D Movies", TorznabCatType.Movies3D);
+ AddCategoryMapping("Books:Ebooks", TorznabCatType.BooksEbook);
+ AddCategoryMapping("Books:Comics", TorznabCatType.BooksComics);
+ AddCategoryMapping("Books:Audio Books", TorznabCatType.AudioAudiobook);
+ AddCategoryMapping("Games:XBOX360", TorznabCatType.ConsoleXbox360);
+ AddCategoryMapping("Games:Wii", TorznabCatType.ConsoleWii);
+ AddCategoryMapping("Games:PSP", TorznabCatType.ConsolePSP);
+ AddCategoryMapping("Games:PS3", TorznabCatType.ConsolePS3);
+ AddCategoryMapping("Games:PC", TorznabCatType.PCGames);
+ AddCategoryMapping("Games:Android", TorznabCatType.PCPhoneAndroid);
+ AddCategoryMapping("Music:Mp3", TorznabCatType.AudioMP3);*/
+ }
+
+ public async Task ApplyConfiguration(JToken configJson)
+ {
+ configData.LoadValuesFromJson(configJson);
+ var releases = await PerformQuery(new TorznabQuery());
+
+ await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
+ {
+ throw new Exception("Could not find releases from this URL");
+ });
+
+ return IndexerConfigurationStatus.Completed;
+ }
+
+ // Override to load legacy config format
+ public override void LoadFromSavedConfiguration(JToken jsonConfig)
+ {
+ if (jsonConfig is JObject)
+ {
+ BaseUri = new Uri(jsonConfig.Value("base_url"));
+ SaveConfig();
+ IsConfigured = true;
+ return;
+ }
+
+ base.LoadFromSavedConfiguration(jsonConfig);
+ }
+
+ public async Task> PerformQuery(TorznabQuery query)
+ {
+ List releases = new List();
+ var queryString = query.GetQueryString();
+ var searchTerm = string.IsNullOrEmpty(queryString) ? DateTime.Now.Year.ToString() : queryString;
+ var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchTerm));
+
+ var trackerCategories = MapTorznabCapsToTrackers(query, mapChildrenCatsToParent: true);
+
+ // This tracker can only search one cat at a time, otherwise search all and filter results
+ if (trackerCategories.Count == 1)
+ {
+ episodeSearchUrl += "&category=" + trackerCategories[0];
+ }
+
+ var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
+ try
+ {
+ var jResults = JObject.Parse(results.Content);
+ foreach (JObject result in (JArray)jResults["torrents"])
+ {
+ var release = new ReleaseInfo();
+
+ release.MinimumRatio = 1;
+ release.MinimumSeedTime = 172800;
+
+ if (trackerCategories.Count > 0 && !trackerCategories.Contains((string)result["torrent_category"]))
+ {
+ continue;
+ }
+ release.Category = MapTrackerCatToNewznab((string)result["torrent_category"]);
+
+ release.Title = (string)result["torrent_title"];
+ release.Description = release.Title;
+ release.Seeders = (int)result["seeds"];
+ release.Peers = (int)result["leeches"] + release.Seeders;
+ release.Size = (long)result["size"];
+
+ // "Apr 2, 2015", "Apr 12, 2015" (note the spacing)
+ // some are unix timestamps, some are not.. :/
+ var dateString = string.Join(" ", ((string)result["upload_date"]).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
+ float dateVal;
+ if (ParseUtil.TryCoerceFloat(dateString, out dateVal))
+ release.PublishDate = DateTimeUtil.UnixTimestampToDateTime(dateVal);
+ else
+ release.PublishDate = DateTime.ParseExact(dateString, "MMM d, yyyy", CultureInfo.InvariantCulture);
+
+ release.Guid = new Uri((string)result["page"]);
+ release.Comments = release.Guid;
+
+ release.InfoHash = (string)result["torrent_hash"];
+ release.MagnetUri = new Uri((string)result["magnet_uri"]);
+ release.Link = new Uri(string.Format(DownloadUrl, release.InfoHash));
+
+ releases.Add(release);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(results.Content, ex);
+ }
+
+ return releases;
+ }
+
+ public override Task Download(Uri link)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Jackett/Indexers/nCore.cs b/src/Jackett/Indexers/nCore.cs
index 8f4979896..98c55d2e5 100644
--- a/src/Jackett/Indexers/nCore.cs
+++ b/src/Jackett/Indexers/nCore.cs
@@ -1,168 +1,169 @@
-using CsQuery;
-using Jackett.Models;
-using Jackett.Services;
-using Jackett.Utils;
-using Jackett.Utils.Clients;
-using Newtonsoft.Json;
-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.Text;
-using System.Threading.Tasks;
-using System.Web;
-using Jackett.Models.IndexerConfig;
-
-namespace Jackett.Indexers
-{
- public class NCore : BaseIndexer, IIndexer
- {
- private string LoginUrl { get { return SiteLink + "login.php"; } }
- private string SearchUrl { get { return SiteLink + "torrents.php"; } }
-
- new ConfigurationDataNCore configData
- {
- get { return (ConfigurationDataNCore)base.configData; }
- set { base.configData = value; }
- }
-
- public NCore(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
- : base(name: "nCore",
- description: "A Hungarian private torrent site.",
- link: "https://ncore.cc/",
- caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
- manager: i,
- client: wc,
- logger: l,
- p: ps,
- configData: new ConfigurationDataNCore())
- {
- }
-
- public async Task ApplyConfiguration(JToken configJson)
- {
- configData.LoadValuesFromJson(configJson);
-
- if (configData.Hungarian.Value == false && configData.English.Value == false)
- throw new ExceptionWithConfigData("Please select atleast one language.", configData);
-
- var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
- var pairs = new Dictionary {
- { "nev", configData.Username.Value },
- { "pass", configData.Password.Value },
- { "ne_leptessen_ki", "1"},
- { "set_lang", "en" },
- { "submitted", "1" },
- { "submit", "Access!" }
- };
-
- var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, referer: SiteLink);
- await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("profile.php"), () =>
- {
- CQ dom = result.Content;
- var messageEl = dom["#hibauzenet table tbody tr"];
- var msgContainer = messageEl.Get(0).ChildElements.ElementAt(1);
- var errorMessage = msgContainer != null ? msgContainer.InnerText : "Error while trying to login.";
- throw new ExceptionWithConfigData(errorMessage, configData);
- });
-
- return IndexerConfigurationStatus.RequiresTesting;
- }
-
- List> CreateKeyValueList(params string[][] keyValues)
- {
- var list = new List>();
- foreach (var d in keyValues)
- {
- list.Add(new KeyValuePair(d[0], d[1]));
- }
- return list;
- }
-
- private IEnumerable> GetSearchFormData(string searchString)
- {
- const string searchTypeKey = "kivalasztott_tipus[]";
- var baseList = CreateKeyValueList(
- new[] { "nyit_sorozat_resz", "true" },
- new[] { "miben", "name" },
- new[] { "tipus", "kivalasztottak_kozott" },
- new[] { "submit.x", "1" },
- new[] { "submit.y", "1" },
- new[] { "submit", "Ok" },
- new[] { "mire", searchString }
- );
-
- if (configData.English.Value)
- {
- baseList.AddRange(CreateKeyValueList(
- new[] { searchTypeKey, "xvidser" },
- new[] { searchTypeKey, "dvdser" },
- new[] { searchTypeKey, "hdser" }
- ));
- }
-
- if (configData.Hungarian.Value)
- {
- baseList.AddRange(CreateKeyValueList(
- new[] { searchTypeKey, "xvidser_hun" },
- new[] { searchTypeKey, "dvdser_hun" },
- new[] { searchTypeKey, "hdser_hun" }
- ));
- }
- return baseList;
- }
-
- public async Task> PerformQuery(TorznabQuery query)
- {
- var releases = new List();
- var results = await PostDataWithCookiesAndRetry(SearchUrl, GetSearchFormData(query.GetQueryString()));
-
- try
- {
- CQ dom = results.Content;
-
- ReleaseInfo release;
- var rows = dom[".box_torrent_all"].Find(".box_torrent");
-
- foreach (var row in rows)
- {
- CQ qRow = row.Cq();
-
- release = new ReleaseInfo();
- var torrentTxt = qRow.Find(".torrent_txt").Find("a").Get(0);
- if (torrentTxt == null) continue;
- release.Title = torrentTxt.GetAttribute("title");
- release.Description = release.Title;
- release.MinimumRatio = 1;
- release.MinimumSeedTime = 172800;
-
- string downloadLink = SiteLink + torrentTxt.GetAttribute("href");
- string downloadId = downloadLink.Substring(downloadLink.IndexOf("&id=") + 4);
-
- release.Link = new Uri(SiteLink.ToString() + "torrents.php?action=download&id=" + downloadId);
- release.Comments = new Uri(SiteLink.ToString() + "torrents.php?action=details&id=" + downloadId);
- release.Guid = new Uri(release.Comments.ToString() + "#comments"); ;
- release.Seeders = ParseUtil.CoerceInt(qRow.Find(".box_s2").Find("a").First().Text());
- release.Peers = ParseUtil.CoerceInt(qRow.Find(".box_l2").Find("a").First().Text()) + release.Seeders;
- release.PublishDate = DateTime.Parse(qRow.Find(".box_feltoltve2").Get(0).InnerHTML.Replace("
", " "), CultureInfo.InvariantCulture);
- string[] sizeSplit = qRow.Find(".box_meret2").Get(0).InnerText.Split(' ');
- release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
-
- releases.Add(release);
- }
- }
- catch (Exception ex)
- {
- OnParseError(results.Content, ex);
- }
-
-
- return releases.ToArray();
- }
-
- }
+using CsQuery;
+using Jackett.Models;
+using Jackett.Services;
+using Jackett.Utils;
+using Jackett.Utils.Clients;
+using Newtonsoft.Json;
+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.Text;
+using System.Threading.Tasks;
+using System.Web;
+using Jackett.Models.IndexerConfig;
+using Jackett.Models.IndexerConfig.Bespoke;
+
+namespace Jackett.Indexers
+{
+ public class NCore : BaseIndexer, IIndexer
+ {
+ private string LoginUrl { get { return SiteLink + "login.php"; } }
+ private string SearchUrl { get { return SiteLink + "torrents.php"; } }
+
+ new ConfigurationDataNCore configData
+ {
+ get { return (ConfigurationDataNCore)base.configData; }
+ set { base.configData = value; }
+ }
+
+ public NCore(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
+ : base(name: "nCore",
+ description: "A Hungarian private torrent site.",
+ link: "https://ncore.cc/",
+ caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
+ manager: i,
+ client: wc,
+ logger: l,
+ p: ps,
+ configData: new ConfigurationDataNCore())
+ {
+ }
+
+ public async Task ApplyConfiguration(JToken configJson)
+ {
+ configData.LoadValuesFromJson(configJson);
+
+ if (configData.Hungarian.Value == false && configData.English.Value == false)
+ throw new ExceptionWithConfigData("Please select atleast one language.", configData);
+
+ var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
+ var pairs = new Dictionary {
+ { "nev", configData.Username.Value },
+ { "pass", configData.Password.Value },
+ { "ne_leptessen_ki", "1"},
+ { "set_lang", "en" },
+ { "submitted", "1" },
+ { "submit", "Access!" }
+ };
+
+ var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, referer: SiteLink);
+ await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("profile.php"), () =>
+ {
+ CQ dom = result.Content;
+ var messageEl = dom["#hibauzenet table tbody tr"];
+ var msgContainer = messageEl.Get(0).ChildElements.ElementAt(1);
+ var errorMessage = msgContainer != null ? msgContainer.InnerText : "Error while trying to login.";
+ throw new ExceptionWithConfigData(errorMessage, configData);
+ });
+
+ return IndexerConfigurationStatus.RequiresTesting;
+ }
+
+ List> CreateKeyValueList(params string[][] keyValues)
+ {
+ var list = new List>();
+ foreach (var d in keyValues)
+ {
+ list.Add(new KeyValuePair(d[0], d[1]));
+ }
+ return list;
+ }
+
+ private IEnumerable> GetSearchFormData(string searchString)
+ {
+ const string searchTypeKey = "kivalasztott_tipus[]";
+ var baseList = CreateKeyValueList(
+ new[] { "nyit_sorozat_resz", "true" },
+ new[] { "miben", "name" },
+ new[] { "tipus", "kivalasztottak_kozott" },
+ new[] { "submit.x", "1" },
+ new[] { "submit.y", "1" },
+ new[] { "submit", "Ok" },
+ new[] { "mire", searchString }
+ );
+
+ if (configData.English.Value)
+ {
+ baseList.AddRange(CreateKeyValueList(
+ new[] { searchTypeKey, "xvidser" },
+ new[] { searchTypeKey, "dvdser" },
+ new[] { searchTypeKey, "hdser" }
+ ));
+ }
+
+ if (configData.Hungarian.Value)
+ {
+ baseList.AddRange(CreateKeyValueList(
+ new[] { searchTypeKey, "xvidser_hun" },
+ new[] { searchTypeKey, "dvdser_hun" },
+ new[] { searchTypeKey, "hdser_hun" }
+ ));
+ }
+ return baseList;
+ }
+
+ public async Task> PerformQuery(TorznabQuery query)
+ {
+ var releases = new List();
+ var results = await PostDataWithCookiesAndRetry(SearchUrl, GetSearchFormData(query.GetQueryString()));
+
+ try
+ {
+ CQ dom = results.Content;
+
+ ReleaseInfo release;
+ var rows = dom[".box_torrent_all"].Find(".box_torrent");
+
+ foreach (var row in rows)
+ {
+ CQ qRow = row.Cq();
+
+ release = new ReleaseInfo();
+ var torrentTxt = qRow.Find(".torrent_txt").Find("a").Get(0);
+ if (torrentTxt == null) continue;
+ release.Title = torrentTxt.GetAttribute("title");
+ release.Description = release.Title;
+ release.MinimumRatio = 1;
+ release.MinimumSeedTime = 172800;
+
+ string downloadLink = SiteLink + torrentTxt.GetAttribute("href");
+ string downloadId = downloadLink.Substring(downloadLink.IndexOf("&id=") + 4);
+
+ release.Link = new Uri(SiteLink.ToString() + "torrents.php?action=download&id=" + downloadId);
+ release.Comments = new Uri(SiteLink.ToString() + "torrents.php?action=details&id=" + downloadId);
+ release.Guid = new Uri(release.Comments.ToString() + "#comments"); ;
+ release.Seeders = ParseUtil.CoerceInt(qRow.Find(".box_s2").Find("a").First().Text());
+ release.Peers = ParseUtil.CoerceInt(qRow.Find(".box_l2").Find("a").First().Text()) + release.Seeders;
+ release.PublishDate = DateTime.Parse(qRow.Find(".box_feltoltve2").Get(0).InnerHTML.Replace("
", " "), CultureInfo.InvariantCulture);
+ string[] sizeSplit = qRow.Find(".box_meret2").Get(0).InnerText.Split(' ');
+ release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
+
+ releases.Add(release);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(results.Content, ex);
+ }
+
+
+ return releases.ToArray();
+ }
+
+ }
}
\ No newline at end of file
diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj
index 81e2cde6d..2f128f417 100644
--- a/src/Jackett/Jackett.csproj
+++ b/src/Jackett/Jackett.csproj
@@ -185,6 +185,7 @@
+
@@ -195,6 +196,7 @@
+
@@ -222,14 +224,14 @@
-
+
-
+
-
-
+
+
@@ -265,7 +267,7 @@
-
+
@@ -429,6 +431,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationDataAnimeBytes.cs b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataAnimeBytes.cs
similarity index 90%
rename from src/Jackett/Models/IndexerConfig/ConfigurationDataAnimeBytes.cs
rename to src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataAnimeBytes.cs
index 47ddb275e..858239823 100644
--- a/src/Jackett/Models/IndexerConfig/ConfigurationDataAnimeBytes.cs
+++ b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataAnimeBytes.cs
@@ -1,22 +1,22 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jackett.Models.IndexerConfig
-{
- class ConfigurationDataAnimeBytes : ConfigurationDataBasicLogin
- {
- public BoolItem IncludeRaw { get; private set; }
- public DisplayItem DateWarning { get; private set; }
-
- public ConfigurationDataAnimeBytes()
- : base()
- {
- IncludeRaw = new BoolItem() { Name = "IncludeRaw", Value = false };
- DateWarning = new DisplayItem("This tracker does not supply upload dates so they are based off year of release.") { Name = "DateWarning" };
- }
- }
-}
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Models.IndexerConfig.Bespoke
+{
+ class ConfigurationDataAnimeBytes : ConfigurationDataBasicLogin
+ {
+ public BoolItem IncludeRaw { get; private set; }
+ public DisplayItem DateWarning { get; private set; }
+
+ public ConfigurationDataAnimeBytes()
+ : base()
+ {
+ IncludeRaw = new BoolItem() { Name = "IncludeRaw", Value = false };
+ DateWarning = new DisplayItem("This tracker does not supply upload dates so they are based off year of release.") { Name = "DateWarning" };
+ }
+ }
+}
diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationDataFileList.cs b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataFileList.cs
similarity index 90%
rename from src/Jackett/Models/IndexerConfig/ConfigurationDataFileList.cs
rename to src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataFileList.cs
index db58b34d0..54c475ddc 100644
--- a/src/Jackett/Models/IndexerConfig/ConfigurationDataFileList.cs
+++ b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataFileList.cs
@@ -1,22 +1,22 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jackett.Models.IndexerConfig
-{
- class ConfigurationDataFileList : ConfigurationDataBasicLogin
- {
- public BoolItem IncludeRomanianReleases { get; private set; }
- public DisplayItem CatWarning { get; private set; }
-
- public ConfigurationDataFileList()
- : base()
- {
- IncludeRomanianReleases = new BoolItem() { Name = "IncludeRomanianReleases", Value = false };
- CatWarning = new DisplayItem("When mapping TV ensure you add category 5000 in addition to 5030,5040.") { Name = "CatWarning" };
- }
- }
-}
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Models.IndexerConfig.Bespoke
+{
+ class ConfigurationDataFileList : ConfigurationDataBasicLogin
+ {
+ public BoolItem IncludeRomanianReleases { get; private set; }
+ public DisplayItem CatWarning { get; private set; }
+
+ public ConfigurationDataFileList()
+ : base()
+ {
+ IncludeRomanianReleases = new BoolItem() { Name = "IncludeRomanianReleases", Value = false };
+ CatWarning = new DisplayItem("When mapping TV ensure you add category 5000 in addition to 5030,5040.") { Name = "CatWarning" };
+ }
+ }
+}
diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationDataNCore.cs b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataNCore.cs
similarity index 95%
rename from src/Jackett/Models/IndexerConfig/ConfigurationDataNCore.cs
rename to src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataNCore.cs
index 1dc5aaad0..067a312d8 100644
--- a/src/Jackett/Models/IndexerConfig/ConfigurationDataNCore.cs
+++ b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataNCore.cs
@@ -1,62 +1,62 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jackett.Models.IndexerConfig
-{
- public class ConfigurationDataNCore : ConfigurationData
- {
- public StringItem Username { get; private set; }
- public StringItem Password { get; private set; }
- public BoolItem Hungarian { get; set; }
- public BoolItem English { get; set; }
-
- public ConfigurationDataNCore()
- {
- Username = new StringItem { Name = "Username", Value = "" };
- Password = new StringItem { Name = "Password", Value = "" };
- Hungarian = new BoolItem { Name = "Hungarian", Value = true };
- English = new BoolItem { Name = "English", Value = true };
- }
-
- public ConfigurationDataNCore(JToken json)
- {
- ConfigurationDataNCore configData = new ConfigurationDataNCore();
-
- dynamic configArray = JsonConvert.DeserializeObject(json.ToString());
- foreach (var config in configArray)
- {
- string propertyName = UppercaseFirst((string)config.id);
- switch (propertyName)
- {
- case "Username":
- Username = new StringItem { Name = propertyName, Value = config.value };
- break;
- case "Password":
- Password = new StringItem { Name = propertyName, Value = config.value };
- break;
- case "Hungarian":
- Hungarian = new BoolItem { Name = propertyName, Value = config.value };
- break;
- case "English":
- English = new BoolItem { Name = propertyName, Value = config.value };
- break;
- default:
- break;
- }
- }
- }
-
- static string UppercaseFirst(string s)
- {
- if (string.IsNullOrEmpty(s))
- return string.Empty;
- return char.ToUpper(s[0]) + s.Substring(1);
- }
- }
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Models.IndexerConfig.Bespoke
+{
+ public class ConfigurationDataNCore : ConfigurationData
+ {
+ public StringItem Username { get; private set; }
+ public StringItem Password { get; private set; }
+ public BoolItem Hungarian { get; set; }
+ public BoolItem English { get; set; }
+
+ public ConfigurationDataNCore()
+ {
+ Username = new StringItem { Name = "Username", Value = "" };
+ Password = new StringItem { Name = "Password", Value = "" };
+ Hungarian = new BoolItem { Name = "Hungarian", Value = true };
+ English = new BoolItem { Name = "English", Value = true };
+ }
+
+ public ConfigurationDataNCore(JToken json)
+ {
+ ConfigurationDataNCore configData = new ConfigurationDataNCore();
+
+ dynamic configArray = JsonConvert.DeserializeObject(json.ToString());
+ foreach (var config in configArray)
+ {
+ string propertyName = UppercaseFirst((string)config.id);
+ switch (propertyName)
+ {
+ case "Username":
+ Username = new StringItem { Name = propertyName, Value = config.value };
+ break;
+ case "Password":
+ Password = new StringItem { Name = propertyName, Value = config.value };
+ break;
+ case "Hungarian":
+ Hungarian = new BoolItem { Name = propertyName, Value = config.value };
+ break;
+ case "English":
+ English = new BoolItem { Name = propertyName, Value = config.value };
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ static string UppercaseFirst(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return string.Empty;
+ return char.ToUpper(s[0]) + s.Substring(1);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationDataRuTor.cs b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataRuTor.cs
similarity index 90%
rename from src/Jackett/Models/IndexerConfig/ConfigurationDataRuTor.cs
rename to src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataRuTor.cs
index 49c1024ea..aed0f1391 100644
--- a/src/Jackett/Models/IndexerConfig/ConfigurationDataRuTor.cs
+++ b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataRuTor.cs
@@ -1,27 +1,27 @@
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jackett.Models.IndexerConfig
-{
- public class ConfigurationDataRuTor : ConfigurationData
- {
- [JsonProperty]
- public StringItem Url { get; private set; }
- [JsonProperty]
- public BoolItem StripRussian { get; private set; }
-
- public ConfigurationDataRuTor()
- {
- }
-
- public ConfigurationDataRuTor(string defaultUrl)
- {
- Url = new StringItem { Name = "Url", Value = defaultUrl };
- StripRussian = new BoolItem() { Name = "StripRusNamePrefix", Value = true };
- }
- }
-}
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Models.IndexerConfig.Bespoke
+{
+ public class ConfigurationDataRuTor : ConfigurationData
+ {
+ [JsonProperty]
+ public StringItem Url { get; private set; }
+ [JsonProperty]
+ public BoolItem StripRussian { get; private set; }
+
+ public ConfigurationDataRuTor()
+ {
+ }
+
+ public ConfigurationDataRuTor(string defaultUrl)
+ {
+ Url = new StringItem { Name = "Url", Value = defaultUrl };
+ StripRussian = new BoolItem() { Name = "StripRusNamePrefix", Value = true };
+ }
+ }
+}
diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationDataStrike.cs b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataStrike.cs
similarity index 87%
rename from src/Jackett/Models/IndexerConfig/ConfigurationDataStrike.cs
rename to src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataStrike.cs
index 124ed0c2c..ba39425b0 100644
--- a/src/Jackett/Models/IndexerConfig/ConfigurationDataStrike.cs
+++ b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataStrike.cs
@@ -1,18 +1,18 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jackett.Models.IndexerConfig
-{
- public class ConfigurationDataStrike : ConfigurationDataUrl
- {
- public DisplayItem StrikeWarning { get; private set; }
-
- public ConfigurationDataStrike(string url) : base(url)
- {
- StrikeWarning = new DisplayItem("This indexer does not support RSS Sync, only Search") { Name = "Warning" };
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Models.IndexerConfig.Bespoke
+{
+ public class ConfigurationDataStrike : ConfigurationDataUrl
+ {
+ public DisplayItem StrikeWarning { get; private set; }
+
+ public ConfigurationDataStrike(string url) : base(url)
+ {
+ StrikeWarning = new DisplayItem("This indexer does not support RSS Sync, only Search") { Name = "Warning" };
+ }
+ }
+}
diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationDataAPIKey.cs b/src/Jackett/Models/IndexerConfig/ConfigurationDataAPIKey.cs
new file mode 100644
index 000000000..30fd25ee5
--- /dev/null
+++ b/src/Jackett/Models/IndexerConfig/ConfigurationDataAPIKey.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jackett.Models.IndexerConfig
+{
+ public class ConfigurationDataAPIKey : ConfigurationData
+ {
+ public ConfigurationData.StringItem Key { get; private set; }
+
+ public ConfigurationDataAPIKey()
+ {
+ Key = new ConfigurationData.StringItem { Name = "APIKey", Value = string.Empty };
+ }
+ }
+}