mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-17 17:34:09 +02:00
This commit is contained in:
@@ -1,101 +0,0 @@
|
|||||||
---
|
|
||||||
site: awesomehd
|
|
||||||
name: Awesome-HD
|
|
||||||
description: "An HD tracker"
|
|
||||||
language: en-us
|
|
||||||
type: private
|
|
||||||
encoding: UTF-8
|
|
||||||
links:
|
|
||||||
- https://awesome-hd.me/
|
|
||||||
|
|
||||||
caps:
|
|
||||||
categorymappings:
|
|
||||||
- {id: 1, cat: Movies/HD, desc: "Movies"}
|
|
||||||
- {id: 2, cat: TV/HD, desc: "TV-Shows"}
|
|
||||||
|
|
||||||
modes:
|
|
||||||
search: [q]
|
|
||||||
tv-search: [q, season, ep]
|
|
||||||
movie-search: [q]
|
|
||||||
|
|
||||||
settings:
|
|
||||||
- name: username
|
|
||||||
type: text
|
|
||||||
label: Username
|
|
||||||
- name: password
|
|
||||||
type: password
|
|
||||||
label: Password
|
|
||||||
- name: sort
|
|
||||||
type: select
|
|
||||||
label: Sort requested from site
|
|
||||||
default: "time"
|
|
||||||
options:
|
|
||||||
"time": "created"
|
|
||||||
"seeders": "seeders"
|
|
||||||
"size": "size"
|
|
||||||
- name: type
|
|
||||||
type: select
|
|
||||||
label: Order requested from site
|
|
||||||
default: "desc"
|
|
||||||
options:
|
|
||||||
"desc": "desc"
|
|
||||||
"asc": "asc"
|
|
||||||
- name: info_login
|
|
||||||
type: info
|
|
||||||
label: "Password Changes"
|
|
||||||
default: "This site forces you to change your <b>Password</b> every <b>90 days</b>.<br/>If you get a <b>Login Failed, got redirected</b> error, then access the site with your browser and check if you need to change your password. Logout after saving, and update this config to login."
|
|
||||||
|
|
||||||
login:
|
|
||||||
path: login.php
|
|
||||||
method: form
|
|
||||||
form: form#loginform
|
|
||||||
inputs:
|
|
||||||
username: "{{ .Config.username }}"
|
|
||||||
password: "{{ .Config.password }}"
|
|
||||||
keeplogged: 1
|
|
||||||
error:
|
|
||||||
- selector: form#loginform .warning
|
|
||||||
test:
|
|
||||||
path: torrents.php
|
|
||||||
|
|
||||||
search:
|
|
||||||
paths:
|
|
||||||
- path: torrents.php
|
|
||||||
inputs:
|
|
||||||
$raw: "{{ range .Categories }}filter_cat[{{.}}]=1&{{end}}"
|
|
||||||
searchstr: "{{ .Keywords }}"
|
|
||||||
page: torrents
|
|
||||||
order_by: "{{ .Config.sort }}"
|
|
||||||
order_way: "{{ .Config.type }}"
|
|
||||||
|
|
||||||
rows:
|
|
||||||
selector: table#torrent_table > tbody > tr.group, tr.torrent, tr.group_torrent:not(.edition_info)
|
|
||||||
|
|
||||||
fields:
|
|
||||||
download:
|
|
||||||
selector: a[href^="torrents.php?action=download&id="]
|
|
||||||
attribute: href
|
|
||||||
optional: true
|
|
||||||
details:
|
|
||||||
selector: a[href^="torrents.php?id="]
|
|
||||||
attribute: href
|
|
||||||
title:
|
|
||||||
selector: td:nth-child(3) > a
|
|
||||||
category:
|
|
||||||
selector: td:nth-child(2)
|
|
||||||
date:
|
|
||||||
selector: td:nth-last-child(5)
|
|
||||||
size:
|
|
||||||
selector: td:nth-last-child(4)
|
|
||||||
grabs:
|
|
||||||
selector: td:nth-last-child(3)
|
|
||||||
seeders:
|
|
||||||
selector: td:nth-last-child(2)
|
|
||||||
leechers:
|
|
||||||
selector: td:nth-last-child(1)
|
|
||||||
downloadvolumefactor:
|
|
||||||
case:
|
|
||||||
"*": 1
|
|
||||||
uploadvolumefactor:
|
|
||||||
case:
|
|
||||||
"*": 1
|
|
194
src/Jackett.Common/Indexers/AwesomeHD.cs
Normal file
194
src/Jackett.Common/Indexers/AwesomeHD.cs
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Jackett.Common.Models;
|
||||||
|
using Jackett.Common.Models.IndexerConfig;
|
||||||
|
using Jackett.Common.Services.Interfaces;
|
||||||
|
using Jackett.Common.Utils;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
|
namespace Jackett.Common.Indexers
|
||||||
|
{
|
||||||
|
public class AwesomeHD : BaseWebIndexer
|
||||||
|
{
|
||||||
|
private string SearchUrl => SiteLink + "searchapi.php";
|
||||||
|
private string TorrentUrl => SiteLink + "torrents.php";
|
||||||
|
private new ConfigurationDataPasskey configData => (ConfigurationDataPasskey)base.configData;
|
||||||
|
|
||||||
|
public AwesomeHD(IIndexerConfigurationService configService, Utils.Clients.WebClient c, Logger l, IProtectionService ps)
|
||||||
|
: base("Awesome-HD",
|
||||||
|
description: "An HD tracker",
|
||||||
|
link: "https://awesome-hd.me/",
|
||||||
|
caps: new TorznabCapabilities(),
|
||||||
|
configService: configService,
|
||||||
|
client: c,
|
||||||
|
logger: l,
|
||||||
|
p: ps,
|
||||||
|
configData: new ConfigurationDataPasskey("Note: You can find the Passkey in your profile, next to Personal information."))
|
||||||
|
{
|
||||||
|
Encoding = Encoding.UTF8;
|
||||||
|
Language = "en-us";
|
||||||
|
Type = "private";
|
||||||
|
|
||||||
|
TorznabCaps.SupportsImdbMovieSearch = true;
|
||||||
|
TorznabCaps.SupportsImdbTVSearch = true;
|
||||||
|
|
||||||
|
AddCategoryMapping(1, TorznabCatType.MoviesHD);
|
||||||
|
AddCategoryMapping(2, TorznabCatType.TVHD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||||
|
{
|
||||||
|
LoadValuesFromJson(configJson);
|
||||||
|
|
||||||
|
if (configData.Passkey.Value.Length != 32)
|
||||||
|
throw new Exception("Invalid Passkey configured. Expected length: 32");
|
||||||
|
|
||||||
|
var releases = await PerformQuery(new TorznabQuery());
|
||||||
|
await ConfigureIfOK(string.Empty, releases.Any(),
|
||||||
|
() => throw new Exception("Could not find release from this URL."));
|
||||||
|
|
||||||
|
return IndexerConfigurationStatus.Completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||||
|
{
|
||||||
|
var releases = new List<ReleaseInfo>();
|
||||||
|
var passkey = configData.Passkey.Value;
|
||||||
|
|
||||||
|
var qc = new NameValueCollection
|
||||||
|
{
|
||||||
|
{"passkey", passkey}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(query.ImdbID))
|
||||||
|
{
|
||||||
|
qc.Add("action", "imdbsearch");
|
||||||
|
qc.Add("imdb", query.ImdbID);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(query.GetQueryString()))
|
||||||
|
{
|
||||||
|
qc.Add("action", "titlesearch");
|
||||||
|
qc.Add("title", query.SearchTerm); // not use query.GetQueryString(), see the season code below
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qc.Add("action", "latestmovies");
|
||||||
|
// the endpoint 'latestmovies' only returns movies, this hack overwrites categories to get movies even if
|
||||||
|
// you are searching for tv series. this allows to configure the tracker in Sonarr
|
||||||
|
query.Categories = new int[] {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var searchUrl = SearchUrl + "?" + qc.GetQueryString();
|
||||||
|
var results = await RequestStringWithCookies(searchUrl);
|
||||||
|
if (string.IsNullOrWhiteSpace(results.Content))
|
||||||
|
throw new Exception("Empty response. Please, check the Passkey.");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var doc = XDocument.Parse(results.Content);
|
||||||
|
|
||||||
|
var errorMsg = doc.Descendants("error").FirstOrDefault()?.Value;
|
||||||
|
if (errorMsg?.Contains("No Results") == true)
|
||||||
|
return releases; // no results
|
||||||
|
if (errorMsg != null)
|
||||||
|
throw new Exception(errorMsg);
|
||||||
|
|
||||||
|
var authkey = doc.Descendants("authkey").First().Value;
|
||||||
|
var torrents = doc.Descendants("torrent");
|
||||||
|
foreach (var torrent in torrents)
|
||||||
|
{
|
||||||
|
var torrentName = torrent.FirstValue("name").Trim();
|
||||||
|
|
||||||
|
// the field <type> is always Movie, so we have to guess if it's a tv series
|
||||||
|
var isSerie = torrentName.Contains(": Season ");
|
||||||
|
if (isSerie)
|
||||||
|
torrentName = torrentName.Replace(": Season ", " S");
|
||||||
|
|
||||||
|
// if the category is not in the search categories, skip
|
||||||
|
var cat = new List<int> {isSerie ? TorznabCatType.TVHD.ID : TorznabCatType.MoviesHD.ID};
|
||||||
|
if (query.Categories.Any() && !query.Categories.Intersect(cat).Any())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if it's a tv series season search, skip movies and other seasons
|
||||||
|
if (query.Season > 0 && (!isSerie || !torrentName.EndsWith($" S{query.Season:D2}")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var title = new StringBuilder(torrentName);
|
||||||
|
if (!isSerie && torrent.Element("year") != null) // only for movies
|
||||||
|
title.Append($" {torrent.FirstValue("year")}");
|
||||||
|
if (torrent.Element("internal")?.Value == "1")
|
||||||
|
title.Append(" iNTERNAL");
|
||||||
|
if (torrent.Element("resolution") != null)
|
||||||
|
title.Append($" {torrent.FirstValue("resolution")}");
|
||||||
|
if (torrent.Element("media") != null)
|
||||||
|
title.Append($" {torrent.FirstValue("media")}");
|
||||||
|
if (torrent.Element("encoding") != null)
|
||||||
|
title.Append($" {torrent.FirstValue("encoding")}");
|
||||||
|
if (torrent.Element("audioformat") != null)
|
||||||
|
title.Append($" {torrent.FirstValue("audioformat")}");
|
||||||
|
if (torrent.Element("releasegroup") != null)
|
||||||
|
title.Append($"-{torrent.FirstValue("releasegroup")}");
|
||||||
|
|
||||||
|
var torrentId = torrent.FirstValue("id");
|
||||||
|
var groupId = torrent.FirstValue("groupid");
|
||||||
|
var comments = new Uri($"{TorrentUrl}?id={groupId}&torrentid={torrentId}");
|
||||||
|
var link = new Uri($"{TorrentUrl}?action=download&id={torrentId}&authkey={authkey}&torrent_pass={passkey}");
|
||||||
|
|
||||||
|
var publishDate = DateTime.Parse(torrent.FirstValue("time"));
|
||||||
|
var size = long.Parse(torrent.FirstValue("size"));
|
||||||
|
var grabs = int.Parse(torrent.FirstValue("snatched"));
|
||||||
|
var seeders = int.Parse(torrent.FirstValue("seeders"));
|
||||||
|
var peers = seeders + int.Parse(torrent.FirstValue("leechers"));
|
||||||
|
var freeleech = double.Parse(torrent.FirstValue("freeleech"));
|
||||||
|
|
||||||
|
Uri banner = null;
|
||||||
|
// small cover only for movies
|
||||||
|
if (!isSerie && !string.IsNullOrWhiteSpace(torrent.Element("smallcover")?.Value))
|
||||||
|
banner = new Uri(torrent.FirstValue("smallcover"));
|
||||||
|
else if (!string.IsNullOrWhiteSpace(torrent.Element("cover")?.Value))
|
||||||
|
banner = new Uri(torrent.FirstValue("cover"));
|
||||||
|
|
||||||
|
var description = torrent.Element("encodestatus") != null ?
|
||||||
|
$"Encode status: {torrent.FirstValue("encodestatus")}" : null;
|
||||||
|
|
||||||
|
var imdb = ParseUtil.GetImdbID(torrent.Element("imdb")?.Value);
|
||||||
|
|
||||||
|
var release = new ReleaseInfo
|
||||||
|
{
|
||||||
|
Title = title.ToString(),
|
||||||
|
Comments = comments,
|
||||||
|
Link = link,
|
||||||
|
Guid = link,
|
||||||
|
PublishDate = publishDate,
|
||||||
|
Category = cat,
|
||||||
|
BannerUrl = banner,
|
||||||
|
Description = description,
|
||||||
|
Imdb = imdb,
|
||||||
|
Size = size,
|
||||||
|
Grabs = grabs,
|
||||||
|
Seeders = seeders,
|
||||||
|
Peers = peers,
|
||||||
|
MinimumRatio = 1,
|
||||||
|
MinimumSeedTime = 259200, // 72 hours
|
||||||
|
DownloadVolumeFactor = freeleech,
|
||||||
|
UploadVolumeFactor = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
releases.Add(release);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
OnParseError(results.Content, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return releases;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -282,6 +282,7 @@ namespace Jackett.Updater
|
|||||||
"Definitions/archetorrent.yml",
|
"Definitions/archetorrent.yml",
|
||||||
"Definitions/asiandvdclub.yml",
|
"Definitions/asiandvdclub.yml",
|
||||||
"Definitions/avg.yml",
|
"Definitions/avg.yml",
|
||||||
|
"Definitions/awesomehd.yml", // migrated to C#
|
||||||
"Definitions/b2s-share.yml",
|
"Definitions/b2s-share.yml",
|
||||||
"Definitions/bithq.yml",
|
"Definitions/bithq.yml",
|
||||||
"Definitions/bitme.yml",
|
"Definitions/bitme.yml",
|
||||||
|
Reference in New Issue
Block a user