From 19bc3c7b36e2a936801c332afd6dea229fc8da19 Mon Sep 17 00:00:00 2001
From: JigSawFr <jigsawlimitedfr@gmail.com>
Date: Tue, 5 Jan 2016 15:30:50 +0100
Subject: [PATCH] FADN Provider

---
 src/Jackett/Content/logos/frenchadn.png       | Bin 0 -> 25425 bytes
 src/Jackett/Indexers/FrenchADN.cs             | 966 ++++++++++++++++++
 src/Jackett/Jackett.csproj                    |   5 +
 .../Bespoke/ConfigurationDataFrenchADN.cs     |  53 +
 4 files changed, 1024 insertions(+)
 create mode 100644 src/Jackett/Content/logos/frenchadn.png
 create mode 100644 src/Jackett/Indexers/FrenchADN.cs
 create mode 100644 src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataFrenchADN.cs

diff --git a/src/Jackett/Content/logos/frenchadn.png b/src/Jackett/Content/logos/frenchadn.png
new file mode 100644
index 0000000000000000000000000000000000000000..960e0368023781a16f262792c9b75821e03266f7
GIT binary patch
literal 25425
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
aa)!LyI>-Mkk#YfDdg1Bn=d#Wzp$PzGSe!=y

literal 0
HcmV?d00001

