diff --git a/src/Jackett/Indexers/AlphaRatio.cs b/src/Jackett/Indexers/AlphaRatio.cs new file mode 100644 index 000000000..85c000ef8 --- /dev/null +++ b/src/Jackett/Indexers/AlphaRatio.cs @@ -0,0 +1,232 @@ +using CsQuery; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Web; + +namespace Jackett.Indexers +{ + public class AlphaRatio : IndexerInterface + { + public string DisplayName + { + get { return "AlphaRatio"; } + } + + public string DisplayDescription + { + get { return "Legendary"; } + } + + public Uri SiteLink + { + get { return new Uri(BaseUrl); } + } + + + public event Action OnSaveConfigurationRequested; + public event Action OnResultParsingError; + + public bool IsConfigured { get; private set; } + + static string BaseUrl = "https://alpharatio.cc"; + + static string LoginUrl = BaseUrl + "/login.php"; + + static string SearchUrl = BaseUrl + "/ajax.php?action=browse&searchstr="; + + static string DownloadUrl = BaseUrl + "/torrents.php?action=download&id="; + + static string GuidUrl = BaseUrl + "/torrents.php?torrentid="; + + CookieContainer cookies; + HttpClientHandler handler; + HttpClient client; + + string cookieHeader; + + public AlphaRatio() + { + IsConfigured = false; + cookies = new CookieContainer(); + handler = new HttpClientHandler + { + CookieContainer = cookies, + AllowAutoRedirect = true, + UseCookies = true, + }; + client = new HttpClient(handler); + } + + public Task GetConfigurationForSetup() + { + var config = new ConfigurationDataBasicLogin(); + return Task.FromResult(config); + } + + public async Task ApplyConfiguration(JToken configJson) + { + var config = new ConfigurationDataBasicLogin(); + config.LoadValuesFromJson(configJson); + + var pairs = new Dictionary { + { "username", config.Username.Value }, + { "password", config.Password.Value }, + { "login", "Log in" }, + { "keeplogged", "1" } + }; + + var content = new FormUrlEncodedContent(pairs); + + string responseContent; + JArray cookieJArray; + + if (Program.IsWindows) + { + // If Windows use .net http + var response = await client.PostAsync(LoginUrl, content); + responseContent = await response.Content.ReadAsStringAsync(); + cookieJArray = cookies.ToJson(SiteLink); + } + else + { + // If UNIX system use curl + var response = await CurlHelper.PostAsync(LoginUrl, pairs); + responseContent = Encoding.UTF8.GetString(response.Content); + cookieHeader = response.CookieHeader; + cookieJArray = new JArray(response.CookiesFlat); + } + + if (!responseContent.Contains("logout.php?")) + { + CQ dom = responseContent; + dom["#loginform > table"].Remove(); + var errorMessage = dom["#loginform"].Text().Trim().Replace("\n\t", " "); + throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)config); + + } + else + { + + var configSaveData = new JObject(); + configSaveData["cookies"] = cookieJArray; + if (OnSaveConfigurationRequested != null) + OnSaveConfigurationRequested(this, configSaveData); + + IsConfigured = true; + } + } + + public void LoadFromSavedConfiguration(JToken jsonConfig) + { + cookies.FillFromJson(SiteLink, (JArray)jsonConfig["cookies"]); + cookieHeader = cookies.GetCookieHeader(SiteLink); + IsConfigured = true; + } + + void FillReleaseInfoFromJson(ReleaseInfo release, JObject r) + { + var id = r["torrentId"]; + release.Size = (long)r["size"]; + release.Seeders = (int)r["seeders"]; + release.Peers = (int)r["leechers"] + release.Seeders; + release.Guid = new Uri(GuidUrl + id); + release.Comments = release.Guid; + release.Link = new Uri(DownloadUrl + id); + } + + public async Task PerformQuery(TorznabQuery query) + { + List releases = new List(); + + foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) + { + + var searchString = title + " " + query.GetEpisodeSearchString(); + var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString); + + string results; + if (Program.IsWindows) + { + results = await client.GetStringAsync(episodeSearchUrl); + } + else + { + var response = await CurlHelper.GetAsync(episodeSearchUrl, cookieHeader); + results = Encoding.UTF8.GetString(response.Content); + } + try + { + + var json = JObject.Parse(results); + foreach (JObject r in json["response"]["results"]) + { + DateTime pubDate = DateTime.MinValue; + double dateNum; + if (double.TryParse((string)r["groupTime"], out dateNum)) + pubDate = UnixTimestampToDateTime(dateNum); + + var groupName = (string)r["groupName"]; + + if (r["torrents"] is JArray) + { + foreach (JObject t in r["torrents"]) + { + var release = new ReleaseInfo(); + release.PublishDate = pubDate; + release.Title = groupName; + release.Description = groupName; + FillReleaseInfoFromJson(release, t); + releases.Add(release); + } + } + else + { + var release = new ReleaseInfo(); + release.PublishDate = pubDate; + release.Title = groupName; + release.Description = groupName; + FillReleaseInfoFromJson(release, r); + releases.Add(release); + } + + } + } + catch (Exception ex) + { + OnResultParsingError(this, results, ex); + throw ex; + } + } + + return releases.ToArray(); + } + + static DateTime UnixTimestampToDateTime(double unixTime) + { + DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); + long unixTimeStampInTicks = (long)(unixTime * TimeSpan.TicksPerSecond); + return new DateTime(unixStart.Ticks + unixTimeStampInTicks); + } + + public async Task Download(Uri link) + { + if (Program.IsWindows) + { + return await client.GetByteArrayAsync(link); + } + else + { + var response = await CurlHelper.GetAsync(link.ToString(), cookieHeader); + return response.Content; + } + + } + + } +} diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 2f71054f6..dcd16fd34 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -122,6 +122,7 @@ + @@ -220,6 +221,9 @@ PreserveNewest + + PreserveNewest + diff --git a/src/Jackett/WebContent/logos/alpharatio.png b/src/Jackett/WebContent/logos/alpharatio.png new file mode 100644 index 000000000..1ff6bcddd Binary files /dev/null and b/src/Jackett/WebContent/logos/alpharatio.png differ