// ==UserScript== // ----------------------------------- MetaData -------------------------------------- // @name qui - quiCKIE // @author WirlyWirly + Contributors π«Ά // @version 1.47 // @homepage https://github.com/WirlyWirly/quiCKIE // @description A UserScript to quickly send torrents from a tracker to a client, with customizable per-site settings and presets π° // Orignally written for qui, later extended to support more torrent clients // Written on LibreWolf via Violentmonkey // @namespace https://github.com/WirlyWirly // @icon https://raw.githubusercontent.com/WirlyWirly/quiCKIE/main/icon.webp?raw=true // @run-at document-end // ----------------------------------- Matches -------------------------------------- // Adding a New Tracker: https://github.com/WirlyWirly/quiCKIE/wiki/Adding-a-New-Tracker // @match https://aither.cc/ // @match https://aither.cc/*/bookmarks* // @match https://aither.cc/playlists/* // @match https://aither.cc/torrents* // @match https://alpharatio.cc/top10.php* // @match https://alpharatio.cc/torrents.php* // @match https://animebytes.tv/alltorrents.php?*&userid=* // @match https://animebytes.tv/artist.php?id=* // @match https://animebytes.tv/bookmarks.php* // @match https://animebytes.tv/collage.php?*id=* // @match https://animebytes.tv/company.php?id=* // @match https://animebytes.tv/series.php?id=* // @match https://animebytes.tv/torrents* // @match https://animez.to/ // @match https://animez.to/torrents* // @match https://animez.to/torrent-bookmarks* // @match https://anthelion.me/torrents.php* // @match https://avistaz.to/ // @match https://avistaz.to/*/bookmark* // @match https://avistaz.to/torrent* // @match https://bakabt.me/torrent/* // @match https://beyond-hd.me/ // @match https://beyond-hd.me/bookmarks* // @match https://beyond-hd.me/download/* // @match https://beyond-hd.me/library* // @match https://beyond-hd.me/torrents* // @match https://beyond-hd.me/torrents/seed* // @match https://beyond-hd.me/watchlist* // @match https://bibliotik.me/collections/* // @match https://bibliotik.me/notifications/torrents* // @match https://bibliotik.me/torrents/* // @match https://bibliotik.me/users/*/leeching* // @match https://bibliotik.me/users/*/seeding* // @match https://bibliotik.me/users/*/snatches* // @match https://bibliotik.me/users/*/uploads* // @match https://bitporn.eu/ // @match https://bitporn.eu/*/bookmarks* // @match https://bitporn.eu/playlists/* // @match https://bitporn.eu/torrents* // @match https://broadcasthe.net/collages.php?id=* // @match https://broadcasthe.net/series.php?id=* // @match https://broadcasthe.net/torrents.php* // @match https://cinemaz.to/ // @match https://cinemaz.to/*/bookmark* // @match https://cinemaz.to/torrent/* // @match https://clearjav.com/ // @match https://clearjav.com/*/bookmarks* // @match https://clearjav.com/movies/* // @match https://clearjav.com/playlists/* // @match https://clearjav.com/torrents* // @match https://www.deepbassnine.com/artist.php?id=* // @match https://www.deepbassnine.com/collages.php?id=* // @match https://www.deepbassnine.com/torrents.php* // @match https://digitalcore.club/ // @match https://digitalcore.club/alltorrents* // @match https://digitalcore.club/apps* // @match https://digitalcore.club/bookmarks* // @match https://digitalcore.club/games* // @match https://digitalcore.club/movies* // @match https://digitalcore.club/music* // @match https://digitalcore.club/other* // @match https://digitalcore.club/torrent-lists/* // @match https://digitalcore.club/torrent/* // @match https://digitalcore.club/tvseries* // @match https://digitalcore.club/xxx* // @include /^https://(www\.empornium|emparadise)\.(sx|rs)/collage/\d.*/ // @include /^https://(www\.empornium|emparadise)\.(sx|rs)/top10\.php.*/ // @include /^https://(www\.empornium|emparadise)\.(sx|rs)/torrents\.php.*/ // @include /^https://(www\.empornium|emparadise)\.(sx|rs)/user\.php\?id=\d+/ // @match https://e*hentai.org/gallerytorrents.php* // @match https://exoticaz.to/ // @match https://exoticaz.to/*/bookmark* // @match https://exoticaz.to/torrent* // @match https://femdomcult.org/collage/* // @match https://femdomcult.org/torrents.php* // @match https://gazellegames.net/collections.php?id=* // @match https://gazellegames.net/torrents.php* // @match https://gazellegames.net/bookmarks.php* // @match https://www.happyfappy.net/collage/* // @match https://www.happyfappy.net/top10.php* // @match https://www.happyfappy.net/torrents.php* // @match https://www.happyfappy.net/user.php?id=* // @match https://hdbits.org/bookmarks* // @match https://hdbits.org/browse.php* // @match https://hdbits.org/details.php?id=* // @match https://hdbits.org/film/info?id=* // @include /^https://iptorrents\.\w+/details.php?id=.*/ // @include /^https://iptorrents\.\w+/t.*/ // @include /^https://iptorrents\.\w+/torrent.php?id=.*/ // @match https://jpopsuki.eu/artist.php?id=* // @match https://jpopsuki.eu/collages.php?id=* // @match https://jpopsuki.eu/top10.php* // @match https://jpopsuki.eu/torrents.php* // @match https://karagarga.in/details.php* // @match https://karagarga.in/browse.php* // @match https://kufirc.com/bookmarks.php* // @match https://kufirc.com/collages.php* // @match https://kufirc.com/top10.php* // @match https://kufirc.com/torrents.php* // @match https://lat-team.com/ // @match https://lat-team.com/*/bookmarks // @match https://lat-team.com/playlists/* // @match https://lat-team.com/torrents* // @match https://lst.gg/ // @match https://lst.gg/*/bookmarks* // @match https://lst.gg/playlists/* // @match https://lst.gg/torrents* // @match https://luminarr.me/ // @match https://luminarr.me/*/bookmarks // @match https://luminarr.me/playlists/* // @match https://luminarr.me/torrents* // @match https://materialize.is/collages.php?id=* // @match https://materialize.is/top10.php* // @match https://materialize.is/torrents.php* // @match https://www.morethantv.me/collage/* // @match https://www.morethantv.me/top10.php* // @match https://www.morethantv.me/torrents/browse* // @match https://www.myanonamouse.net/ // @match https://www.myanonamouse.net/stats/top10Tor.php* // @match https://www.myanonamouse.net/t/* // @match https://www.myanonamouse.net/tor/browse.php* // @match https://www.myanonamouse.net/tor/search.php* // @match https://nebulance.io/bookmarks.php* // @match https://nebulance.io/top10.php* // @match https://nebulance.io/torrents.php* // @match https://nebulance.io/details.php* // @include /^https://(sukebei\.)?nyaa\.\w+/.*/ // @include /^https://(sukebei\.)?nyaa\.\w+/view/.*/ // @match https://oldtoons.world/ // @match https://oldtoons.world/*/bookmarks // @match https://oldtoons.world/playlists/* // @match https://oldtoons.world/torrents* // @match https://orpheus.network/artist.php?id=* // @match https://orpheus.network/bookmarks.php* // @match https://orpheus.network/collages.php?id=* // @match https://orpheus.network/top10.php* // @match https://orpheus.network/torrents.php* // @match https://passthepopcorn.me/torrents.php?id=* // @match https://portugas.org/ // @match https://portugas.org/*/bookmarks // @match https://portugas.org/playlists/* // @match https://portugas.org/torrents* // @match https://privatehd.to/ // @match https://privatehd.to/torrent* // @match https://privatehd.to/*/bookmark* // @match https://redacted.sh/artist.php?id=* // @match https://redacted.sh/bookmarks.php* // @match https://redacted.sh/collage*.php?id=* // @match https://redacted.sh/top10.php* // @match https://redacted.sh/torrents.php* // @match https://redacted.sh/userhistory.php?action=subscribed_collages // @match https://retro-movies.club/ // @match https://retro-movies.club/*/bookmarks // @match https://retro-movies.club/playlists/* // @match https://retro-movies.club/torrents* // @match https://secret-cinema.pw/artist.php?id=* // @match https://secret-cinema.pw/collages.php?id=* // @match https://secret-cinema.pw/top10.php* // @match https://secret-cinema.pw/torrents.php* // @match https://thegeeks.click/browse.php* // @match https://thegeeks.click/details.php?id=* // @match https://www.torrentleech.org/torrent* // @match https://tv-vault.me/torrents.php?id=* // ----------------------------------- Permissions -------------------------------------- // @grant GM_addStyle // @grant GM_getResourceText // @grant GM_getValue // @grant GM_listValues // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_xmlhttpRequest // ----------------------------------- Dependencies -------------------------------------- // @resource settingsPanelCSS https://raw.githubusercontent.com/WirlyWirly/quiCKIE/main/quiCKIE.css?raw=true // @resource presetsMenuCSS https://raw.githubusercontent.com/WirlyWirly/quiCKIE/main/contextMenu.css?raw=true // @require https://raw.githubusercontent.com/WirlyWirly/quiCKIE/main/contextMenu.js?raw=true // @require https://raw.githubusercontent.com/WirlyWirly/UserScripts/main/HelperScripts/simpleLogger.js // @require https://cdn.jsdelivr.net/gh/sizzlemctwizzle/GM_config@43fd0fe4de1166f343883511e53546e87840aeaf/gm_config.js // ----------------------------------- Development -------------------------------------- // localhost urls used during development. Easily served over http by MiniServe: https://github.com/svenstaro/miniserve // resource settingsPanelCSS http://localhost:12345/quiCKIE.css // resource presetsMenuCSS http://localhost:12345/ContextMenu.css // require http://localhost:12345/ContextMenu.js // ----------------------------------- Script Links -------------------------------------- // @updateURL https://raw.githubusercontent.com/WirlyWirly/quiCKIE/main/quiCKIE.user.js?raw=true // @downloadURL https://raw.githubusercontent.com/WirlyWirly/quiCKIE/main/quiCKIE.user.js?raw=true // // ==/UserScript== // Set to true to enable verbose console logging, useful during development or troubleshooting const verboseConsoleLogging = false // This string helps prevent various JavaScript oddities when working with variables 'use strict' // =================================== SETTINGS PANEL TRACKERS ====================================== // @quickieSettingsPanelTrackers const settingsPanelTrackers = [ // Keep this list alphabetical, as each tracker here will appear as a row in the quiCKIE settings panel // Each tracker requires 3 things; A TitleCase name, the homepage URL, and the primaryDomain of the tracker // Here are examples of identify the domain of a tracker... // https://broadcasthe.net/ --> broadcasthe // https://www.myanonamouse.net/ --> myanonamouse // https://sukebei.nyaa.si/ --> nyaa // βΉοΈ If the tracker has more than one domain that it can be accessed from (common for public trackers), you may also include the 'otherDomains' property, which should consist of an array (list) of different domains. This will make it so that these domains all share the same tracker settings from within the quiCKIE settings panel. // otherDomains: ['domain1', 'domain2', 'domain3'], { trackerName: 'Aither', // @holy-elbow homepageURL: 'https://aither.cc', primaryDomain: 'aither', }, { trackerName: 'AlphaRatio', homepageURL: 'https://alpharatio.cc', primaryDomain: 'alpharatio', }, { trackerName: 'AnimeBytes', homepageURL: 'https://animebytes.tv', primaryDomain: 'animebytes', }, { trackerName: 'AnimeZ', // @holy-elbow homepageURL: 'https://animez.to', primaryDomain: 'animez', }, { trackerName: 'Anthelion', // @malefis homepageURL: 'https://anthelion.me', primaryDomain: 'anthelion', }, { trackerName: 'AvistaZ', // @fercats99 homepageURL: 'https://avistaz.to', primaryDomain: 'avistaz', }, { trackerName: 'BakaBT', homepageURL: 'https://bakabt.me', primaryDomain: 'bakabt', }, { trackerName: 'Beyond-HD', // @empUser homepageURL: 'https://beyond-hd.me', primaryDomain: 'beyond-hd', }, { trackerName: 'Bibliotik', homepageURL: 'https://bibliotik.me', primaryDomain: 'bibliotik', }, { trackerName: 'BitPorn', homepageURL: 'https://bitporn.eu', primaryDomain: 'bitporn', }, { trackerName: 'BroadcasTheNet', homepageURL: 'https://broadcasthe.net', primaryDomain: 'broadcasthe', }, { trackerName: 'CinemaZ', // @fercats99 homepageURL: 'https://cinemaz.to', primaryDomain: 'cinemaz', }, { trackerName: 'ClearJAV', // @holy-elbow homepageURL: 'https://clearjav.com', primaryDomain: 'clearjav', }, { trackerName: 'DeepBassNine', // @tartuffe homepageURL: 'https://www.deepbassnine.com', primaryDomain: 'deepbassnine', }, { trackerName: 'DigitalCore', // @holy-elbow homepageURL: 'https://digitalcore.club/', primaryDomain: 'digitalcore', }, { trackerName: 'E-Hentai', // @holy-elbow homepageURL: 'https://e-hentai.org', primaryDomain: 'e-hentai', otherDomains: ['exhentai'], }, { trackerName: 'Empornium', homepageURL: 'https://emparadise.rs', primaryDomain: 'empornium', otherDomains: ['emparadise'] }, { trackerName: 'ExoticaZ', // @fercats99 > @holy-elbow homepageURL: 'https://exoticaz.to', primaryDomain: 'exoticaz', }, { trackerName: 'Femdomcult', // @holy-elbow homepageURL: 'https://femdomcult.org', primaryDomain: 'femdomcult', }, { trackerName: 'GazelleGames', homepageURL: 'https://gazellegames.net', primaryDomain: 'gazellegames', }, { trackerName: 'HappyFappy', // @empUser homepageURL: 'https://www.happyfappy.org', primaryDomain: 'happyfappy', }, { trackerName: 'HDBits', homepageURL: 'https://hdbits.org', primaryDomain: 'hdbits', }, { trackerName: 'IP-Torrents', homepageURL: 'https://iptorrents.me', primaryDomain: 'iptorrents', }, { trackerName: 'JPopsuki', // @tartuffe homepageURL: 'https://jpopsuki.eu', primaryDomain: 'jpopsuki', }, { trackerName: 'Karagarga', // @fercats99 homepageURL: 'https://karagarga.in', primaryDomain: 'karagarga', }, { trackerName: 'Kufirc', // @holy-elbow homepageURL: 'https://kufirc.com', primaryDomain: 'kufirc', }, { trackerName: 'Lat-Team', homepageURL: 'https://lat-team.com', primaryDomain: 'lat-team', }, { trackerName: 'LST', // @LilithOfTheValley homepageURL: 'https://lst.gg', primaryDomain: 'lst', }, { trackerName: 'Luminarr', // @holy-elbow homepageURL: 'https://lumniarr.me', primaryDomain: 'luminarr', }, { trackerName: 'Materialize', homepageURL: 'https://materialize.is', primaryDomain: 'materialize', }, { trackerName: 'MoreThanTV', // @holy-elbow homepageURL: 'https://www.morethantv.me', primaryDomain: 'morethantv', }, { trackerName: 'MyAnonaMouse', homepageURL: 'https://www.myanonamouse.net', primaryDomain: 'myanonamouse', }, { trackerName: 'Nebulance', // @malefis homepageURL: 'https://nebulance.io', primaryDomain: 'nebulance', }, { trackerName: 'Nyaa', homepageURL: 'https://nyaa.si', primaryDomain: 'nyaa', }, { trackerName: 'Oldtoons', homepageURL: 'https://oldtoons.world', primaryDomain: 'oldtoons', }, { trackerName: 'Orpheus', homepageURL: 'https://orpheus.network', primaryDomain: 'orpheus', }, { trackerName: 'PassThePopcorn', homepageURL: 'https://passthepopcorn.me', primaryDomain: 'passthepopcorn', }, { trackerName: 'Portugas', // @Phreaker homepageURL: 'https://portugas.org', primaryDomain: 'portugas', }, { trackerName: 'PrivateHD', // @holy-elbow homepageURL: 'https://privatehd.to', primaryDomain: 'privatehd', }, { trackerName: 'Redacted', homepageURL: 'https://redacted.sh', primaryDomain: 'redacted', }, { trackerName: 'RetroMoviesClub', // @LilithOfTheValley homepageURL: 'https://retro-movies.club', primaryDomain: 'retro-movies', }, { trackerName: 'Secret-Cinema', // @tartuffe homepageURL: 'https://secret-cinema.pw', primaryDomain: 'secret-cinema', }, { trackerName: 'TheGeeks', homepageURL: 'https://thegeeks.click', primaryDomain: 'thegeeks', }, { trackerName: 'TorrentLeech', // @holy-elbow homepageURL: 'https://www.torrentleech.org', primaryDomain: 'torrentleech', }, { trackerName: 'TV-Vault', homepageURL: 'https://tv-vault.me', primaryDomain: 'tv-vault', }, ] // =================================== quiCKIE SETTINGS ====================================== // The domain of the current site, which MUST be registerd to one of the trackers in the settingsPanelTrackers array // Example: https://broadcasthe.net/ --> broadcasthe let trackerDomain = document.location.hostname.match(/^(\w+\.)?(.+?)\..+$/)[2].toLowerCase() // A simple logger, which will only console log messages when it has been enabled above let logger = new simpleLogger({ enabled: verboseConsoleLogging, scriptName: 'quiCKIE'}) // Everything related to the GM_config library, which is used for saving and creating the settings panel: https://github.com/sizzlemctwizzle/GM_config let [ primaryDomain, allPrimaryDomains, allTrackerNames, primaryDomainToTrackerName, primaryDomainToHomepage, trackerNameToPrimaryDomain, presetCount ] = createGMConfigSettingsPanel(trackerDomain) // Retrieve the settings and presetMenuItems that are relevant to the current tracker let SETTINGS = getTrackerSettings(primaryDomain) let presetMenuItems = createPresetItems([SETTINGS.primaryDomain]) // All the emojis that may be displayed on bunnyButtons, defined as a RegExp so that they can be replaced during different stages of the script const emojiRegex = new RegExp('π°|π±|π|π’|π|πΈ|π€|π|π§²|π§|π|βοΈ|β|πΎ|π§', 'g') // The full URL and Path of the current page, useful for figuring out exactly what page you are on using pageURL.match(/regex/) const pageURL = document.URL const pagePath = document.location.pathname // =================================== TRACKER SPECIFIC HANDLING ====================================== // @trackerSpecificHandling // Because the primaryDomain is unique for each quiCKIE supported tracker, we can use it to determine what tracker this is and how to proceed from there if ( primaryDomain == 'animebytes' ) { // ----------------------------------- AnimeBytes ----------------------------------- // Bookmarks | Browse | Collages | Company | Seeding\Snatched\Leeching | Series let trackerHandlingOptions = { // ------------------------- REQUIRED ------------------------- // A valid CSS selector that is unique to ONLY the download elements (download buttons) on the page downloadElementsSelector: 'a[href^="/torrent/"][title="Download torrent"]', // --------------------------OPTIONAL ------------------------- // The following properties are all optional and can be applied on a per-tracker basis or when appropriate to do so depending on the page of the tracker // βΉοΈ Tip: To apply options on a per-page basis, use an 'if' statement to determine the current page based on the pageURL. From there, you can apply the options relevant to that page (See the BroadCasTheNet\Empornium\IP-Torrents\MyAnonaMouse\Nyaa blocks for examples) // - - - - - - - - - PRESENTATION - - - - - - - - - // Options to assist with the visual presentation\styling of bunnyButtons // The text that will be displayed by EVERY bunnyButton, useful for removing the surrounding whitespace included with the default setting, or when performing advanced styling bunnyButtonText: ' π° ', // Default = ' π° ' || Options = Any string // The font-size of EVERY bunnyButton, useful for re-sizing them to better fit the page bunnyButtonfontSize: 'inherit', // Default = 'inherit' || Options = Any percentile | A valid 'font-size' css value // Additional CSS style properties that will be applied to EVERY bunnyButton, useful for advanced styling (see the BakabT\HDBits\MyAnonaMouse\Nyaa blocks for examples) bunnyButtonAddStyles: '', // Default = '' || Options = A string containing css style properties // Additional class names that will be applied to EVERY bunnyButton, useful for advanced styling bunnyButtonAddClasses: [], // Default = [] || Options = An array of strings // If EVERY bunnyButton should be placed alongside its respective downloadElement.parentElement, which may result in the bunnyButton appearing on the same row as the downloadElement bunnyButtonParentPlacement: false, // Default = false || Options = true | false // If the downloadElement.parentElement should be hidden When 'π Hide Download Button' (settings panel) and the above 'bunnyButtonParentPlacement' option are both enabled. Some sites, but not all, will show a noticable gap when both those options are enabled, so this options exists to try preventing that gap. downloadElementHideParentElementGap: false, // Default = false || Options = true | false // The separator used between EVERY bunnyButton and the downloadElement elementsSeparator: 'automatic', // Default = 'automatic' || options = 'automatic' | Any string | false // A function that will be called after all the bunnyButtons have been created, useful for advanced styling when certain bunnyButtons on the page have individual styling needs (see the BakaBT\Empornium\MyAnonaMouse blocks for examples) // The provided 'elements' parameter will be an object consisting of three arrays: elements = { bunnyButtons: [], downloadElements: [], pairedElements:[] } // β οΈ quiCKIE is a NON-DESTRUCTIVE UserScript that does NOT break or destroy the default site elements. This ensures quiCKIE is friendly\compatible with other UserScripts. Always adhere to this principle by only manipulating the bunnyButtons created by quiCKIE itself afterBunnyButtonCreation: false, // Default = false || options = false | function(elements) {...} // - - - - - - - - - EMOJIOGRAPHY - - - - - - - - - // Options that allow you to add "Emojiography" support to a tracker by providing a string representing a JavaScript comparison. If that check completes successfully and is 'true', it indicates a torrent is seeding\snatched\freeleech and as a result will have its bunnyButton emoji updated to reflect this // The string may start with 'downloadElement' (representing a DL button) then be followed by a chain of '.closest()' and\or '.querySelector()' methods in order to locate a 'targetElement' (which refers to a element in the HTML indicating the torrent has a certain status). If the targetElement is found, the check is considered to be 'true' // See the AnimeBytes\BroadcasTheNet\Empornium\Orpheus\PassThePopcorn\Redacted blocks for examples // βΉοΈ Tip: If the targetElement has a unique .textContent but not attributes, one option is to perform a `targetElement.textContent.match(/regex/)`. If the regex match is found, the check is considered to be 'true' (see the MyAnonaMouse\Redacted block for examples) // βΉοΈ Tip: When inspecting the page from your browser, right-click the DL button HTML element and select the 'Use in Console' option. This will create a variable in your console that you can use to test your chaining. Once you have a working chain that to locate the target element, you can use it for these options. // A string representing a JavaScript comparison, that if 'true' indicates a torrent has the status of 'seeding', so the bunnyButton emoji will be changed to 'π±' seedingStatusSelector: null, // Default = null || Options = 'downloadElement...' // A string representing a JavaScript comparison, that if 'true' indicates a torrent has the status of 'snatched', so the bunnyButton emoji will be changed to 'π' snatchedStatusSelector: `downloadElement.closest('td').querySelector('a.snatched-torrent')`, // Default = null || Options = 'downloadElement...' // A string representing a JavaScript comparison, that if 'true' indicates a torrent has the status of 'freeleech', so the bunnyButton emoji will be changed to 'π' freeleechStatusSelector: `downloadElement.closest('td').querySelector('img[alt^="Freeleech"]')`, // Default = null || Options = 'downloadElement...' // A string representing a JavaScript comparison, that if 'true' indicates a torrent has the status of 'featured', so the bunnyButton emoji will be changed to 'π’' featuredStatusSelector: null, // Default = null || Options = 'downloadElement...' // - - - - - - - - - PAGINATION - - - - - - - - - // Options that can assist when the tracker has pagination, which is when the page does not perform a full refresh for new DL buttons, which results in those new DL buttons that are loaded into the page not having bunnyButtons //β οΈ You should not enable or use these options unless the tracker you are adding actually has pagination, in which case the URL's with pagination should be filtered through an if check so as to not apply these options to the entire site: pageURL.match(/pageURLRegex/) ? trackerHandlingOptions.enablePaginationLooping = true : null // If quiCKIE should repeatedly check for new download elements, which works as a simple approach for handling pagination enablePaginationLooping: false, // Default = false || Options = true | false // - - - - - - - - - OTHER - - - - - - - - - // Options to perform a vareity of tasks that may or may not apply to certain trackers // The element that will be used as the root when performing .querySelectorAll(downloadElementsSelector) to find all the downloadElements queryFromElement: document, // Default = document || Options = document | A specific element (node) // The name of the downloadElement attribute that contains the torrentURL downloadElementsTorrentURLAttribute: 'href', // Default = 'href' || Options = A string matching a attribute name of the download element // If quiCKIE should ALWAYS download the .torrent file through the browser before sending it to the torrent client, useful if the torrentURL authentication doesn't actually work // Magnet links are ALWAYS sent directly to the torrent client, as they are not proper http links that can be downloaded through the browser forceTorrentFile: false, // Default = false || Options = true | false // If quiCKIE should attach the right-click presetsMenu to the new bunnyButtons, useful for advanced presetsMenu manipulation bunnyButtonAttachPresetsMenu: true, // Default = true || Options = true | false } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'aither' ) { // ----------------------------------- Aither ----------------------------------- // Bookmarks | Browse | Details | Playlists unit3dTrackerHandler('a[href*="/download"]') } else if ( primaryDomain == 'alpharatio' ) { // ----------------------------------- AlphaRatio ----------------------------------- // Browse | Details | Top 10 let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'animez' ) { // --------------------------------- AnimeZ ------------------------------------ // Home | Browse| Bookmarks let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="https://animez.to/torrents/"][href$="/download"]', } if ( pageURL.match(/\/torrents\/\d+/) ) { trackerHandlingOptions.bunnyButtonText = 'π° quiCKIE' trackerHandlingOptions.bunnyButtonAddStyles = ` background: #4263eb; border-radius: 8px; border; 1px solid transparent; color: #f9fafb; box-shadow: 0 1px 1px rgba(229, 231, 235, .06); padding: 0.6875rem 1.5rem; font-size: 1rem; font-weight: 500; line-height: 1.5rem; ` } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'anthelion' ) { // ----------------------------------- Anthelion ----------------------------------- // Browse | Collages | Film let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'avistaz' ) { // ----------------------------------- AvistaZ ----------------------------------- // Details let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="https://avistaz.to/download/torrent/"]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'bakabt' ) { // ----------------------------------- BakaBT ----------------------------------- // Details let trackerHandlingOptions = { downloadElementsSelector: 'a.download_link[href^="/download/"]', bunnyButtonFontSize: '140%', bunnyButtonText: 'π° quiCKIE', freeleechStatusSelector: "document.querySelector('span.freeleech')", bunnyButtonAddStyles: ` background: #153245; border-radius: 4px; border: #B6D3E7 solid 2px; color: #B6D3E7; display: inline; font-weight: normal; margin: 0px 5px 0px 5px; padding: 3px 4px 4px 4px; vertical-align: super; `, afterBunnyButtonCreation: function(elements) { // The actions to take after the bunnyButtons have been created... // Decrease the width of the site DL button so that everything fits onto a single row elements.downloadElements[0].style.width = '395px' }, } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'beyond-hd' ) { // ----------------------------------- Beyond-HD ----------------------------------- // Browse | Details | Homepage | Library unit3dTrackerHandler('a[href^="https://beyond-hd.me/download/"]') } else if ( primaryDomain == 'bibliotik' ) { // ----------------------------------- Bibliotik ----------------------------------- // Browse | Details | Seeing\Snatched\Leeching\Uploads let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/torrents/"][title="Download"]', bunnyButtonFontSize: '120%', bunnyButtonAddStyles: 'vertical-align: bottom', // These status selectors are currently only working on the users seeding\snatched page seedingStatusSelector: `downloadElement.closest('tr').querySelector('a.seeders').nextSibling.baseURI.match(/seeding/)`, snatchedStatusSelector: `downloadElement.closest('tr').querySelector('a.snatches').nextSibling.baseURI.match(/snatches/)`, } // This is a details page, so apply styling to the only bunnyButton if ( pagePath.match(/\/torrents\/\d+/) ) { trackerHandlingOptions.bunnyButtonText = 'π° quiCKIE' trackerHandlingOptions.bunnyButtonAddStyles = ` background: #153245 !important; border-radius: 3px; border: #B6D3E7 solid 1px; color: #B6D3E7; font-size: 90%; margin: 0px 2px 0px 8px; padding: 2px 5px 2px 5px; vertical-align: center; ` } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'bitporn' ) { // ----------------------------------- BitPorn ----------------------------------- // Browse | Details unit3dTrackerHandler('a[href^="https://bitporn.eu/torrents/download/"]') } else if ( primaryDomain == 'broadcasthe' ) { // ----------------------------------- BroadcasTheNet ----------------------------------- // Browse | Series | Season\Episodes let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', seedingStatusSelector: "downloadElement.closest('td').querySelector('a.tor_highlight_seed')", snatchedStatusSelector: "downloadElement.closest('td').querySelector('a.tor_highlight_snatch')", } // This is a browse page (not Season\Episode), so apply styling to all bunnyButtons if ( pageURL.match(/torrents\.php(?!\?id=\d+)/) ) { trackerHandlingOptions.afterBunnyButtonCreation = function(elements) { // The actions to take after the bunnyButtons have been created... // Style all bunnyButtons, giving them a square-type look to more closely match the site buttons for ( let bunnyButton of elements.bunnyButtons ) { bunnyButton.textContent = 'π°' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText} background: #153245; border-radius: 3px; border: #B6D3E7 solid 1px; color: #B6D3E7; font-size: 80%; padding: 2px 2px 2px 2px; vertical-align: unset;`) } } } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'cinemaz' ) { // ----------------------------------- CinemaZ ----------------------------------- // Details let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="https://cinemaz.to/download/torrent/"]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'clearjav' ) { // ----------------------------------- ClearJAV ----------------------------------- // Bookmarks | Browse | Details | Movies| Playlists unit3dTrackerHandler('a[href^="https://clearjav.com/torrents/download/"]') } else if ( primaryDomain == 'deepbassnine' ) { // ----------------------------------- DeepBassNine ----------------------------------- // Album | Artist | Browse let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'digitalcore' ) { // ---------------------------------- DigitalCore --------------------------------- // Browse | Details | Home if ( pageURL.match(/\/torrent\/\d+/) ) { // The torrent details page let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/api/v1/torrents/download"]:has(i.fa-download)', bunnyButtonText: 'π° quiCKIE', bunnyButtonAddStyles: ` background: #252525; border-radius: 3px; border: #323232 solid 1px; color: #ccc; font-size: 12px; margin-left: 11.033px; padding: 1px 39.817px; vertical-align: middle; ` } let observer = new MutationObserver(function(mutations) { quickieTrackerHandler(trackerHandlingOptions) }) let target = document.getElementById('contentContainer') let config = { childList: true } observer.observe(target, config) } else if ( pagePath.match(/^\/?$/) ) { // The homepage let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/api/v1/torrents/download"]', enablePaginationLooping: true, } quickieTrackerHandler(trackerHandlingOptions) } else { // The browse page let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/api/v1/torrents/download"]', } let pageObserver = new MutationObserver(async function(pageMutations) { // Wait until the
of is loaded... let tbodyElement = await waitForElement('torrents-table[torrents] tbody', document.getElementById('contentContainer')) try { let torrentObserver = new MutationObserver(function(torrentMutations) { // The actions to take when there are changes to the quickieTrackerHandler(trackerHandlingOptions) }) torrentObserver.observe(tbodyElement, { childList: true }) } catch(error) { return } }) let target = document.getElementById('contentContainer') let config = { childList: true } pageObserver.observe(target, config) } } else if ( primaryDomain == 'e-hentai' ) { // ----------------------------------- E-Hentai ----------------------------------- // Torrents let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="https://ehtracker.org/get/"]', } if ( pageURL.match(/exhentai/) ) { trackerHandlingOptions.downloadElementsSelector = 'a[href^="https://exhentai.org/torrent/"]' } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'empornium' ) { // ----------------------------------- Empornium ----------------------------------- // Browse | Collages | Details | Top10 | UserProfile let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/torrents.php?action=download&id="]', bunnyButtonFontSize: '130%', seedingStatusSelector: "downloadElement.parentElement.querySelector('i.torrent_icons.seeding')", snatchedStatusSelector: "downloadElement.parentElement.querySelector('i.torrent_icons.snatched')", freeleechStatusSelector: "downloadElement.closest('span.torrent_icon_container').querySelector('i.font_icon.unlimited_leech')" } // This is a collage page, so place the bunnyButton alongside the parentElement if ( pageURL.match(/\/collage\/\d+/) ) { trackerHandlingOptions.bunnyButtonParentPlacement = true trackerHandlingOptions.downloadElementHideParentElementGap = true } // This is a details page, so apply styling to certain bunnyButtons if ( pageURL.match(/torrents\.php\?id=\d+/) ) { trackerHandlingOptions.afterBunnyButtonCreation = function(elements) { // The actions to take after the bunnyButtons have been created... // The main downloadElement, which will be referenced to determine the current torrentStatus let mainDownloadElement = document.querySelector(`#user-sidebar ${trackerHandlingOptions.downloadElementsSelector}`) for ( let bunnyButton of elements.bunnyButtons ) { // Style the bunnyButtons that match this CSS selector, giving them a bar-type look to more closely match the larger site buttons if ( bunnyButton.matches('span.torrent_buttons a.quickie_bunnyButton, #user-sidebar > a.quickie_bunnyButton') ) { bunnyButton.setAttribute('style', `${bunnyButton.style.cssText} border-radius: 5px; font-size: 100%; font-weight: Bold; margin: 0px 8px 0px 0px; padding: 4px 10px 4px 10px; vertical-align: middle;`) if ( bunnyButton.dataset.torrenturl.match(/&usetoken=1/) ) { // This is a Freeleech button bunnyButton.textContent = 'πΈ Freeleech' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText}border: #A0DA83 solid 1px; color: #A0DA83; background: #113400;`) bunnyButton.setAttribute('data-emojospecified', 'true') } else if ( bunnyButton.dataset.torrenturl.match(/&usetoken=2/) ) { // This is a Doubleseed button bunnyButton.textContent = 'π± Doubleseed' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText}border: #F09D63 solid 1px; color: #F09D63; background: #431C00`) bunnyButton.setAttribute('data-emojospecified', 'true') } else { // This is a standard Download button bunnyButton.textContent = 'π° quiCKIE' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText}border: #B6D3E7 solid 1px; color: #B6D3E7; background: #153245;`) // Check for torrentStatus relative to the mainDownloadElement mainDownloadElement.closest('.torrent_icon_container').querySelector('i.font_icon.unlimited_leech') != null ? bunnyButtonTorrentStatus(bunnyButton, 'freeleech') : null // Freeleech mainDownloadElement.querySelector('i.torrent_icons.snatched') != null ? bunnyButtonTorrentStatus(bunnyButton, 'snatched') : null // Snatched mainDownloadElement.querySelector('i.torrent_icons.seeding') != null ? bunnyButtonTorrentStatus(bunnyButton, 'seeding') : null // Seeding } } } } } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'exoticaz' ) { // ----------------------------------- ExoticaZ ----------------------------------- // Details let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="https://exoticaz.to/download/torrent/"]', } if ( pageURL.match(/\/torrent\/\d+/) ) { // This is a details page, so apply styling to the only bunnyButton trackerHandlingOptions.bunnyButtonText = 'π° quiCKIE' trackerHandlingOptions.bunnyButtonAddStyles = ` background: #e94a93; border-radius: 0; border: #e8e6e3 solid 1px; border: 1px solid transparent; color: #e8e6e3; display: inline-block; font-family: 'Roboto'; font-size: .8203125rem; font-weight: 400 line-height: 1; margin-left: 5px; margin-right: 1px; margin-top: 3px; padding: .2rem .7rem; ` } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'femdomcult' ) { // ----------------------------------- Femdomcult ----------------------------------- // Bookmarks | Browse | Collages | Details | let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/torrents.php?action=download&id="]', bunnyButtonFontSize: '125%', bunnyButtonParentPlacement: true, } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'gazellegames' ) { // ----------------------------------- GazelleGames ----------------------------------- // Browse | Bundles | Game let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', seedingStatusSelector: "downloadElement.closest('td').querySelector('#color_seeding')", snatchedStatusSelector: "downloadElement.closest('td').querySelector('#color_snatched')", freeleechStatusSelector: "downloadElement.closest('td').querySelector('.freeleech_label, .personal_freeleech_label')", } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'happyfappy' ) { // ----------------------------------- HappyFappy ----------------------------------- // Browse | Collages | Details | Top10 let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/torrents.php?action=download&id="]', bunnyButtonFontSize: '125%', bunnyButtonText: 'π°', seedingStatusSelector: `downloadElement.querySelector('span.icon_disk_seed')`, snatchedStatusSelector: `downloadElement.querySelector('span.icon_disk_snatched')`, freeleechStatusSelector: `downloadElement.parentElement.querySelector('img[alt="Freeleech"]')`, } // This is a details page, so apply styling to certain bunnyButtons if ( pageURL.match(/torrents\.php\?id=\d+/) ) { trackerHandlingOptions.afterBunnyButtonCreation = function(elements) { // The actions to take after the bunnyButtons have been created... // The main downloadElement, which will be referenced to determine the current torrentStatus let mainDownloadElement = document.querySelector(`#user-sidebar ${trackerHandlingOptions.downloadElementsSelector}`) for ( let bunnyButton of elements.bunnyButtons ) { // Style the bunnyButtons that match this CSS selector, giving them a bar-type look to more closely match the larger site buttons if ( bunnyButton.matches('span.torrent_buttons a.quickie_bunnyButton, #user-sidebar > a.quickie_bunnyButton') ) { bunnyButton.setAttribute('style', `${bunnyButton.style.cssText} border-radius: 5px; font-size: 125%; font-weight: Bold; margin: 0px 8px 0px 0px; padding: 4px 10px 4px 10px; vertical-align: auto;`) if ( bunnyButton.dataset.torrenturl.match(/&usetoken=1/) ) { // This is a Freeleech button bunnyButton.textContent = 'πΈ Freeleech' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText}border: #A0DA83 solid 1px; color: #A0DA83; background: #113400;`) bunnyButton.setAttribute('data-emojospecified', 'true') } else if ( bunnyButton.dataset.torrenturl.match(/&usetoken=2/) ) { // This is a Doubleseed button bunnyButton.textContent = 'π± Doubleseed' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText}border: #F09D63 solid 1px; color: #F09D63; background: #431C00`) bunnyButton.setAttribute('data-emojospecified', 'true') } else { // This is a standard Download button bunnyButton.textContent = 'π° quiCKIE' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText}border: #B6D3E7 solid 1px; color: #B6D3E7; background: #153245;`) // Check for torrentStatus relative to the mainDownloadElement mainDownloadElement.parentElement.querySelector('img[alt="Freeleech"]') != null ? bunnyButtonTorrentStatus(bunnyButton, 'freeleech') : null // Freeleech mainDownloadElement.querySelector('span.icon_disk_snatched') != null ? bunnyButtonTorrentStatus(bunnyButton, 'snatched') : null // Snatched mainDownloadElement.querySelector('span.icon_disk_seed') != null ? bunnyButtonTorrentStatus(bunnyButton, 'seeding') : null // Seeding } } } } } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'hdbits' ) { // ----------------------------------- HDBits ----------------------------------- // Browse | Details | Film let trackerHandlingOptions = { downloadElementsSelector: 'a.js-download[href^="/download.php/"]', bunnyButtonFontSize: '140%', bunnyButtonText: 'π°', featuredStatusSelector: `downloadElement.closest('tr').className.match(/featured/i)`, freeleechStatusSelector: "downloadElement.closest('td').querySelector('a.fl')", } // This is a details page, so apply styling to the only bunnyButton if ( pageURL.match(/details\.php\?id=\d+/) ) { trackerHandlingOptions.seedingStatusSelector = "downloadElement.closest('td').querySelector('span.tag_seeding')" trackerHandlingOptions.snatchedStatusSelector = "downloadElement.closest('td').querySelector('span.tag_completed')" trackerHandlingOptions.freeleechStatusSelector = "downloadElement.closest('td').querySelector('span.tag.freeleech')" trackerHandlingOptions.bunnyButtonText = 'π° quiCKIE' trackerHandlingOptions.bunnyButtonAddStyles = ` background: #153245; border-radius: 3px; border: #B6D3E7 solid 1px; color: #B6D3E7; font-size: 90%; margin: 0px 2px 0px 8px; padding: 2px 5px 2px 5px; vertical-align: unset; ` } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'iptorrents' ) { // ----------------------------------- IP-Torrents ----------------------------------- // Browse | Details let trackerHandlingOptions = { downloadElementsSelector: 'a[href*="download.php"]', bunnyButtonFontSize: '160%', bunnyButtonText: 'π°', } if ( pageURL.match(/(torrent|details)\.php\?id=\d+/) ) { // This is a details page, so apply styling to certain bunnyButtons trackerHandlingOptions.afterBunnyButtonCreation = function(elements) { // The actions to take after the bunnyButtons have been created... let firstBunnyButton = true for ( bunnyButton of elements.bunnyButtons ) { // The first bunnyButton, so apply special styling if ( firstBunnyButton == true ) { bunnyButton.setAttribute('style', `${bunnyButton.style.cssText} background: #153245; border-radius: 999px; border: #B6D3E7 solid 1px; font-size: 500%; margin: 5px 5px 5px 5px; padding: 20px; vertical-align: middle;`) // Check if this torrent is freeleech bunnyButton.closest('div.info').querySelector('span.free') ? bunnyButtonTorrentStatus(bunnyButton, 'freeleech') : null firstBunnyButton = false continue } // Check is this torrent is freeleech bunnyButton.closest('tr').querySelector('span.free') ? bunnyButtonTorrentStatus(bunnyButton, 'freeleech') : null } } } else { // This is NOT a details page, so do a regular torrentStatus check trackerHandlingOptions.freeleechStatusSelector = `downloadElement.closest('tr').querySelector('span.free')` } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'jpopsuki' ) { // ----------------------------------- JpopSuki ----------------------------------- // Album | Artist | Browse let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'karagarga' ) { // ----------------------------------- Karagarga ----------------------------------- // Browse | Details let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/down.php/"]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'kufirc' ) { // ----------------------------------- Kufirc ----------------------------------- // Browse | Collages | Details | Top10 let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', bunnyButtonFontSize: "140%", } pageURL.match(/top10/) ? trackerHandlingOptions.enablePaginationLooping = true : null quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'lat-team' ) { // ----------------------------------- Lat-Team ----------------------------------- // Bookmarks | Browse | Details | Homepage | Playlists unit3dTrackerHandler('a[href^="https://lat-team.com/torrents/download"]') } else if ( primaryDomain == 'lst' ) { // ----------------------------------- LST ----------------------------------- // Bookmarks | Browse | Details | Homepage | Playlists | MediaHub unit3dTrackerHandler('a[href^="https://lst.gg/torrents/download"]') } else if ( primaryDomain == 'luminarr' ) { // ----------------------------------- Luminarr ----------------------------------- // Bookmarks | Browse | Details | Playlists unit3dTrackerHandler('a[href^="https://luminarr.me/torrents/download"]') } else if ( primaryDomain == 'materialize' ) { // ----------------------------------- Materialize ----------------------------------- // Browse | Collages | Details | Top10 let trackerHandlingOptions = { downloadElementsSelector: 'a[href*="torrents.php?action=download&id="]', forceTorrentFile: true, } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'morethantv' ) { // ----------------------------------- MoreThanTV ----------------------------------- // Browse | Collages | Details | Top10 let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/torrents.php?action=download&id="]', elementsSeparator: '||', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'myanonamouse' ) { // ----------------------------------- MyAnonaMouse ----------------------------------- // Browse | Details | Homepage | Top10 if ( pageURL.match(/\/t\/\d+/) ) { // The book details page, which doesn't require a MutationObserver let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/tor/download.php/"][title*="Download"]', seedingStatusSelector: "document.getElementById('DLhistory').textContent.match(/seeding/i)", snatchedStatusSelector: "document.getElementById('DLhistory').textContent.match(/seeder/i)", freeleechStatusSelector: "document.getElementById('ratio').textContent.match(/freeleech/i)", bunnyButtonFontSize: '125%', bunnyButtonText: 'π° quiCKIE', bunnyButtonAddStyles: ` background: #153245; border-radius: 8px; border: #B6D3E7 solid 1px; color: #B6D3E7; font-weight: Bold; margin: 0px 10px 0px 10px; padding: 3px 10px 5px 10px; vertical-align: middle; `, afterBunnyButtonCreation: function(elements) { // The actions to take after the bunnyButtons have been created... for ( let bunnyButton of elements.bunnyButtons ) { // If DL buttons are hidden, change bunnyButton display to block so the buttons are properly spaced apart SETTINGS.hideDL == true ? bunnyButton.style.display = 'block' : null // This is the Freeleech Wedge button, so apply different text\styles if ( bunnyButton.dataset.torrenturl.match(/tid=\d+&fl/) ) { bunnyButton.textContent = 'π§ Freeleech' bunnyButton.setAttribute('style', `${bunnyButton.style.cssText}background: #2E2400; border: #CBC29E solid 1px; color: #CBC29E;`) } } }, } quickieTrackerHandler(trackerHandlingOptions) } else { // The Search or Homepage, both of which require a MutationObserver let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/tor/download.php/"][title*="Download"]', bunnyButtonFontSize: '150%', bunnyButtonText: 'π°', seedingStatusSelector: "downloadElement.closest('tr').querySelector('div.browseAct').textContent.match(/Recently Seeding/i)", snatchedStatusSelector: "downloadElement.closest('tr').querySelector('div.browseInact')", freeleechStatusSelector: `downloadElement.closest('tr').querySelector('a[href$="&fl"][title*="Download"]') == null`, // There is no FL Wedge button, so this torrent must already be FL afterBunnyButtonCreation: function(elements) { // The actions to take after the bunnyButtons have been created... // Site download buttons are hidden, so change the Freelech Wedge button to cheese now that it won't conflict with the sites wedge button if ( SETTINGS.hideDL ) { for ( let bunnyButton of elements.bunnyButtons ) { bunnyButton.dataset.torrenturl.match(/tid=\d+&fl/) ? replaceEmojis(bunnyButton, 'π§') : null } } }, } let observer = new MutationObserver( function(mutations) { // Functionality to run when changes are detected to the target element quickieTrackerHandler(trackerHandlingOptions) }) let target = document.getElementById('ssr') // Search table pageURL.match(/\/top10Tor\.php/) ? target = document.getElementById('top10') : null // Top 10 let config = { childList: true } observer.observe(target, config) } } else if ( primaryDomain == 'nebulance' ) { // ----------------------------------- Nebulance ----------------------------------- // Bookmarks | Browse | Top 10 let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', bunnyButtonFontSize: '115%', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'nyaa' ) { // ----------------------------------- Nyaa ----------------------------------- // Browse | Details let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="/download/"][href$=".torrent"]', } // The Details page, so apply styling to the single bunnyButton if ( pageURL.match(/view\/\d+/) ) { trackerHandlingOptions.bunnyButtonText = 'π° quiCKIE' trackerHandlingOptions.bunnyButtonAddStyles = ` background: #153245; border-radius: 3px; border: #B6D3E7 solid 1px; color: #B6D3E7; font-size: 90%; margin: 0px 2px 0px 8px; padding: 2px 5px 2px 5px; vertical-align: top; ` } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'oldtoons' ) { // ----------------------------------- OldToons ----------------------------------- // Browse | Details | Homepage | Playlists | Similar unit3dTrackerHandler('a[href^="https://oldtoons.world/torrents/download/"]') } else if ( primaryDomain == 'orpheus' ) { // ----------------------------------- Orpheus ----------------------------------- // Album | Artist | Browse | Collages let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', seedingStatusSelector: "downloadElement.closest('td').querySelector('strong.tl_seeding')", snatchedStatusSelector: "downloadElement.closest('td').querySelector('strong.tl_snatched')", freeleechStatusSelector: "downloadElement.closest('td').querySelector('strong.tl_free')" } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'passthepopcorn' ) { // ----------------------------------- PassThepopcorn ----------------------------------- // Film let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', seedingStatusSelector: `downloadElement.closest('td').querySelector('a.torrent-info-link[title="Seeding"]')`, snatchedStatusSelector: `downloadElement.closest('td').querySelector('a.torrent-info-link[title="Downloaded"]')`, freeleechStatusSelector: `downloadElement.closest('td').querySelector('a.torrent-info-link .torrent-info__download-modifier--free')` } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'portugas' ) { // ----------------------------------- Portugas ----------------------------------- // Browse | Album | Artist unit3dTrackerHandler('a[href^="https://portugas.org/torrents/download/"]') } else if ( primaryDomain == 'privatehd' ) { // ----------------------------------- PrivateHD ----------------------------------- // Details let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="https://privatehd.to/download/torrent/"]', } quickieTrackerHandler(trackerHandlingOptions) } else if ( primaryDomain == 'redacted' ) { // ----------------------------------- Redacted ----------------------------------- // Album | Artist | Bookmarks | Browse | Collages | Top10 let trackerHandlingOptions = { downloadElementsSelector: 'a[href^="torrents.php?action=download&id="]', seedingStatusSelector: "downloadElement.closest('tr').querySelector('.tl_notice').textContent.match(/seeding/i)", snatchedStatusSelector: "downloadElement.closest('tr').querySelector('.tl_snatched')", freeleechStatusSelector: "downloadElement.closest('tr').querySelector('.tl_free')" } if ( !pageURL.match(/collages?\.php\?id=\d+/) ) { // This is NOT a collage page, so it doesn't require a MutationObserver quickieTrackerHandler(trackerHandlingOptions) } else { // This is a collage page, which loads DL buttons after the '+' button of the album is clicked (pagination). Setup nested observation. trackerHandlingOptions.downloadElementsSelector = `#discog_table tbody ${trackerHandlingOptions.downloadElementsSelector}` let pageObserver = new MutationObserver( async function(pageMutations) { // The actions to take when new PAGES are loaded // DL elements are already present, meaning the user has the account setting 'Torrent group display' toggled to 'Open' document.querySelector(trackerHandlingOptions.downloadElementsSelector) ? quickieTrackerHandler(trackerHandlingOptions) : null try { // Wait until the of a new page is loaded... var tbodyElement = await waitForElement('#discog_table tbody', document.getElementById('discog_table')) } catch (error) { // There was an error, likely this mutation did not contain the waitForElement query target logger.debug(error) return } try { let tbodyObserver = new MutationObserver( function() { // The actions to take when the '+' button of a