diff --git a/src/Jackett/Indexers/FrenchADN.cs b/src/Jackett/Indexers/FrenchADN.cs
new file mode 100644
index 00000000..58238ce2
--- /dev/null
+++ b/src/Jackett/Indexers/FrenchADN.cs
@@ -0,0 +1,966 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using CsQuery;
+using Jackett.Models;
+using Jackett.Models.IndexerConfig.Bespoke;
+using Jackett.Services;
+using Jackett.Utils;
+using Jackett.Utils.Clients;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using NLog;
+
+namespace Jackett.Indexers
+{
+    /// <summary>
+    /// Provider for French-ADN Private Tracker
+    /// </summary>
+    public class FrenchADN : BaseIndexer, IIndexer
+    {
+        private string LoginUrl { get { return SiteLink + "login.php?"; } }
+        private string LoginCheckUrl { get { return SiteLink + "takelogin.php"; } }
+        private string SearchUrl { get { return SiteLink + "browse.php"; } }
+        private string TorrentCommentUrl { get { return SiteLink + "details.php?id={id}#comments"; } }
+        private string TorrentDescriptionUrl { get { return SiteLink + "details.php?id={id}"; } }
+        private string TorrentDownloadUrl { get { return SiteLink + "download.php?id={id}"; } }
+        private string TorrentThanksUrl { get { return SiteLink + "takethanks.php"; } }
+        private bool Latency { get { return ConfigData.Latency.Value; } }
+        private bool DevMode { get { return ConfigData.DevMode.Value; } }
+        private bool CacheMode { get { return ConfigData.HardDriveCache.Value; } }
+        private string directory { get { return System.IO.Path.GetTempPath() + "Jackett\\" + MethodBase.GetCurrentMethod().DeclaringType.Name + "\\"; } }
+
+        private Dictionary<string, string> emulatedBrowserHeaders = new Dictionary<string, string>();
+        private CQ fDom = null;
+
+        private ConfigurationDataFrenchADN ConfigData
+        {
+            get { return (ConfigurationDataFrenchADN)configData; }
+            set { base.configData = value; }
+        }
+
+        public FrenchADN(IIndexerManagerService i, IWebClient w, Logger l, IProtectionService ps)
+            : base(
+                name: "French-ADN",
+                description: "Your French Family Provider",
+                link: "https://french-adn.com/",
+                caps: new TorznabCapabilities(),
+                manager: i,
+                client: w,
+                logger: l,
+                p: ps,
+                downloadBase: "https://french-adn.com/download.php?id=",
+                configData: new ConfigurationDataFrenchADN())
+        {
+            // Clean capabilities
+            TorznabCaps.Categories.Clear();
+
+            // Movies
+            AddCategoryMapping("15", TorznabCatType.Movies);            // ALL
+            AddCategoryMapping("108", TorznabCatType.MoviesSD);         // TS CAM
+            AddCategoryMapping("25", TorznabCatType.MoviesSD);          // BDRIP
+            AddCategoryMapping("56", TorznabCatType.MoviesSD);          // BRRIP
+            AddCategoryMapping("16", TorznabCatType.MoviesSD);          // DVDRIP
+            AddCategoryMapping("49", TorznabCatType.MoviesDVD);         // TVRIP
+            AddCategoryMapping("102", TorznabCatType.MoviesWEBDL);      // WEBRIP
+            AddCategoryMapping("105", TorznabCatType.MoviesHD);         // 1080P
+            AddCategoryMapping("104", TorznabCatType.MoviesHD);         // 720P
+            AddCategoryMapping("17", TorznabCatType.MoviesDVD);         // DVD R
+            AddCategoryMapping("21", TorznabCatType.MoviesDVD);         // DVD R5
+            AddCategoryMapping("112", TorznabCatType.MoviesDVD);        // DVD REMUX
+            AddCategoryMapping("107", TorznabCatType.Movies3D);         // 3D
+            AddCategoryMapping("113", TorznabCatType.MoviesBluRay);     // BLURAY
+            AddCategoryMapping("118", TorznabCatType.MoviesHD);         // MHD
+
+            // Series
+            AddCategoryMapping("41", TorznabCatType.TV);                // ALL
+            AddCategoryMapping("43", TorznabCatType.TV);                // VF
+            AddCategoryMapping("44", TorznabCatType.TV);                // VOSTFR
+            AddCategoryMapping("42", TorznabCatType.TV);                // PACK
+
+            // TV
+            AddCategoryMapping("110", TorznabCatType.TV);               // SHOWS
+
+            // Anime
+            AddCategoryMapping("109", TorznabCatType.TVAnime);          // ANIME
+
+            // Manga
+            AddCategoryMapping("119", TorznabCatType.TVAnime);          // MANGA
+
+            // Documentaries
+            AddCategoryMapping("114", TorznabCatType.TVDocumentary);    // DOCUMENTARY
+
+            // Music
+            AddCategoryMapping("22", TorznabCatType.Audio);             // ALL
+            AddCategoryMapping("24", TorznabCatType.AudioLossless);     // FLAC
+            AddCategoryMapping("23", TorznabCatType.AudioMP3);          // MP3
+
+            // Games
+            AddCategoryMapping("33", TorznabCatType.PCGames);           // ALL
+            AddCategoryMapping("45", TorznabCatType.PCGames);           // PC GAMES
+            AddCategoryMapping("93", TorznabCatType.Console3DS);        // 3DS
+            AddCategoryMapping("94", TorznabCatType.Console);           // PS2
+            AddCategoryMapping("93", TorznabCatType.ConsolePS3);        // PS3
+            AddCategoryMapping("95", TorznabCatType.ConsolePSP);        // PSP
+            AddCategoryMapping("35", TorznabCatType.ConsolePS3);        // WII
+
+            // Applications
+            AddCategoryMapping("11", TorznabCatType.PC);                // ALL
+            AddCategoryMapping("12", TorznabCatType.PC);                // APPS WINDOWS
+            AddCategoryMapping("97", TorznabCatType.PCMac);             // APPS MAC
+            AddCategoryMapping("98", TorznabCatType.PC);                // APPS LINUX
+
+            // Books
+            AddCategoryMapping("115", TorznabCatType.BooksEbook);       // EBOOK
+            AddCategoryMapping("114", TorznabCatType.BooksComics);      // COMICS
+
+            // Other
+            AddCategoryMapping("103", TorznabCatType.Other);            // STAFF
+        }
+
+        /// <summary>
+        /// Configure our FADN Provider
+        /// </summary>
+        /// <param name="configJson">Our params in Json</param>
+        /// <returns>Configuration state</returns>
+        public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
+        {
+            // Retrieve config values set by Jackett's user
+            ConfigData.LoadValuesFromJson(configJson);
+
+            // Check & Validate Config
+            validateConfig();
+
+            // Setting our data for a better emulated browser (maximum security)
+            // TODO: Encoded Content not supported by Jackett at this time
+            // emulatedBrowserHeaders.Add("Accept-Encoding", "gzip, deflate");
+
+            // If we want to simulate a browser
+            if (ConfigData.Browser.Value)
+            {
+
+                // Clean headers
+                emulatedBrowserHeaders.Clear();
+
+                // Inject headers
+                emulatedBrowserHeaders.Add("Accept", ConfigData.HeaderAccept.Value);
+                emulatedBrowserHeaders.Add("Accept-Language", ConfigData.HeaderAcceptLang.Value);
+                emulatedBrowserHeaders.Add("DNT", Convert.ToInt32(ConfigData.HeaderDNT.Value).ToString());
+                emulatedBrowserHeaders.Add("Upgrade-Insecure-Requests", Convert.ToInt32(ConfigData.HeaderUpgradeInsecure.Value).ToString());
+                emulatedBrowserHeaders.Add("User-Agent", ConfigData.HeaderUserAgent.Value);
+            }
+
+            // Build WebRequest for index
+            var myIndexRequest = new WebRequest()
+            {
+                Type = RequestType.GET,
+                Url = SiteLink,
+                Headers = emulatedBrowserHeaders
+            };
+
+            // Get index page for cookies
+            output("\nGetting index page (for cookies).. with " + SiteLink);
+            var indexPage = await webclient.GetString(myIndexRequest);
+
+             // Building login form data
+             var pairs = new Dictionary<string, string> {
+                { "username", ConfigData.Username.Value },
+                { "password", ConfigData.Password.Value }
+            };
+
+            // Build WebRequest for login
+            var myRequestLogin = new WebRequest()
+            {
+                Type = RequestType.GET,
+                Url = LoginUrl,
+                Headers = emulatedBrowserHeaders,
+                Cookies = indexPage.Cookies,
+                Referer = SiteLink
+            };
+
+            // Get login page -- (not used, but simulation needed by tracker security's checks)
+            latencyNow();
+            output("\nGetting login page (user simulation).. with " + LoginUrl);
+            var loginPage = await webclient.GetString(myRequestLogin);
+
+            // Build WebRequest for submitting authentification
+            var request = new WebRequest()
+            {
+                PostData = pairs,
+                Referer = LoginUrl,
+                Type = RequestType.POST,
+                Url = LoginCheckUrl,
+                Headers = emulatedBrowserHeaders,
+                Cookies = indexPage.Cookies,
+   
+            };
+
+            // Perform loggin
+            latencyNow();
+            output("\nPerform loggin.. with " + LoginCheckUrl);
+            var response = await webclient.GetString(request);
+
+            // Test if we are logged in
+            await ConfigureIfOK(response.Cookies, !string.IsNullOrEmpty(response.Cookies) && !response.IsRedirect, () =>
+            {
+                // Default error message
+                string message = "Error during attempt !";
+
+                // Parse redirect header
+                string redirectTo = response.RedirectingTo;
+
+                // Analyzer error code
+                if(redirectTo.Contains("login.php?error=4"))
+                {
+                    // Set message
+                    message = "Wrong username or password !";
+                }
+
+                // Oops, unable to login
+                output("-> Login failed: " + message, "error");
+                throw new ExceptionWithConfigData("Login failed: " + message, configData);
+            });
+
+            output("\nCookies saved for future uses...");
+            ConfigData.CookieHeader.Value = indexPage.Cookies + " " + response.Cookies + " ts_username=" + ConfigData.Username.Value;
+
+            output("\n-> Login Success\n");
+
+            return IndexerConfigurationStatus.RequiresTesting;
+        }
+
+        /// <summary>
+        /// Execute our search query
+        /// </summary>
+        /// <param name="query">Query</param>
+        /// <returns>Releases</returns>
+        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
+        {
+            var releases = new List<ReleaseInfo>();
+            var torrentRowList = new List<CQ>();
+            var searchTerm = query.GetQueryString();
+            var searchUrl = SearchUrl;
+            int nbResults = 0;
+            int pageLinkCount = 0;
+
+            // Check cache first so we don't query the server (if search term used or not in dev mode)
+            if (!DevMode && !string.IsNullOrEmpty(searchTerm))
+            {
+                lock (cache)
+                {
+                    // Remove old cache items
+                    CleanCache();
+
+                    // Search in cache
+                    var cachedResult = cache.Where(i => i.Query == searchTerm).FirstOrDefault();
+                    if (cachedResult != null)
+                        return cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray();
+                }
+            }
+
+            // Build our query
+            var request = buildQuery(searchTerm, query, searchUrl);
+
+            // Getting results & Store content
+            WebClientStringResult results = await queryExec(request);
+            fDom = results.Content;
+
+            try
+            {
+                // Find torrent rows
+                var firstPageRows = findTorrentRows();
+
+                // Add them to torrents list
+                torrentRowList.AddRange(firstPageRows.Select(fRow => fRow.Cq()));
+
+                // Check if there are pagination links at bottom
+                Boolean pagination = (fDom["#quicknavpage_menu"].Length != 0);
+
+                // If pagination available
+                if (pagination)
+                {
+                    // Retrieve available pages (3 pages shown max)
+                    pageLinkCount = fDom["#navcontainer_f:first > ul"].Find("a").Not(".smalltext").Not("#quicknavpage").Length;
+
+                    // Last button ? (So more than 3 page are available)
+                    Boolean more = (fDom["#navcontainer_f:first > ul"].Find("a.smalltext").Length > 1); ;
+                
+                    // More page than 3 pages ?
+                    if (more)
+                    {
+                        // Get total page count from last link
+                        pageLinkCount = ParseUtil.CoerceInt(Regex.Match(fDom["#navcontainer_f:first > ul"].Find("a:eq(4)").Attr("href").ToString(), @"\d+").Value);
+                    }
+
+                    // Calculate average number of results (based on torrents rows lenght on first page)
+                    nbResults = firstPageRows.Count() * pageLinkCount;
+                }
+                else {
+                    nbResults = 1;
+                    pageLinkCount = 1;
+
+                    // Check if we have a minimum of one result
+                    if (firstPageRows.Length > 1)
+                    {
+                        // Retrieve total count on our alone page
+                        nbResults = firstPageRows.Count();
+                    }
+                    else
+                    {
+                        // Check if no result
+                        if(torrentRowList.First().Find("td").Length == 1)
+                        {
+                            // No results found
+                            output("\nNo result found for your query, please try another search term ...\n", "info");
+
+                            // No result found for this query
+                            return releases;
+                        }
+                    }
+                }
+                output("\nFound " + nbResults + " result(s) (+/- " + firstPageRows.Length + ") in " + pageLinkCount + " page(s) for this query !");
+                output("\nThere are " + firstPageRows.Length + " results on the first page !");
+
+                // If we have a term used for search and pagination result superior to one
+                if (!string.IsNullOrWhiteSpace(query.GetQueryString()) && pageLinkCount > 1)
+                {
+                    // Starting with page #2
+                    for (int i = 2; i <= Math.Min(Int32.Parse(ConfigData.Pages.Value), pageLinkCount); i++)
+                    {
+                        output("\nProcessing page #" + i);
+
+                        // Request our page
+                        latencyNow();
+
+                        // Build our query -- Minus 1 to page due to strange pagination number on tracker side, starting with page 0...
+                        var pageRequest = buildQuery(searchTerm, query, searchUrl, i);
+
+                        // Getting results & Store content
+                        WebClientStringResult pageResults = await queryExec(pageRequest);
+
+                        // Assign response
+                        fDom = pageResults.Content;
+
+                        // Process page results
+                        var additionalPageRows = findTorrentRows();
+
+                        // Add them to torrents list
+                        torrentRowList.AddRange(additionalPageRows.Select(fRow => fRow.Cq()));
+                    }
+                }
+
+                // Loop on results
+                foreach (CQ tRow in torrentRowList)
+                {
+                    output("\n=>> Torrent #" + (releases.Count + 1));
+
+                    // ID
+                    int id = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(1) > div:first > a").Attr("name").ToString(), @"\d+").Value);
+                    output("ID: " + id);
+
+                    // Check if torrent is not nuked by tracker or rulez, can't download it
+                    if (tRow.Find("td:eq(2) > a").Length == 0)
+                    {
+                        // Next item
+                        output("Torrent is nuked, we can't download it, going to next torrent...");
+                        continue;
+                    }
+
+                    // Release Name
+                    string name = tRow.Find("td:eq(2) > a").Attr("title").ToString().Substring(24).Trim();
+                    output("Release: " + name);
+
+                    // Category
+                    int categoryID = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(0) > a").Attr("href").ToString(), @"\d+").Value);
+                    string categoryName = tRow.Find("td:eq(0) > a > img").Attr("title").Split(new[] { ':' }, 2)[1].Trim().ToString();
+                    output("Category: " + MapTrackerCatToNewznab(categoryID.ToString()) + " (" + categoryID + " - " + categoryName + ")");
+
+                    // Seeders
+                    int seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(5) > div > font").Select(s => Regex.Replace(s.ToString(), "<.*?>", String.Empty)).ToString(), @"\d+").Value);
+                    output("Seeders: " + seeders);
+
+                    // Leechers
+                    int leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(6) > div > font").Text().ToString(), @"\d+").Value);
+                    output("Leechers: " + leechers);
+
+                    // Completed
+                    int completed = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(4)").Text().ToString(), @"\d+").Value);
+                    output("Completed: " + completed);
+
+                    // Files
+                    int files = 1;
+                    if (tRow.Find("td:eq(3) > a").Length == 1)
+                    {
+                        files = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(3) > a").Text().ToString(), @"\d+").Value);
+                    }
+                    output("Files: " + files);
+
+                    // Health
+                    int percent = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(7) > img").Attr("src").ToString(), @"\d+").Value) * 10;
+                    output("Health: " + percent + "%");
+
+                    // Size
+                    string humanSize = tRow.Find("td:eq(8)").Text().ToString().ToLowerInvariant();
+                    long size = ReleaseInfo.GetBytes(humanSize);
+                    output("Size: " + humanSize + " (" + size + " bytes)");
+
+                    // Date & IMDB & Genre
+                    string infosData = tRow.Find("td:eq(1) > div:last").Text().ToString();
+                    IList<string> infosList = Regex.Split(infosData, "\\|").ToList();
+                    IList<string> infosTorrent = infosList.Select(s => s.Split(new[] { ':' }, 2)[1].Trim()).ToList();
+
+                    // --> Date
+                    DateTime date = formatDate(infosTorrent.First());
+                    output("Released on: " + date.ToLocalTime().ToString());
+
+                    // --> Genre
+                    string genre = infosTorrent.Last();
+                    output("Genre: " + genre);
+
+                    // Torrent Details URL
+                    Uri detailsLink = new Uri(TorrentDescriptionUrl.Replace("{id}", id.ToString()));
+                    output("Details: " + detailsLink.AbsoluteUri);
+
+                    // Torrent Comments URL
+                    Uri commentsLink = new Uri(TorrentCommentUrl.Replace("{id}", id.ToString()));
+                    output("Comments Link: " + commentsLink.AbsoluteUri);
+
+                    // Torrent Download URL
+                    Uri downloadLink = new Uri(TorrentDownloadUrl.Replace("{id}", id.ToString()));
+                    output("Download Link: " + downloadLink.AbsoluteUri);
+
+                    // Building release infos
+                    var release = new ReleaseInfo();
+                    release.Category = MapTrackerCatToNewznab(categoryID.ToString());
+                    release.Title = name;
+                    release.Seeders = seeders;
+                    release.Peers = seeders + leechers;
+                    release.MinimumRatio = 1;
+                    release.MinimumSeedTime = 172800;
+                    release.PublishDate = date;
+                    release.Size = size;
+                    release.Guid = detailsLink;
+                    release.Comments = commentsLink;
+                    release.Link = downloadLink;
+                    releases.Add(release);
+                }
+
+            }
+            catch (Exception ex)
+            {
+                OnParseError("Error, unable to parse result \n" + ex.StackTrace, ex);
+            }
+
+            // Return found releases
+            return releases;
+        }
+
+        /// <summary>
+        /// Build query to process
+        /// </summary>
+        /// <param name="term">Term to search</param>
+        /// <param name="query">Torznab Query for categories mapping</param>
+        /// <param name="url">Search url for provider</param>
+        /// <param name="page">Page number to request</param>
+        /// <returns>URL to query for parsing and processing results</returns>
+        private string buildQuery(string term, TorznabQuery query, string url, int page = 0)
+        {
+            var parameters = new NameValueCollection();
+            List<string> categoriesList = MapTorznabCapsToTrackers(query);
+
+            // Building our tracker query
+            parameters.Add("do", "search");
+
+            // If search term provided
+            if (!string.IsNullOrWhiteSpace(term))
+            {
+                // Add search term ~~ Strange search engine, need to replace space with dot for results !
+                parameters.Add("keywords", term.Replace(' ', '.'));
+            }
+            else
+            {
+                // Showing all torrents (just for output function)
+                parameters.Add("keywords", "");
+                term = "all";
+            }
+
+            // Adding requested categories
+            if(categoriesList.Count > 0)
+            {
+                // Add categories
+                parameters.Add("category", String.Join(",", categoriesList));
+            }
+            else
+            {
+                // Add empty category parameter
+                parameters.Add("category", "");
+            }
+
+            // Building our tracker query
+            parameters.Add("search_type", "t_name");
+
+            // Check if we are processing a new page
+            if (page > 1)
+            {
+                // Adding page number to query
+                parameters.Add("page", page.ToString());
+            }
+
+            // Building our query
+            url += "?" + parameters.GetQueryString();
+
+            output("\nBuilded query for \"" + term + "\"... " + url);
+
+            // Return our search url
+            return url;
+        }
+
+        /// <summary>
+        /// Switch Method for Querying
+        /// </summary>
+        /// <param name="request">URL created by Query Builder</param>
+        /// <returns>Results from query</returns>
+        private async Task<WebClientStringResult> queryExec(string request)
+        {
+            WebClientStringResult results = null;
+
+            // Switch in we are in DEV mode with Hard Drive Cache or not
+            if (DevMode && CacheMode)
+            {
+                // Check Cache before querying and load previous results if available
+                results = await queryCache(request);
+            }
+            else
+            {
+                // Querying tracker directly
+                results = await queryTracker(request);
+            }
+            return results;
+        }
+
+        /// <summary>
+        /// Get Torrents Page from Cache by Query Provided
+        /// </summary>
+        /// <param name="request">URL created by Query Builder</param>
+        /// <returns>Results from query</returns>
+        private async Task<WebClientStringResult> queryCache(string request)
+        {
+            WebClientStringResult results = null;
+
+            // Create Directory if not exist
+            System.IO.Directory.CreateDirectory(directory);
+
+            // Clean Storage Provider Directory from outdated cached queries
+            cleanCacheStorage();
+
+            // Create fingerprint for request
+            string file = directory + request.GetHashCode() + ".json";
+
+            // Checking modes states
+            if (System.IO.File.Exists(file))
+            {
+                // File exist... loading it right now !
+                output("Loading results from hard drive cache ..." + request.GetHashCode() + ".json");
+                results = JsonConvert.DeserializeObject<WebClientStringResult>(System.IO.File.ReadAllText(file));
+            }
+            else
+            {
+                // No cached file found, querying tracker directly
+                results = await queryTracker(request);
+
+                // Cached file didn't exist for our query, writing it right now !
+                output("Writing results to hard drive cache ..." + request.GetHashCode() + ".json");
+                System.IO.File.WriteAllText(file, JsonConvert.SerializeObject(results));
+            }
+            return results;
+        }
+
+        /// <summary>
+        /// Get Torrents Page from Tracker by Query Provided
+        /// </summary>
+        /// <param name="request">URL created by Query Builder</param>
+        /// <returns>Results from query</returns>
+        private async Task<WebClientStringResult> queryTracker(string request)
+        {
+            WebClientStringResult results = null;
+
+            // Cache mode not enabled or cached file didn't exist for our query
+            output("\nQuerying tracker for results....");
+
+            // Request our first page
+            latencyNow();
+            results = await RequestStringWithCookiesAndRetry(request, ConfigData.CookieHeader.Value, SearchUrl, emulatedBrowserHeaders);
+
+            // Return results from tracker
+            return results;
+        }
+
+        /// <summary>
+        /// Clean Hard Drive Cache Storage
+        /// </summary>
+        /// <param name="force">Force Provider Folder deletion</param>
+        private void cleanCacheStorage(Boolean force = false)
+        {
+            // Check cleaning method
+            if (force)
+            {
+                // Deleting Provider Storage folder and all files recursively
+                output("\nDeleting Provider Storage folder and all files recursively ...");
+
+                // Check if directory exist
+                if (System.IO.Directory.Exists(directory))
+                {
+                    // Delete storage directory of provider
+                    System.IO.Directory.Delete(directory, true);
+                    output("-> Storage folder deleted successfully.");
+                }
+                else
+                {
+                    // No directory, so nothing to do
+                    output("-> No Storage folder found for this provider !");
+                }
+            }
+            else
+            {
+                int i = 0;
+                // Check if there is file older than ... and delete them
+                output("\nCleaning Provider Storage folder... in progress.");
+                System.IO.Directory.GetFiles(directory)
+                .Select(f => new System.IO.FileInfo(f))
+                .Where(f => f.LastAccessTime < DateTime.Now.AddMilliseconds(-Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value)))
+                .ToList()
+                .ForEach(f => {
+                    output("Deleting cached file << " + f.Name + " >> ... done.");
+                    f.Delete();
+                    i++;
+                });
+
+                // Inform on what was cleaned during process
+                if (i > 0)
+                {
+                    output("-> Deleted " + i + " cached files during cleaning.");
+                }
+                else {
+                    output("-> Nothing deleted during cleaning.");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Generate a random fake latency to avoid detection on tracker side
+        /// </summary>
+        private void latencyNow()
+        {
+            // Need latency ?
+            if (Latency)
+            {
+                // Generate a random value in our range
+                var random = new Random(DateTime.Now.Millisecond);
+                int waiting = random.Next(Convert.ToInt32(ConfigData.LatencyStart.Value), Convert.ToInt32(ConfigData.LatencyEnd.Value));
+                output("\nLatency Faker => Sleeping for " + waiting + " ms...");
+
+                // Sleep now...
+                System.Threading.Thread.Sleep(waiting);
+            }
+        }
+
+        /// <summary>
+        /// Find torrent rows in search pages
+        /// </summary>
+        /// <returns>JQuery Object</returns>
+        private CQ findTorrentRows()
+        {
+            // Return all occurencis of torrents found
+            return fDom["#showcontents > table > tbody > tr:not(:first)"];
+        }
+
+        /// <summary>
+        /// Format Date to DateTime
+        /// </summary>
+        /// <param name="clock"></param>
+        /// <returns>A DateTime</returns>
+        private DateTime formatDate(string clock)
+        {
+            DateTime date;
+
+            // Switch from date format
+            if(clock.Contains("Aujourd'hui") || clock.Contains("Hier"))
+            {
+                // Get hours & minutes
+                IList<int> infosClock = clock.Split(':').Select(s => ParseUtil.CoerceInt(Regex.Match(s, @"\d+").Value)).ToList();
+
+                // Ago date with today
+                date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, Convert.ToInt32(infosClock[0]), Convert.ToInt32(infosClock[1]), DateTime.Now.Second);
+
+                // Set yesterday if necessary
+                if (clock.Contains("Hier"))
+                {
+                    // Remove one day from date
+                    date.AddDays(-1);
+                }
+            }
+            else
+            {
+                // Parse Date if full
+                date = DateTime.ParseExact(clock, "MM-dd-yyyy HH:mm", CultureInfo.GetCultureInfo("fr-FR"), DateTimeStyles.AssumeLocal);
+            }
+
+            return date.ToUniversalTime();
+        }
+
+        /// <summary>
+        /// Download torrent file from tracker
+        /// </summary>
+        /// <param name="link">URL string</param>
+        /// <returns></returns>
+        public async override Task<byte[]> Download(Uri link)
+        {
+            var dl = link.AbsoluteUri;
+            // This tracker need to thanks Uploader before getting torrent file...
+            output("\nThis tracker needs you to thank uploader before downloading torrent!");
+
+            // Retrieving ID from link provided
+            int id = ParseUtil.CoerceInt(Regex.Match(link.AbsoluteUri, @"\d+").Value);
+            output("Torrent Requested ID: " + id);
+
+            // Building login form data
+            var pairs = new Dictionary<string, string> {
+                { "torrentid", id.ToString() },
+                { "_", string.Empty } // ~~ Strange, blank param...
+            };
+
+            // Add emulated XHR request
+            emulatedBrowserHeaders.Add("X-Prototype-Version", "1.6.0.3");
+            emulatedBrowserHeaders.Add("X-Requested-With", "XMLHttpRequest");
+
+            // Build WebRequest for thanks
+            var myRequestThanks = new WebRequest()
+            {
+                Type = RequestType.POST,
+                PostData = pairs,
+                Url = TorrentThanksUrl,
+                Headers = emulatedBrowserHeaders,
+                Cookies = ConfigData.CookieHeader.Value,
+                Referer = TorrentDescriptionUrl.Replace("{id}", id.ToString())
+            };
+
+            // Get thanks page -- (not used, just for doing a request)
+            latencyNow();
+            output("Thanks user, to get download link for our torrent.. with " + TorrentThanksUrl);
+            var thanksPage = await webclient.GetString(myRequestThanks);
+
+            // Get torrent file now
+            output("Getting torrent file now....");
+            var response = await base.Download(link);
+
+            // Remove our XHR request header
+            emulatedBrowserHeaders.Remove("X-Prototype-Version");
+            emulatedBrowserHeaders.Remove("X-Requested-With");
+
+            // Return content
+            return response;
+        }
+
+        /// <summary>
+        /// Output message for logging or developpment (console)
+        /// </summary>
+        /// <param name="message">Message to output</param>
+        /// <param name="level">Level for Logger</param>
+        private void output(string message, string level = "debug")
+        {
+            // Check if we are in dev mode
+            if (DevMode)
+            {
+                // Output message to console
+                Console.WriteLine(message);
+            }
+            else
+            {
+                // Send message to logger with level
+                switch (level)
+                {
+                    default:
+                        goto case "debug";
+                    case "debug":
+                        // Only if Debug Level Enabled on Jackett
+                        if (Engine.Logger.IsDebugEnabled)
+                        {
+                            logger.Debug(message);
+                        }
+                        break;
+                    case "info":
+                        logger.Info(message);
+                        break;
+                    case "error":
+                        logger.Error(message);
+                        break;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Validate Config entered by user on Jackett
+        /// </summary>
+        private void validateConfig()
+        {
+            output("\nValidating Settings ... \n");
+
+            // Check Username Setting
+            if (string.IsNullOrEmpty(ConfigData.Username.Value))
+            {
+                throw new ExceptionWithConfigData("You must provide a username for this tracker to login !", ConfigData);
+            }
+            else
+            {
+                output("Validated Setting -- Username (auth) => " + ConfigData.Username.Value.ToString());
+            }
+
+            // Check Password Setting
+            if (string.IsNullOrEmpty(ConfigData.Password.Value))
+            {
+                throw new ExceptionWithConfigData("You must provide a password with your username for this tracker to login !", ConfigData);
+            }
+            else
+            {
+                output("Validated Setting -- Password (auth) => " + ConfigData.Password.Value.ToString());
+            }
+
+            // Check Max Page Setting
+            if (!string.IsNullOrEmpty(ConfigData.Pages.Value))
+            {
+                try
+                {
+                    output("Validated Setting -- Max Pages => " + Convert.ToInt32(ConfigData.Pages.Value));
+                }
+                catch (Exception)
+                {
+                    throw new ExceptionWithConfigData("Please enter a numeric maximum number of pages to crawl !", ConfigData);
+                }
+            }
+            else
+            {
+                throw new ExceptionWithConfigData("Please enter a maximum number of pages to crawl !", ConfigData);
+            }
+
+            // Check Latency Setting
+            if (ConfigData.Latency.Value)
+            {
+                output("\nValidated Setting -- Latency Simulation enabled");
+
+                // Check Latency Start Setting
+                if (!string.IsNullOrEmpty(ConfigData.LatencyStart.Value))
+                {
+                    try
+                    {
+                        output("Validated Setting -- Latency Start => " + Convert.ToInt32(ConfigData.LatencyStart.Value));
+                    }
+                    catch (Exception)
+                    {
+                        throw new ExceptionWithConfigData("Please enter a numeric latency start in ms !", ConfigData);
+                    }
+                }
+                else
+                {
+                    throw new ExceptionWithConfigData("Latency Simulation enabled, Please enter a start latency !", ConfigData);
+                }
+
+                // Check Latency End Setting
+                if (!string.IsNullOrEmpty(ConfigData.LatencyEnd.Value))
+                {
+                    try
+                    {
+                        output("Validated Setting -- Latency End => " + Convert.ToInt32(ConfigData.LatencyEnd.Value));
+                    }
+                    catch (Exception)
+                    {
+                        throw new ExceptionWithConfigData("Please enter a numeric latency end in ms !", ConfigData);
+                    }
+                }
+                else
+                {
+                    throw new ExceptionWithConfigData("Latency Simulation enabled, Please enter a end latency !", ConfigData);
+                }
+            }
+
+            // Check Browser Setting
+            if (ConfigData.Browser.Value == true)
+            {
+                output("\nValidated Setting -- Browser Simulation enabled");
+
+                // Check ACCEPT header Setting
+                if (string.IsNullOrEmpty(ConfigData.HeaderAccept.Value))
+                {
+                    throw new ExceptionWithConfigData("Browser Simulation enabled, Please enter an ACCEPT header !", ConfigData);
+                }
+                else
+                {
+                    output("Validated Setting -- ACCEPT (header) => " + ConfigData.HeaderAccept.Value.ToString());
+                }
+
+                // Check ACCEPT-LANG header Setting
+                if (string.IsNullOrEmpty(ConfigData.HeaderAcceptLang.Value))
+                {
+                    throw new ExceptionWithConfigData("Browser Simulation enabled, Please enter an ACCEPT-LANG header !", ConfigData);
+                }
+                else
+                {
+                    output("Validated Setting -- ACCEPT-LANG (header) => " + ConfigData.HeaderAcceptLang.Value.ToString());
+                }
+
+                // Check USER-AGENT header Setting
+                if (string.IsNullOrEmpty(ConfigData.HeaderUserAgent.Value))
+                {
+                    throw new ExceptionWithConfigData("Browser Simulation enabled, Please enter an USER-AGENT header !", ConfigData);
+                }
+                else
+                {
+                    output("Validated Setting -- USER-AGENT (header) => " + ConfigData.HeaderUserAgent.Value.ToString());
+                }
+            }
+            else
+            {
+                // Browser simulation must be enabled (otherwhise, this provider will not work due to tracker's security)
+                throw new ExceptionWithConfigData("Browser Simulation must be enabled for this provider to work, please enable it !", ConfigData);
+            }
+
+            // Check Dev Cache Settings
+            if (ConfigData.HardDriveCache.Value == true)
+            {
+                output("\nValidated Setting -- DEV Hard Drive Cache enabled");
+
+                // Check if Dev Mode enabled !
+                if (!ConfigData.DevMode.Value)
+                {
+                    throw new ExceptionWithConfigData("Hard Drive is enabled but not in DEV MODE, Please enable DEV MODE !", ConfigData);
+                }
+
+                // Check Cache Keep Time Setting
+                if (!string.IsNullOrEmpty(ConfigData.HardDriveCacheKeepTime.Value))
+                {
+                    try
+                    {
+                        output("Validated Setting -- Cache Keep Time (ms) => " + Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value));
+                    }
+                    catch (Exception)
+                    {
+                        throw new ExceptionWithConfigData("Please enter a numeric hard drive keep time in ms !", ConfigData);
+                    }
+                }
+                else
+                {
+                    throw new ExceptionWithConfigData("Hard Drive Cache enabled, Please enter a maximum keep time for cache !", ConfigData);
+                }
+            }
+            else
+            {
+                // Delete cache if previously existed
+                cleanCacheStorage(true);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj
index 4bed2f73..8f1d8791 100644
--- a/src/Jackett/Jackett.csproj
+++ b/src/Jackett/Jackett.csproj
@@ -207,11 +207,13 @@
     <Compile Include="Indexers\ImmortalSeed.cs" />
     <Compile Include="Indexers\FileList.cs" />
     <Compile Include="Indexers\Abstract\AvistazTracker.cs" />
+    <Compile Include="Indexers\FrenchADN.cs" />
     <Compile Include="Indexers\WiHD.cs" />
     <Compile Include="Indexers\XSpeeds.cs" />
     <Compile Include="Models\GitHub\Asset.cs" />
     <Compile Include="Models\GitHub\Release.cs" />
     <Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataBlueTigers.cs" />
+    <Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataFrenchADN.cs" />
     <Compile Include="Models\IndexerConfig\Bespoke\ConfigurationDataWiHD.cs" />
     <Compile Include="Models\IndexerConfig\ConfigurationDataBasicLoginWithFilter.cs" />
     <Compile Include="Models\IndexerConfig\ConfigurationDataAPIKey.cs" />
@@ -566,6 +568,9 @@
     <Content Include="Content\logos\tvchaosuk.png">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="Content\logos\frenchadn.png">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="Content\logos\wihd.png">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
diff --git a/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataFrenchADN.cs b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataFrenchADN.cs
new file mode 100644
index 00000000..f41af8e7
--- /dev/null
+++ b/src/Jackett/Models/IndexerConfig/Bespoke/ConfigurationDataFrenchADN.cs
@@ -0,0 +1,53 @@
+namespace Jackett.Models.IndexerConfig.Bespoke
+{
+    class ConfigurationDataFrenchADN : ConfigurationData
+    {
+        public DisplayItem CredentialsWarning { get; private set; }
+        public StringItem Username { get; private set; }
+        public StringItem Password { get; private set; }
+        public DisplayItem PagesWarning { get; private set; }
+        public StringItem Pages { get; private set; }
+        public DisplayItem SecurityWarning { get; private set; }
+        public BoolItem Latency { get; private set; }
+        public BoolItem Browser { get; private set; }
+        public DisplayItem LatencyWarning { get; private set; }
+        public StringItem LatencyStart { get; private set; }
+        public StringItem LatencyEnd { get; private set; }
+        public DisplayItem HeadersWarning { get; private set; }
+        public StringItem HeaderAccept { get; private set; }
+        public StringItem HeaderAcceptLang { get; private set; }
+        public BoolItem HeaderDNT { get; private set; }
+        public BoolItem HeaderUpgradeInsecure { get; private set; }
+        public StringItem HeaderUserAgent { get; private set; }
+        public DisplayItem DevWarning { get; private set; }
+        public BoolItem DevMode { get; private set; }
+        public BoolItem HardDriveCache { get; private set; }
+        public StringItem HardDriveCacheKeepTime { get; private set; }
+
+        public ConfigurationDataFrenchADN()
+            : base()
+        {
+            CredentialsWarning = new DisplayItem("<b>Credentials Configuration</b> (<i>Private Tracker</i>),<br /><br /> <ul><li><b>Username</b> is your account name on this tracker.</li><li><b>Password</b> is your password associated to your account name.</li></ul>") { Name = "Credentials" };
+            Username = new StringItem { Name = "Username (Required)", Value = "" };
+            Password = new StringItem { Name = "Password (Required)", Value = "" };
+            PagesWarning = new DisplayItem("<b>Preferences Configuration</b> (<i>Tweak your search settings</i>),<br /><br /> <ul><li><b>Max Pages to Process</b> let you specify how many page (max) Jackett can process when doing a search. Setting a value <b>higher than 4 is dangerous</b> for you account ! (<b>Result of too many requests to tracker...that <u>will be suspect</u></b>).</li></ul>") { Name = "Preferences" };
+            Pages = new StringItem { Name = "Max Pages to Process (Required)", Value = "4" };
+            SecurityWarning = new DisplayItem("<b>Security Configuration</b> (<i>Read this area carefully !</i>),<br /><br /> <ul><li><b>Latency Simulation</b> will simulate human browsing with Jacket by pausing Jacket for an random time between each request, to fake a real content browsing.</li><li><b>Browser Simulation</b> will simulate a real human browser by injecting additionals headers when doing requests to tracker.<b>You must enable it to use this provider!</b></li></ul>") { Name = "Security" };
+            Latency = new BoolItem() { Name = "Latency Simulation (Optional)", Value = false };
+            Browser = new BoolItem() { Name = "Browser Simulation (Forced)", Value = true };
+            LatencyWarning = new DisplayItem("<b>Latency Configuration</b> (<i>Required if latency simulation enabled</i>),<br /><br/> <ul><li>By filling this range, <b>Jackett will make a random timed pause</b> <u>between requests</u> to tracker <u>to simulate a real browser</u>.</li><li>MilliSeconds <b>only</b></li></ul>") { Name = "Simulate Latency" };
+            LatencyStart = new StringItem { Name = "Minimum Latency (ms)", Value = "1589" };
+            LatencyEnd = new StringItem { Name = "Maximum Latency (ms)", Value = "3674" };
+            HeadersWarning = new DisplayItem("<b>Browser Headers Configuration</b> (<i>Required if browser simulation enabled</i>),<br /><br /> <ul><li>By filling these fields, <b>Jackett will inject headers</b> with your values <u>to simulate a real browser</u>.</li><li>You can get <b>your browser values</b> here: <a href='https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending' target='blank'>www.whatismybrowser.com</a></li></ul><br /><i><b>Note that</b> some headers are not necessary because they are injected automatically by this provider such as Accept_Encoding, Connection, Host or X-Requested-With</i>") { Name = "Injecting headers" };
+            HeaderAccept = new StringItem { Name = "Accept", Value = "" };
+            HeaderAcceptLang = new StringItem { Name = "Accept-Language", Value = "" };
+            HeaderDNT = new BoolItem { Name = "DNT", Value = false };
+            HeaderUpgradeInsecure = new BoolItem { Name = "Upgrade-Insecure-Requests", Value = false };
+            HeaderUserAgent = new StringItem { Name = "User-Agent", Value = "" };
+            DevWarning = new DisplayItem("<b>Development Facility</b> (<i>For Developers ONLY</i>),<br /><br /> <ul><li>By enabling development mode, <b>Jackett will bypass his cache</b> and will <u>output debug messages to console</u> instead of his log file.</li><li>By enabling Hard Drive Cache, <b>This provider</b> will <u>save each query answers from tracker</u> in temp directory, in fact this reduce drastically HTTP requests when building a provider at parsing step for example. So, <b> Jackett will search for a cached query answer on hard drive before executing query on tracker side !</b> <i>DEV MODE must be enabled to use it !</li></ul>") { Name = "Development" };
+            DevMode = new BoolItem { Name = "Enable DEV MODE (Developers ONLY)", Value = false };
+            HardDriveCache = new BoolItem { Name = "Enable HARD DRIVE CACHE (Developers ONLY)", Value = false };
+            HardDriveCacheKeepTime = new StringItem { Name = "Keep Cached files for (ms)", Value = "300000" };
+        }
+    }
+}
\ No newline at end of file
-- 
GitLab