1
0
Fork 0
mirror of https://github.com/Jackett/Jackett synced 2025-02-24 15:21:06 +00:00

Add BlueTigers Indexer

Adds BlueTigers Indexer. Torznab Category mapping still to come.
This commit is contained in:
flightlevel 2015-11-08 12:48:49 +11:00
parent 02d0f9c5a1
commit f999e6657b
5 changed files with 280 additions and 0 deletions

View file

@ -25,6 +25,7 @@ We were previously focused on TV but are working on extending searches to allow
* [BeyondHD](https://beyondhd.me/)
* [BIT-HDTV](https://www.bit-hdtv.com)
* [BitMeTV](http://www.bitmetv.org/)
* [BlueTigers](https://www.bluetigers.ca/)
* [BTN](http://broadcasthe.net)
* [Demonoid](http://www.demonoid.pw/)
* [EuTorrents](https://eutorrents.to/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View file

@ -0,0 +1,211 @@
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.Text.RegularExpressions;
using System.Threading.Tasks;
using Jackett.Models.IndexerConfig.Bespoke;
namespace Jackett.Indexers
{
public class BlueTigers : BaseIndexer, IIndexer
{
private string LoginUrl => SiteLink + "account-login.php";
private string TorrentSearchUrl => SiteLink + "torrents-search.php";
private string IndexUrl => SiteLink + "index.php";
private ConfigurationDataBlueTigers ConfigData
{
get { return (ConfigurationDataBlueTigers)configData; }
set { base.configData = value; }
}
public BlueTigers(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "BlueTigers",
description: "BlueTigers - No Ratio - Private",
link: "https://www.bluetigers.ca/",
caps: new TorznabCapabilities(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataBlueTigers(@"BlueTigers can search for one or all languages.
If you select 2 languages below, results will contain all 3 languages.
<br> For best results change the torrents per page setting to 50 in your BlueTigers profile."))
{
AddCategoryMapping(19, TorznabCatType.TV);
AddCategoryMapping(2, TorznabCatType.TV);
AddCategoryMapping(17, TorznabCatType.TV);
AddCategoryMapping(52, TorznabCatType.ConsoleXbox);
AddCategoryMapping(29, TorznabCatType.PCMac);
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
ConfigData.LoadValuesFromJson(configJson);
if (ConfigData.French.Value == false && ConfigData.English.Value == false && ConfigData.Spanish.Value == false)
throw new ExceptionWithConfigData("Please select at least one language.", ConfigData);
await RequestStringWithCookies(LoginUrl, string.Empty);
var pairs = new Dictionary<string, string> {
{ "username", ConfigData.Username.Value },
{ "password", ConfigData.Password.Value },
{ "take_login", "1" }
};
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, IndexUrl, SiteLink);
Regex rgx = new Regex(@"uid=[0-9]{1,10}; pass=[a-z0-9]{1,40};");
await ConfigureIfOK(result.Cookies, rgx.IsMatch(result.Cookies), () =>
{
var errorMessage = "Error while trying to login.";
throw new ExceptionWithConfigData(errorMessage, ConfigData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
List<ReleaseInfo> releases = new List<ReleaseInfo>();
NameValueCollection qParams = new NameValueCollection();
if (ConfigData.French.Value && !ConfigData.English.Value && !ConfigData.Spanish.Value)
{
qParams.Add("lang", "1");
}
else
{
if (!ConfigData.French.Value && ConfigData.English.Value && !ConfigData.Spanish.Value)
{
qParams.Add("lang", "2");
}
else
{
if (!ConfigData.French.Value && !ConfigData.English.Value && ConfigData.Spanish.Value)
{
qParams.Add("lang", "3");
}
else
{
qParams.Add("lang", "0");
}
}
}
List<string> catList = MapTorznabCapsToTrackers(query);
foreach (string cat in catList)
{
qParams.Add("cat", cat);
}
if (!string.IsNullOrEmpty(query.SanitizedSearchTerm))
{
qParams.Add("search", query.GetQueryString());
}
string queryStr = qParams.GetQueryString();
string searchUrl = $"{TorrentSearchUrl}?incldead=0&freeleech=0&sort=id&order=ascdesc&{queryStr}";
List<CQ> torrentRowList = new List<CQ>();
var results = await RequestStringWithCookiesAndRetry(searchUrl);
try
{
CQ fDom = results.Content;
var firstPageRows = fDom["table[class='ttable_headinner'] > tbody > tr:not(:First-child)"];
torrentRowList.AddRange(firstPageRows.Select(fRow => fRow.Cq()));
//If a search term is used, follow upto the first 4 pages (initial plus 3 more)
if (!string.IsNullOrWhiteSpace(query.GetQueryString()) && fDom["a[class='boutons']"].Filter("a[href*=&page=]").Length > 0)
{
int pageLinkCount;
int.TryParse(fDom["a[class='boutons']"].Filter("a[href*=&page=]").Last().Attr("href").Split(new[] { "&page=" }, StringSplitOptions.None).LastOrDefault(), out pageLinkCount);
for (int i = 1; i < Math.Min(4, pageLinkCount + 1); i++)
{
var sResults = await RequestStringWithCookiesAndRetry($"{searchUrl}&page={i}");
CQ sDom = sResults.Content;
var additionalPageRows = sDom["table[class='ttable_headinner'] > tbody > tr:not(:First-child)"];
torrentRowList.AddRange(additionalPageRows.Select(sRow => sRow.Cq()));
}
}
foreach (CQ tRow in torrentRowList)
{
long torrentId = 0;
string idTarget = "bookmarks.php?torrent=";
string id = tRow.Find("a[href*=" + idTarget + "]").First().Attr("href").Trim();
if (!string.IsNullOrEmpty(id) && id.Contains(idTarget))
{
long.TryParse(id.Substring(id.LastIndexOf(idTarget, StringComparison.Ordinal) + idTarget.Length), out torrentId);
}
if (torrentId <= 0) continue;
long category = 0;
string catTarget = "torrents.php?cat=";
string cat = tRow.Find("a[href*=" + catTarget + "]").First().Attr("href").Trim();
if (!string.IsNullOrEmpty(cat) && cat.Contains(catTarget))
{
long.TryParse(cat.Substring(cat.LastIndexOf(catTarget, StringComparison.Ordinal) + catTarget.Length), out category);
}
Uri guid = new Uri($"{SiteLink}torrents-details.php?hit=1&id={torrentId}");
Uri link = new Uri($"{SiteLink}download.php?hit=1&id={torrentId}");
Uri comments = new Uri($"{SiteLink}comments.php?type=torrent&id={torrentId}");
string title = tRow.Find("a[href*=torrents-details.php?id=]").First().Text().Trim();
string stats = tRow.Find("div[id=kt" + torrentId.ToString() + "]").First().Text();
string sizeStr = new Regex("Taille:(.*)Vitesse:").Match(stats).Groups[1].ToString().Trim();
string pubDateStr = new Regex("Ajout.:(.*)Compl.t.s").Match(stats).Groups[1].ToString().Trim();
DateTime pubDate = DateTime.ParseExact(pubDateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
string statistics = tRow.Find("a[href*=torrents-details.php?id=]").First().RenderSelection().Trim();
string startTag = "<table ";
string endTag = "</table>";
CQ statsCq = startTag + new Regex(startTag + "(.*)" + endTag).Match(statistics).Groups[1].ToString().Trim() + endTag;
int seeders;
int leechers;
int.TryParse(statsCq.Find("font[color=#05FC09]").First().Text(), out seeders);
int.TryParse(statsCq.Find("font[color=red]").First().Text(), out leechers);
var release = new ReleaseInfo();
release.Title = title;
release.Guid = guid;
release.Link = link;
release.PublishDate = pubDate;
release.Size = ReleaseInfo.GetBytes(sizeStr);
release.Description = title;
release.Seeders = seeders;
release.Peers = leechers + seeders;
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
release.Category = MapTrackerCatToNewznab(category.ToString());
release.Comments = comments;
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
}
}

View file

@ -179,6 +179,7 @@
<Compile Include="Controllers\DownloadController.cs" />
<Compile Include="Engine.cs" />
<Compile Include="Indexers\AlphaRatio.cs" />
<Compile Include="Indexers\BlueTigers.cs" />
<Compile Include="Indexers\EuTorrents.cs" />
<Compile Include="Indexers\Avistaz.cs" />
<Compile Include="Indexers\BakaBT.cs" />
@ -203,6 +204,7 @@
<Compile Include="Indexers\FileList.cs" />
<Compile Include="Indexers\Abstract\AvistazTracker.cs" />
<Compile Include="Indexers\AnimeTorrents.cs" />
<Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataBlueTigers.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilter.cs" />
<Compile Include="Models\IndexerConfig\ConfigurationDataAPIKey.cs" />
<Compile Include="Models\ManualSearchResult.cs" />
@ -439,6 +441,9 @@
<Content Include="Content\logos\beyondhd.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\bluetigers.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\logos\broadcastthenet.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View file

@ -0,0 +1,63 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Jackett.Models.IndexerConfig.Bespoke
{
public class ConfigurationDataBlueTigers : ConfigurationData
{
public StringItem Username { get; private set; }
public StringItem Password { get; private set; }
public DisplayItem Instructions { get; set; }
public BoolItem French { get; set; }
public BoolItem English { get; set; }
public BoolItem Spanish { get; set; }
public ConfigurationDataBlueTigers(string displayInstructions)
{
Username = new StringItem { Name = "Username", Value = "" };
Password = new StringItem { Name = "Password", Value = "" };
Instructions = new DisplayItem(displayInstructions) { Name = "" };
French = new BoolItem { Name = "French", Value = true };
English = new BoolItem { Name = "English", Value = true };
Spanish = new BoolItem { Name = "Spanish", Value = true };
}
public ConfigurationDataBlueTigers(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 "French":
French = new BoolItem { Name = propertyName, Value = config.value };
break;
case "English":
English = new BoolItem { Name = propertyName, Value = config.value };
break;
case "Spanish":
Spanish = 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);
}
}
}