diff --git a/.gitignore b/.gitignore index ba35e2a..2dde1f5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ config.ini screenshots downloaded_files __pycache__ +secrets.ini diff --git a/README.md b/README.md index dc2457e..c2dd030 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Automatically create screenshots of your stats and save it as PNG, as who got th ## Supported Trackers: - Aither (ATH) + - Anthelion (ANT) - Bluetopia (BLU) - Reelflix (RF) - Speedapp (SP) @@ -32,7 +33,9 @@ Automatically create screenshots of your stats and save it as PNG, as who got th - PassThePopcorn (PTP) - BeyondHD (BHD) - Oldtoons (OTW) - + - TV-Vault (TVV) + - DEEPBASSNiNE (DB9) + - PixelCove (PxC) It's easy to add new trackers. You can request it here or add it yourself. diff --git a/config.ini.example b/config.ini.example index 90b9734..e7e1582 100644 --- a/config.ini.example +++ b/config.ini.example @@ -1,5 +1,3 @@ -#This config file holds all of your data. - [settings] # Browser to use for screenshots. Options are: chrome, firefox, edge, safari, brave, opera # If using brave or opera, you need to specify the binary location. @@ -7,16 +5,18 @@ browser = chrome binary_location = C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe # Set to true if you want to take full page screenshots. Set to false if you want to take only the visible part of the page. full_page_screenshot = false +# Set to true if you want to store the 2FA secrets and use them for auto-filling 2FA codes. +auto_2fa = false -#List of supported trackers. Remove the trackers that you don't want to screenshot. Only keep what you want. +# List of supported trackers. Remove the trackers that you don't want to screenshot. Only keep what you want. [wanted-trackers] -trackers = ["AB", "ANT", "ATH", "BHD", "BLU", "BTN", "CRT", "FL", "GGN", "GPW", - "HDT", "HUNO", "JME", "LST", "MAM", "MTV", "NBL", "OPS", "OTW", "PTP", - "RED", "RF", "SP", "STC", "STT", "SZN", "TDC", "TL"] +trackers = ["aither", "animetorrents", "animebytes", "anthelion", "beyond-hd", "blutopia", "broadcasthenet", "cathode-raytube", "deepbassnine", "filelist", "gazellegames", "greatposterwall", "hdtorrents", + "huno", "jme", "lst", "morethantv", "myanonamouse", "nebulance", "oldtoons", "orpheus", "passthepopcorn", "pixelcove", "redacted", "reelflix", "skipthecommercials", + "skipthetrailers", "speedapp", "swarmazon", "thedarkcommunity", "torrentleech", "tv-vault"] -#Referance: ["AB", "ANT", "ATH", "BHD", "BLU", "BTN", "CRT", "FL", "GGN", "GPW", -# "HDT", "HUNO", "JME", "LST", "MAM", "MTV", "NBL", "OPS", "OTW", "PTP", -# "RED", "RF", "SP", "STC", "STT", "SZN", "TDC", "TL"] +# Reference: ["aither", "animetorrents", "animebytes", "anthelion", "beyond-hd", "blutopia", "broadcasthenet", "cathode-raytube", "deepbassnine", "filelist", "gazellegames", "greatposterwall", "hdtorrents", + "huno", "jme", "lst", "morethantv", "myanonamouse", "nebulance", "oldtoons", "orpheus", "passthepopcorn", "pixelcove", "redacted", "reelflix", "skipthecommercials", + "skipthetrailers", "speedapp", "swarmazon", "thedarkcommunity", "torrentleech", "tv-vault"] #Edit the trackers you want to use with your details. [aither] @@ -47,7 +47,7 @@ profile_url = https://hawke.uno/users/XXX [speedapp] username = YOUR USERNAME password = YOUR PASSWORD -#Do Not Change the URL +# DO NOT CHANGE profile_url = https://speedapp.io/profile/ [filelist] @@ -66,6 +66,8 @@ profile_url = https://greatposterwall.com/user.php?id=XXX username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://animetorrents.me/user-profile.php?uid=XXX +# DO NOT CHANGE +login_url = https://animetorrents.me/login.php [redacted] username = YOUR USERNAME @@ -86,11 +88,14 @@ profile_url = https://skipthetrailers.xyz/users/XXX username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://animebytes.tv/user.php?id=XXX +login_url = https://animebytes.tv/user.php [jme] username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://jme-reunit3d.de/users/XXX +# DO NOT CHANGE +login_url = https://jme-reunit3d.de/login [thedarkcommunity] username = YOUR USERNAME @@ -101,6 +106,8 @@ profile_url = https://thedarkcommunity.cc/users/XXX username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://www.cathode-ray.tube/user.php?id=XXX +# DO NOT CHANGE +login_url = https://www.cathode-ray.tube/login [myanonamouse] username = YOUR EMAIL @@ -117,17 +124,19 @@ username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://www.torrentleech.org/profile/XXX/ -#ORPHEUS DOES NOT WORK WITH 2FA [orpheus] username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://orpheus.network/user.php?id=XXXX +# DO NOT CHANGE +login_url = https://orpheus.network/login.php [swarmazon] username = YOUR USERNAME password = YOUR PASSWORD -#Do not change the URL +# DO NOT CHANGE URLS profile_url = https://swarmazon.club/en/view/my-statistics.php +login_url = https://swarmazon.club/en/account/login.php [morethantv] username = YOUR USERNAME @@ -138,6 +147,8 @@ profile_url = https://www.morethantv.me/user.php?id=XXX username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://hd-torrents.org/usercp.php?uid=XXX +# DO NOT CHANGE +login_url = https://hd-torrents.org [broadcasthenet] username = YOUR USERNAME @@ -164,5 +175,25 @@ username = YOUR USERNAME password = YOUR PASSWORD profile_url = https://oldtoons.world/users/XXX +[anthelion] +username = YOUR USERNAME +password = YOUR PASSWORD +profile_url = https://redacted.sh/user.php?id=XXX + +[tv-vault] +username = YOUR USERNAME +password = YOUR PASSWORD +profile_url = https://tv-vault.me/user.php?id=XXX + +[deepbassnine] +username = YOUR USERNAME +password = YOUR PASSWORD +profile_url = https://deepbassnine.com/user.php?id=XXX + +[pixelcove] +username = YOUR USERNAME +password = YOUR PASSWORD +profile_url = https://www.pixelcove.me/user.php?id=XXX + #GitHub: https://github.com/KlevGG/TrackerScreenshot diff --git a/requirements.txt b/requirements.txt index 36cae0c..839d033 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,6 @@ seleniumbase==4.27.4 Selenium-Screenshot==2.1.0 -black==24.4.2 \ No newline at end of file +black==24.4.2 +argon2-cffi==23.1.0 +cryptography==43.0.1 +pyotp==2.9.0 \ No newline at end of file diff --git a/screenshots.py b/screenshots.py index c81ac0b..e86c1c8 100644 --- a/screenshots.py +++ b/screenshots.py @@ -1,14 +1,75 @@ # Required Libraries - You can change the browser driver if you would like to. More details on GitHub. -from seleniumbase import Driver, SB # type: ignore -from selenium.webdriver.common.by import By -from Screenshot import Screenshot # type: ignore -import datetime import configparser +import json +import os +from getpass import getpass + +from argon2 import PasswordHasher +from seleniumbase import Driver + +from utils import encrypt_secrets, get_decrypted_secrets # type: ignore # Read config file config = configparser.ConfigParser(interpolation=None) config.read("config.ini") +trackers_list = json.loads(config["wanted-trackers"]["trackers"]) + +if "auto_2fa" in config["settings"] and config["settings"]["auto_2fa"] == "true": + ph = PasswordHasher() + # Check if master password is stored in config file + if "master_password" not in config["settings"]: + # Prompt the user to enter the master password + print("Master password not found in config file, please enter it.") + master_password = getpass("") + # Hash the master password + master_password_hash = ph.hash(master_password) + salt = os.urandom(16) + # Store the master password hash in the config file + config["settings"]["master_password"] = master_password_hash + config["settings"]["salt"] = salt.hex() + with open("config.ini", "w") as configfile: + config.write(configfile) + + twofa_trackers = [ + "aither", + "anthelion", + "blutopia", + "huno", + "redacted", + "broadcasthenet", + "gazellegames", + "passthepopcorn", + "pixelcove", + "beyond-hd", + "oldtoons", + "cathode-raytube", + "morethantv", + "orpheus", + "torrentleech", + ] + + # Decrypt the secrets + decrypted_secrets = get_decrypted_secrets() + + # Prompt for any missing 2FA secrets, as long as the tracker is also in trackers_list + for tracker in twofa_trackers: + if tracker not in decrypted_secrets and tracker in trackers_list: + decrypted_secrets[tracker] = input( + f"Please enter the 2FA secret for {tracker}: " + ) + + # Write the secrets to the secrets file + secrets_config = configparser.ConfigParser() + secrets_config.read("secrets.ini") + + # Encrypt the secrets and write them to the secrets file + encrypted_secrets = encrypt_secrets(decrypted_secrets) + secrets_config["secrets"] = encrypted_secrets + with open("secrets.ini", "w") as secretsfile: + secrets_config.write(secretsfile) + + if "browser" not in config["settings"]: config["settings"]["browser"] = "chrome" browser = config["settings"]["browser"] @@ -31,819 +92,22 @@ driver = Driver(uc=True, browser=browser) driver.implicitly_wait(6) -ob = Screenshot.Screenshot() - - -def hide_notification(driver=driver): +# For each tracker in the config file, run the tracker class +for tracker in trackers_list: try: - driver.execute_script( - "document.querySelector('#noty_bottomRight_layout_container').style.display = 'none';" - ) - except: # noqa: E722 - pass - - -def take_screenshot(tracker_name, driver=driver, is_load_at_runtime=False): - hide_notification(driver) - - date_string = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S") - image_name = tracker_name + "_" + date_string + ".png" - - if config["settings"].get("full_page_screenshot", "false") == "true": - ob.full_screenshot( - driver, - save_path="screenshots", - image_name=image_name, - is_load_at_runtime=is_load_at_runtime, - ) - else: - driver.save_screenshot("screenshots/" + image_name) - - -if "ATH" in config["wanted-trackers"]["trackers"]: - print("Entering Aither.") - # Get the details from the config file - username = config["aither"]["username"] - password = config["aither"]["password"] - profile_url = config["aither"]["profile_url"] - - driver.get(profile_url) - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.CLASS_NAME, "auth-form__primary-button").click() - take_screenshot("Aither") - print("Aither Screenshoted") - - -if "RF" in config["wanted-trackers"]["trackers"]: - print("Entering Reelflix.") - # Get the details from the config file - username = config["reelflix"]["username"] - password = config["reelflix"]["password"] - profile_url = config["reelflix"]["profile_url"] - - driver.get(profile_url) - - # Navigation - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.ID, "login-button").click() - take_screenshot("RF") - print("Reelflix Screenshoted") - - -if "LST" in config["wanted-trackers"]["trackers"]: - print("Entering LST.") - username = config["lst"]["username"] - password = config["lst"]["password"] - profile_url = config["lst"]["profile_url"] - - driver.get(profile_url) - - # Navigation - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.ID, "login-button").click() - take_screenshot("LST") - print("LST Screenshoted") - -if "BLU" in config["wanted-trackers"]["trackers"]: - print("Entering BLU.") - username = config["blutopia"]["username"] - password = config["blutopia"]["password"] - profile_url = config["blutopia"]["profile_url"] - - driver.get(profile_url) - - # Navigation - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.CLASS_NAME, "auth-form__primary-button").click() - - # 2FA is enabled, ask for the code - if driver.find_elements(By.ID, "code"): - code = input("Please enter the 2FA code: ") - code_field = driver.find_element(By.ID, "code") - code_field.send_keys(code) - - take_screenshot("BLU") - print("Blu Screenshoted") - -if "HUNO" in config["wanted-trackers"]["trackers"]: - print("Entering HUNO.") - username = config["huno"]["username"] - password = config["huno"]["password"] - profile_url = config["huno"]["profile_url"] - skip = False - - driver.get(profile_url) - - if driver.find_elements(By.ID, "challenge-running"): - print( - "Please solve the challenge and press enter to continue or type 'n' and press enter to skip." + tracker_class_name = "trackers." + tracker.lower() + tracker_class = getattr( + __import__(tracker_class_name, fromlist=[tracker]), + tracker.capitalize().replace("-", "") + "Tracker", ) - response = input() - if response == "n": - skip = True - - if not skip: - # Navigation - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.ID, "login-button").click() - - # 2FA is enabled, ask for the code - if driver.find_elements(By.ID, "v_input"): - code = input("Please enter the 2FA code: ") - code_field = driver.find_element(By.ID, "v_input") - code_field.send_keys(code) - driver.find_element(By.ID, "submit_verification").click() - - # is_load_at_runtime is set to ensure the full page screenshot is taken correctly - if config["settings"].get("full_page_screenshot", "false") == "true": - take_screenshot("HUNO", is_load_at_runtime=True) - else: - take_screenshot("HUNO") - print("HUNO Screenshoted") - -if "SP" in config["wanted-trackers"]["trackers"]: - print("Entering Speedapp.") - username = config["speedapp"]["username"] - password = config["speedapp"]["password"] - profile_url = config["speedapp"]["profile_url"] - - driver.get(profile_url) - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and screenshot - driver.find_element(By.TAG_NAME, "button").click() - - take_screenshot("SP") - print("Speedapp Screenshoted") - -if "FL" in config["wanted-trackers"]["trackers"]: - print("Entering Filelist.") - username = config["filelist"]["username"] - password = config["filelist"]["password"] - profile_url = config["filelist"]["profile_url"] - - driver.get(profile_url) - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and screenshot - driver.find_element(By.CLASS_NAME, "btn").click() - - take_screenshot("FL") - print("Filelist Screenshoted") - - -if "GPW" in config["wanted-trackers"]["trackers"]: - print("Entering GreatPosterWall.") - username = config["greatposterwall"]["username"] - password = config["greatposterwall"]["password"] - profile_url = config["greatposterwall"]["profile_url"] - - driver.get(profile_url) - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.CLASS_NAME, "Button").click() - - take_screenshot("GPW") - print("GPW Screenshoted") - - -###THE FOLLOWING ARE TESTED BY THE COMMUNITY### - -if "JME" in config["wanted-trackers"]["trackers"]: - print("Entering JME.") - username = config["jme"]["username"] - password = config["jme"]["password"] - profile_url = config["jme"]["profile_url"] - - driver.get( - "https://jme-reunit3d.de/login" - ) # DO NOT CHANGE THIS, JME requires an extra step for login - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.ID, "login-button").click() - - driver.get(profile_url) - - take_screenshot("JME") - print("JME-REUNIT3D Screenshoted") - - -if "ANT" in config["wanted-trackers"]["trackers"]: - print("Entering AnimeTorrents.") - username = config["animetorrents"]["username"] - password = config["animetorrents"]["password"] - profile_url = config["animetorrents"]["profile_url"] - - driver.get("https://animetorrents.me/login.php") # DO NOT CHANGE - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login - driver.find_element(By.ID, "login-element-6").click() - - # Load profile and screenshot - driver.get(profile_url) - - take_screenshot("ANT") - print("ANT Screenshoted") - - -if "RED" in config["wanted-trackers"]["trackers"]: - print("Entering Redacted.") - username = config["redacted"]["username"] - password = config["redacted"]["password"] - profile_url = config["redacted"]["profile_url"] - driver.get( - "https://redacted.sh/login.php" - ) # Keep the link as it is, DO NOT CHANGE. - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - twofa_field = driver.find_element(By.NAME, "qrcode_confirm") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # 2FA, ask for the code - code = input( - "Please enter the 2FA code: (If you don't have 2FA, just press enter.) " - ) - twofa_field.send_keys(code) - - # Login - driver.find_element(By.CLASS_NAME, "submit").click() - - # Load profile and screenshot - driver.get(profile_url) - - take_screenshot("RED") - print("RED Screenshoted") - - -if "STC" in config["wanted-trackers"]["trackers"]: - print("Entering SkipTheCommericals.") - username = config["skipthecommercials"]["username"] - password = config["skipthecommercials"]["password"] - profile_url = config["skipthecommercials"]["profile_url"] - - driver.get(profile_url) - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.ID, "login-button").click() - - take_screenshot("STC") - print("SkipTheCommericals Screenshoted") - - -if "STT" in config["wanted-trackers"]["trackers"]: - print("Entering SkipTheTrailers.") - username = config["skipthetrailers"]["username"] - password = config["skipthetrailers"]["password"] - profile_url = config["skipthetrailers"]["profile_url"] - - driver.get(profile_url) - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.ID, "login-button").click() - - take_screenshot("STT") - print("SkipTheTrailers Screenshoted") - -if "AB" in config["wanted-trackers"]["trackers"]: - print("Entering AnimeBytes") - username = config["animebytes"]["username"] - password = config["animebytes"]["password"] - profile_url = config["animebytes"]["profile_url"] - - driver.get( - "https://animebytes.tv/user.php" - ) # Keep the link as it is, DO NOT CHANGE. - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") + except ModuleNotFoundError: + print(f"Tracker {tracker} does not exist.") + continue - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login - driver.find_element(By.CLASS_NAME, "submit").click() - - # Load profile and screenshot - driver.get(profile_url) # Add your profile link - - take_screenshot("AB") - print("AnimeBytes Screenshoted") - -if "TDC" in config["wanted-trackers"]["trackers"]: - print("Entering TheDarkCommunity") - username = config["thedarkcommunity"]["username"] - password = config["thedarkcommunity"]["password"] - profile_url = config["thedarkcommunity"]["profile_url"] - - driver.get(profile_url) - - # Navigation - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.ID, "login-button").click() - - take_screenshot("TDC") - print("TDC Screenshoted") - - -if "CRT" in config["wanted-trackers"]["trackers"]: - print("Entering Cathode-Ray.tube") - username = config["cathode-raytube"]["username"] - password = config["cathode-raytube"]["password"] - profile_url = config["cathode-raytube"]["profile_url"] - - driver.get( - "https://www.cathode-ray.tube/login" - ) # Keep the link as it is, DO NOT CHANGE. - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login - driver.find_element(By.ID, "login_button").click() - - # 2FA is enabled, ask for the code - if driver.find_elements(By.NAME, "code"): - code = input("Please enter the 2FA code: ") - code_field = driver.find_element(By.NAME, "code") - code_field.send_keys(code) - driver.find_element(By.ID, "login_button").click() - - # Load profile and screenshot - driver.get(profile_url) - - # Hide passkey - try: - passkey_li = driver.find_element(By.XPATH, "//li[contains(text(), 'Passkey')]") - driver.execute_script("arguments[0].style.display = 'none';", passkey_li) - except: # noqa: E722 - pass - - take_screenshot("CRT") - print("CRT Screenshoted") - -if "MAM" in config["wanted-trackers"]["trackers"]: - print("Entering myanonamouse") - username = config["myanonamouse"]["username"] - password = config["myanonamouse"]["password"] - profile_url = config["myanonamouse"]["profile_url"] - - driver.get(profile_url) - - # Navigation - username_field = driver.find_element(By.NAME, "email") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.CLASS_NAME, "btn").click() - - take_screenshot("MAM") - print("myanonamouse Screenshoted") - -if "NBL" in config["wanted-trackers"]["trackers"]: - print("Entering Nebulance") - username = config["nebulance"]["username"] - password = config["nebulance"]["password"] - profile_url = config["nebulance"]["profile_url"] - - driver.get(profile_url) - - # Navigation - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.NAME, "login").click() - - take_screenshot("NBL") - print("Nebulance Screenshoted") - -if "TL" in config["wanted-trackers"]["trackers"]: - print("Entering TorrentLeech") - username = config["torrentleech"]["username"] - password = config["torrentleech"]["password"] - profile_url = config["torrentleech"]["profile_url"] - - driver.get(profile_url) - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.CLASS_NAME, "btn").click() - - take_screenshot("TL") - print("TorrentLeech Screenshoted") - -if "OPS" in config["wanted-trackers"]["trackers"]: - print("Entering Orpheus") - username = config["orpheus"]["username"] - password = config["orpheus"]["password"] - profile_url = config["orpheus"]["profile_url"] - driver.get( - "https://orpheus.network/login.php" - ) # Keep the link as it is, DO NOT CHANGE. - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - twofa_field = driver.find_element(By.NAME, "twofa") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # 2FA, ask for the code - code = input( - "Please enter the 2FA code: (If you don't have 2FA, just press enter.) " - ) - twofa_field.send_keys(code) - - # Login - driver.find_element(By.CLASS_NAME, "submit").click() - - # Load profile and screenshot - driver.get(profile_url) # Add your profile link - - take_screenshot("OPS") - print("OPS Screenshoted") - -if "SZN" in config["wanted-trackers"]["trackers"]: - print("Entering Swarmazon") - username = config["swarmazon"]["username"] - password = config["swarmazon"]["password"] - profile_url = config["swarmazon"]["profile_url"] - - driver.get("https://swarmazon.club/en/account/login.php") - - # Navigation - Login - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login - driver.find_element(By.CLASS_NAME, "btn").click() - - # Load profile and screenshot - driver.get(profile_url) # Keep as-is - - take_screenshot("Swarmazon") - print("Swarmazon Screenshoted") - -if "MTV" in config["wanted-trackers"]["trackers"]: - print("Entering MoreThanTV") - username = config["morethantv"]["username"] - password = config["morethantv"]["password"] - profile_url = config["morethantv"]["profile_url"] - - driver.get(profile_url) - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - driver.find_element(By.ID, "login_button").click() - - # 2FA is enabled, ask for the code - if driver.find_elements(By.NAME, "code"): - code = input("Please enter the 2FA code: ") - code_field = driver.find_element(By.NAME, "code") - code_field.send_keys(code) - driver.find_element(By.ID, "login_button").click() - - # Hide passkey - try: - passkey_li = driver.find_element(By.XPATH, "//li[contains(text(), 'Passkey')]") - driver.execute_script("arguments[0].style.display = 'none';", passkey_li) - except: # noqa: E722 - pass - - # Login and save screenshot - take_screenshot("MoreThanTV") - print("MoreThanTV Screenshoted") - -if "HDT" in config["wanted-trackers"]["trackers"]: - print("Entering HD-Torrents") - username = config["hdtorrents"]["username"] - password = config["hdtorrents"]["password"] - profile_url = config["hdtorrents"]["profile_url"] - - driver.get("https://hd-torrents.org") # Keep the link as it is, DO NOT CHANGE. - - # Navigation - Login - username_field = driver.find_element(By.NAME, "uid") - password_field = driver.find_element(By.NAME, "pwd") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login - driver.find_element( - By.XPATH, - "/html/body/div[3]/table/tbody/tr/td/form/table/tbody/tr/td[1]/table/tbody/tr/td[5]/input", - ).click() - - # Load profile and screenshot - driver.get(profile_url) # Add your profile link - - take_screenshot("HDT") - print("HDT Screenshoted") - -if "BTN" in config["wanted-trackers"]["trackers"]: - with SB(uc=True, locale_code="en") as sb: - print("Entering BroadcasTheNet") - username = config["broadcasthenet"]["username"] - password = config["broadcasthenet"]["password"] - profile_url = config["broadcasthenet"]["profile_url"] - - sb.driver.uc_open_with_reconnect(profile_url, 1) - - # Navigation - DO NOT CHANGE - username_field = "input[id='username']" - password_field = "input[id='password']" - login_button = "input[name='login']" - - # Send username and password - sb.type(username_field, username) - sb.type(password_field, password) - sb.driver.reconnect(0.1) - sb.driver.uc_click(login_button, reconnect_time=4) - sb.wait_for_text_not_visible("Checking", timeout=10) - - # 2FA is enabled, ask for the code - if sb.driver.find_elements(By.ID, "code"): - code = input("Please enter the 2FA code: ") - code_field = "input[id='code']" - sb.type(code_field, code) - submit_button = "input[type='submit']" - sb.driver.uc_click(submit_button, reconnect_time=4) - - sb.driver.get(profile_url) - - info_button = "a[href='#section2']" - sb.driver.uc_click(info_button, reconnect_time=4) - # Login and save screenshot - take_screenshot("BroadcasTheNet", sb.driver) - print("BroadcasTheNet Screenshoted") - -if "GGN" in config["wanted-trackers"]["trackers"]: - print("Entering GazelleGames") - username = config["gazellegames"]["username"] - password = config["gazellegames"]["password"] - profile_url = config["gazellegames"]["profile_url"] - - driver.get(profile_url) - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - twofa_field = driver.find_element(By.NAME, "authkey") - - print( - "Manually solve the captcha image. Press enter when done. (If you use 2FA then press enter after you type the code below)" - ) - code = input() - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - twofa_field.send_keys(code) - - driver.find_element(By.CLASS_NAME, "submit").click() - - # Login and save screenshot - take_screenshot("GazelleGames") - print("GazelleGames Screenshoted") - -if "PTP" in config["wanted-trackers"]["trackers"]: - print("Entering PassThePopcorn") - username = config["passthepopcorn"]["username"] - password = config["passthepopcorn"]["password"] - profile_url = config["passthepopcorn"]["profile_url"] - - driver.get(profile_url) - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - driver.find_element(By.ID, "login-button").click() - print("Manually solve the captcha image. Press enter when done.") - code = input() - driver.find_element(By.ID, "login-button").click() - - # 2FA is enabled, ask for the code - if driver.find_elements(By.ID, "tfa-code"): - code = input("Please enter the 2FA code: ") - code_field = driver.find_element(By.ID, "tfa-code") - code_field.send_keys(code) - verify_button = driver.find_element(By.CSS_SELECTOR, "input[value='Verify']") - verify_button.click() - - # is_load_at_runtime is set to ensure the full page screenshot is taken correctly - if config["settings"].get("full_page_screenshot", "false") == "true": - take_screenshot("PassThePopcorn", is_load_at_runtime=True) - else: - take_screenshot("PassThePopcorn") - print("PassThePopcorn Screenshoted") - -if "BHD" in config["wanted-trackers"]["trackers"]: - print("Entering BeyondHD") - username = config["beyond-hd"]["username"] - password = config["beyond-hd"]["password"] - profile_url = config["beyond-hd"]["profile_url"] - - driver.get(profile_url) - - # Navigation - DO NOT CHANGE - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - print("Manually solve the captcha. Press enter when done.") - code = input() - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - driver.find_element(By.ID, "login-button").click() - - # 2FA is enabled, ask for the code - if driver.find_elements(By.ID, "code"): - code = input("Please enter the 2FA code: ") - code_field = driver.find_element(By.ID, "code") - code_field.send_keys(code) - driver.find_element(By.ID, "login-button").click() - - driver.get(profile_url) - # Login and save screenshot - take_screenshot("BeyondHD") - print("BeyondHD Screenshoted") - -if "OTW" in config["wanted-trackers"]["trackers"]: - print("Entering OTW.") - username = config["oldtoons"]["username"] - password = config["oldtoons"]["password"] - profile_url = config["oldtoons"]["profile_url"] - - driver.get(profile_url) - - # Navigation - username_field = driver.find_element(By.NAME, "username") - password_field = driver.find_element(By.NAME, "password") - - # Send username and password - username_field.send_keys(username) - password_field.send_keys(password) - - # Login and save screenshot - driver.find_element(By.CLASS_NAME, "auth-form__primary-button").click() - - # 2FA is enabled, ask for the code - if driver.find_elements(By.ID, "code"): - code = input("Please enter the 2FA code: ") - code_field = driver.find_element(By.ID, "code") - code_field.send_keys(code) - - take_screenshot("OTW") - print("OTW Screenshoted") - -else: - driver.quit() + # Create an instance of the tracker class and run it + tracker_instance = tracker_class(driver, config) + tracker_instance.run() driver.quit() - # GitHub: https://github.com/KlevGG/TrackerScreenshot diff --git a/trackers/__init__.py b/trackers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/trackers/aither.py b/trackers/aither.py new file mode 100644 index 0000000..c34355d --- /dev/null +++ b/trackers/aither.py @@ -0,0 +1,51 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class AitherTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "aither" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element( + By.CLASS_NAME, "auth-form__primary-button" + ) + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.ID, "code") + if code_field: + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/animebytes.py b/trackers/animebytes.py new file mode 100644 index 0000000..6ecfae7 --- /dev/null +++ b/trackers/animebytes.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class AnimebytesTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "animebytes" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login(login_url=self.config[self.tracker_name]["login_url"]) + + def click_login_button(self): + login_button = self.driver.find_element(By.CLASS_NAME, "submit") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/animetorrents.py b/trackers/animetorrents.py new file mode 100644 index 0000000..fa4b4b4 --- /dev/null +++ b/trackers/animetorrents.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class AnimetorrentsTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "animetorrents" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login(login_url=self.config[self.tracker_name]["login_url"]) + + def click_login_button(self): + login_button = self.driver.find_element(By.ID, "login-element-6") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/anthelion.py b/trackers/anthelion.py new file mode 100644 index 0000000..b53a8c1 --- /dev/null +++ b/trackers/anthelion.py @@ -0,0 +1,50 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class AnthelionTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "anthelion" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and 2fa elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + twofa_field = self.driver.find_element(By.ID, "twofa") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # 2FA, ask for the code + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input( + "Please enter the 2FA code: (If you don't have 2FA, just press enter.) " + ) + twofa_field.send_keys(code) + + login_button = self.driver.find_element(By.CLASS_NAME, "submit") + # Click on the login button + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/base_tracker.py b/trackers/base_tracker.py new file mode 100644 index 0000000..b49d47e --- /dev/null +++ b/trackers/base_tracker.py @@ -0,0 +1,112 @@ +import datetime +from selenium.webdriver.common.by import By +from Screenshot import Screenshot # type: ignore + + +class BaseTracker: + def __init__(self, driver, config, tracker_name): + self.driver = driver + self.config = config + self.tracker_name = tracker_name + self.ob = Screenshot.Screenshot() + + def login(self, login_url=None): + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL or login URL + if login_url: + self.driver.get(login_url) + else: + self.driver.get(profile_url) + + self.enter_credentials() + self.click_login_button() + + if login_url: + self.driver.get(profile_url) + + def enter_credentials(self, username_field=None, password_field=None): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + + # Find the username, password and login button elements + if not username_field: + username_field = self.driver.find_element(By.NAME, "username") + if not password_field: + password_field = self.driver.find_element(By.NAME, "password") + + # Type username and password + username_field.send_keys(username) + password_field.send_keys(password) + + def click_login_button(self): + login_button = self.driver.find_element(By.ID, "login-button") + login_button.click() + + def hide_passkey(self): + try: + passkey_li = self.driver.find_element( + By.XPATH, "//li[contains(text(), 'Passkey')]" + ) + self.driver.execute_script( + "arguments[0].style.display = 'none';", passkey_li + ) + except: # noqa: E722 + pass + + def hide_notifications(self): + try: + self.driver.execute_script( + "document.querySelector('#noty_bottomRight_layout_container').style.display = 'none';" + ) + except: # noqa: E722 + pass + + def hide_ip(self): + # CRT + try: + element = self.driver.find_element(By.ID, "statuscont0") + self.driver.execute_script("arguments[0].style.display = 'none';", element) + except: # noqa: E722 + pass + + # MTV + try: + element = self.driver.find_element(By.ID, "statuscont1") + self.driver.execute_script("arguments[0].style.display = 'none';", element) + except: # noqa: E722 + pass + + # OTW + try: + element = self.driver.find_element( + By.XPATH, "//h2[contains(text(), 'Clients and IP-Addresses')]" + ) + self.driver.execute_script( + "arguments[0].parentNode.style.display = 'none';", element + ) + except: # noqa: E722 + pass + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + date_string = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S") + image_name = tracker_name + "_" + date_string + ".png" + + if self.config["settings"].get("full_page_screenshot", "false") == "true": + self.ob.full_screenshot( + self.driver, + save_path="screenshots", + image_name=image_name, + is_load_at_runtime=is_load_at_runtime, + ) + else: + self.driver.save_screenshot("screenshots/" + image_name) + + def run(self): + print("Capturing " + self.tracker_name) + self.login() + self.hide_passkey() + self.hide_notifications() + self.hide_ip() + self.take_screenshot(self.tracker_name) + print("Captured " + self.tracker_name + "\n") diff --git a/trackers/beyond-hd.py b/trackers/beyond-hd.py new file mode 100644 index 0000000..2b64b8d --- /dev/null +++ b/trackers/beyond-hd.py @@ -0,0 +1,57 @@ +import pyotp +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class BeyondhdTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "beyond-hd" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.ID, "login-button") + + print("Manually solve the captcha. Press enter when done.") + code = input() + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + try: + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.ID, "code") + if code_field: + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + login_button = self.driver.find_element(By.ID, "login-button") + login_button.click() + except NoSuchElementException: + login_button.click() + + self.driver.get(profile_url) + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/blutopia.py b/trackers/blutopia.py new file mode 100644 index 0000000..1a4b86c --- /dev/null +++ b/trackers/blutopia.py @@ -0,0 +1,56 @@ +import pyotp +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class BlutopiaTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "blutopia" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element( + By.CLASS_NAME, "auth-form__primary-button" + ) + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + try: + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.ID, "code") + if code_field: + # if auto_2fa is enabled, use the 2fa secret from decrypted_secrets + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + except NoSuchElementException: + print("No 2FA required, continuing login process.") + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/broadcasthenet.py b/trackers/broadcasthenet.py new file mode 100644 index 0000000..68ea61d --- /dev/null +++ b/trackers/broadcasthenet.py @@ -0,0 +1,55 @@ +import pyotp +from selenium.webdriver.common.by import By +from seleniumbase import SB # type: ignore + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class BroadcasthenetTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "broadcasthenet" + super().__init__(driver, config, self.tracker_name) + + def run(self): + with SB(uc=True, locale_code="en") as sb: + self.driver = sb.driver + print("Capturing " + self.tracker_name) + username = self.config["broadcasthenet"]["username"] + password = self.config["broadcasthenet"]["password"] + profile_url = self.config["broadcasthenet"]["profile_url"] + + sb.driver.uc_open_with_reconnect(profile_url, 1) + + username_field = "input[id='username']" + password_field = "input[id='password']" + login_button = "input[name='login']" + + # Send username and password + sb.type(username_field, username) + sb.type(password_field, password) + sb.driver.reconnect(0.1) + sb.driver.uc_click(login_button, reconnect_time=4) + sb.wait_for_text_not_visible("Checking", timeout=10) + + # 2FA is enabled, ask for the code + if sb.driver.find_elements(By.ID, "code"): + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field = "input[id='code']" + sb.type(code_field, code) + submit_button = "input[type='submit']" + sb.driver.uc_click(submit_button, reconnect_time=4) + + sb.driver.get(profile_url) + + info_button = "a[href='#section2']" + sb.driver.uc_click(info_button, reconnect_time=4) + # Login and save screenshot + super().take_screenshot("broadcasthenet") + print("Captured " + self.tracker_name + "\n") diff --git a/trackers/cathode-raytube.py b/trackers/cathode-raytube.py new file mode 100644 index 0000000..2b955de --- /dev/null +++ b/trackers/cathode-raytube.py @@ -0,0 +1,59 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class CathoderaytubeTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "cathode-raytube" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + login_url = self.config[self.tracker_name]["login_url"] + + # Open the login URL + self.driver.get(login_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.ID, "login_button") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.NAME, "code") + if code_field: + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + login_button = self.driver.find_element(By.ID, "login_button") + login_button.click() + + # Open the profile URL + self.driver.get(profile_url) + + def click_login_button(self): + login_button = self.driver.find_element(By.ID, "login_button") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/deepbassnine.py b/trackers/deepbassnine.py new file mode 100644 index 0000000..d24f66e --- /dev/null +++ b/trackers/deepbassnine.py @@ -0,0 +1,35 @@ +from selenium.webdriver.common.by import By + +from .base_tracker import BaseTracker + + +class DeepbassnineTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "deepbassnine" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.NAME, "login") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/filelist.py b/trackers/filelist.py new file mode 100644 index 0000000..4855b24 --- /dev/null +++ b/trackers/filelist.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class FilelistTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "filelist" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def click_login_button(self): + login_button = self.driver.find_element(By.CLASS_NAME, "btn") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/gazellegames.py b/trackers/gazellegames.py new file mode 100644 index 0000000..4cac577 --- /dev/null +++ b/trackers/gazellegames.py @@ -0,0 +1,51 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class GazellegamesTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "gazellegames" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and 2fa elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + twofa_field = self.driver.find_element(By.NAME, "authkey") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # 2FA, ask for the code + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + input("Manually solve the captcha image. Press enter when done.") + else: + code = input( + "Manually solve the captcha image. Press enter when done. (If you use 2FA then press enter after you type the code below)" + ) + twofa_field.send_keys(code) + + login_button = self.driver.find_element(By.CLASS_NAME, "submit") + # Click on the login button + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/greatposterwall.py b/trackers/greatposterwall.py new file mode 100644 index 0000000..3cbb0cf --- /dev/null +++ b/trackers/greatposterwall.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class GreatposterwallTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "greatposterwall" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def click_login_button(self): + login_button = self.driver.find_element(By.CLASS_NAME, "Button") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/hdtorrents.py b/trackers/hdtorrents.py new file mode 100644 index 0000000..87aca9e --- /dev/null +++ b/trackers/hdtorrents.py @@ -0,0 +1,30 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class HdtorrentsTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "hdtorrents" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login(login_url=self.config[self.tracker_name]["login_url"]) + + def enter_credentials(self): + username_field = self.driver.find_element(By.NAME, "uid") + password_field = self.driver.find_element(By.NAME, "pwd") + + super().enter_credentials(username_field, password_field) + + def click_login_button(self): + login_button = self.driver.find_element( + By.XPATH, + "/html/body/div[3]/table/tbody/tr/td/form/table/tbody/tr/td[1]/table/tbody/tr/td[5]/input", + ) + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/huno.py b/trackers/huno.py new file mode 100644 index 0000000..537e01f --- /dev/null +++ b/trackers/huno.py @@ -0,0 +1,67 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class HunoTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "huno" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config["huno"]["username"] + password = self.config["huno"]["password"] + profile_url = self.config["huno"]["profile_url"] + skip = False + + # Open the profile URL + self.driver.get(profile_url) + + if self.driver.find_elements( + By.XPATH, + "//*[contains(text(), 'Verify you are human by completing the action below.')]", + ): + print( + "Please solve the challenge and press enter to continue or type 'n' and press enter to skip." + ) + response = input() + if response == "n": + skip = True + if not skip: + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.ID, "login-button") + + # Type username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.ID, "v_input") + if code_field: + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + + verify_button = self.driver.find_element(By.ID, "submit_verification") + verify_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + if self.config["settings"].get("full_page_screenshot", "false") == "true": + super().take_screenshot(self.tracker_name, is_load_at_runtime=True) + else: + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/jme.py b/trackers/jme.py new file mode 100644 index 0000000..beeb6c9 --- /dev/null +++ b/trackers/jme.py @@ -0,0 +1,16 @@ +from .base_tracker import BaseTracker + + +class JmeTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "jme" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login(login_url=self.config[self.tracker_name]["login_url"]) + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/lst.py b/trackers/lst.py new file mode 100644 index 0000000..9211fdb --- /dev/null +++ b/trackers/lst.py @@ -0,0 +1,16 @@ +from .base_tracker import BaseTracker + + +class LstTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "lst" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/morethantv.py b/trackers/morethantv.py new file mode 100644 index 0000000..cbcf41a --- /dev/null +++ b/trackers/morethantv.py @@ -0,0 +1,54 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class MorethantvTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "morethantv" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.ID, "login_button") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.NAME, "code") + if code_field: + decrypted_secrets = get_decrypted_secrets() + if ( + self.config["settings"]["auto_2fa"] == "true" + and self.tracker_name in decrypted_secrets + ): + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + login_button = self.driver.find_element(By.ID, "login_button") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/myanonamouse.py b/trackers/myanonamouse.py new file mode 100644 index 0000000..239f205 --- /dev/null +++ b/trackers/myanonamouse.py @@ -0,0 +1,26 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class MyanonamouseTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "myanonamouse" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def enter_credentials(self): + username_field = self.driver.find_element(By.NAME, "email") + + super().enter_credentials(username_field) + + def click_login_button(self): + login_button = self.driver.find_element(By.CLASS_NAME, "btn") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/nebulance.py b/trackers/nebulance.py new file mode 100644 index 0000000..aa8fb86 --- /dev/null +++ b/trackers/nebulance.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class NebulanceTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "nebulance" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def click_login_button(self): + login_button = self.driver.find_element(By.NAME, "login") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/oldtoons.py b/trackers/oldtoons.py new file mode 100644 index 0000000..a3b88e3 --- /dev/null +++ b/trackers/oldtoons.py @@ -0,0 +1,51 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class OldtoonsTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "oldtoons" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element( + By.CLASS_NAME, "auth-form__primary-button" + ) + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.ID, "code") + if code_field: + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/orpheus.py b/trackers/orpheus.py new file mode 100644 index 0000000..76fbe86 --- /dev/null +++ b/trackers/orpheus.py @@ -0,0 +1,54 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class OrpheusTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "orpheus" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + login_url = self.config[self.tracker_name]["login_url"] + + # Open the login URL + self.driver.get(login_url) + + # Find the username, password and 2fa elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + twofa_field = self.driver.find_element(By.NAME, "twofa") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # 2FA, ask for the code + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input( + "Please enter the 2FA code: (If you don't have 2FA, just press enter.) " + ) + twofa_field.send_keys(code) + + login_button = self.driver.find_element(By.CLASS_NAME, "submit") + # Click on the login button + login_button.click() + + # Open the profile URL + self.driver.get(profile_url) + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/passthepopcorn.py b/trackers/passthepopcorn.py new file mode 100644 index 0000000..fb3850b --- /dev/null +++ b/trackers/passthepopcorn.py @@ -0,0 +1,61 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class PassthepopcornTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "passthepopcorn" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.ID, "login-button") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + captcha_container = self.driver.find_element(By.ID, "captcha_container") + + if captcha_container.get_attribute("class") == "hidden": + login_button.click() + + print("Manually solve the captcha. Press enter when done.") + code = input() + + # Click on the login button + login_button.click() + + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.ID, "tfa-code") + if code_field: + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + verify_button = self.driver.find_element( + By.CSS_SELECTOR, "input[value='Verify']" + ) + verify_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name, is_load_at_runtime=True) + + def run(self): + super().run() diff --git a/trackers/pixelcove.py b/trackers/pixelcove.py new file mode 100644 index 0000000..c8c0814 --- /dev/null +++ b/trackers/pixelcove.py @@ -0,0 +1,58 @@ +import pyotp +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class PixelcoveTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "pixelcove" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.ID, "login_button") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + try: + # 2FA is enabled, ask for the code + code_field = self.driver.find_element(By.NAME, "code") + if code_field: + decrypted_secrets = get_decrypted_secrets() + if ( + self.config["settings"]["auto_2fa"] == "true" + and self.tracker_name in decrypted_secrets + ): + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + code_field.send_keys(code) + login_button = self.driver.find_element(By.ID, "login_button") + login_button.click() + except NoSuchElementException: + print("No 2FA required, continuing login process.") + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/redacted.py b/trackers/redacted.py new file mode 100644 index 0000000..793382e --- /dev/null +++ b/trackers/redacted.py @@ -0,0 +1,50 @@ +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class RedactedTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "redacted" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and 2fa elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + twofa_field = self.driver.find_element(By.NAME, "qrcode_confirm") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # 2FA, ask for the code + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input( + "Please enter the 2FA code: (If you don't have 2FA, just press enter.) " + ) + twofa_field.send_keys(code) + + login_button = self.driver.find_element(By.CLASS_NAME, "submit") + # Click on the login button + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/reelflix.py b/trackers/reelflix.py new file mode 100644 index 0000000..40a3845 --- /dev/null +++ b/trackers/reelflix.py @@ -0,0 +1,16 @@ +from .base_tracker import BaseTracker + + +class ReelflixTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "reelflix" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/skipthecommercials.py b/trackers/skipthecommercials.py new file mode 100644 index 0000000..ee983b4 --- /dev/null +++ b/trackers/skipthecommercials.py @@ -0,0 +1,16 @@ +from .base_tracker import BaseTracker + + +class SkipthecommercialsTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "skipthecommercials" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/skipthetrailers.py b/trackers/skipthetrailers.py new file mode 100644 index 0000000..0fe636d --- /dev/null +++ b/trackers/skipthetrailers.py @@ -0,0 +1,16 @@ +from .base_tracker import BaseTracker + + +class SkipthetrailersTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "skipthetrailers" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/speedapp.py b/trackers/speedapp.py new file mode 100644 index 0000000..f32de81 --- /dev/null +++ b/trackers/speedapp.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class SpeedappTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "speedapp" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def click_login_button(self): + login_button = self.driver.find_element(By.TAG_NAME, "button") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/swarmazon.py b/trackers/swarmazon.py new file mode 100644 index 0000000..b4da30f --- /dev/null +++ b/trackers/swarmazon.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class SwarmazonTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "swarmazon" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login(login_url=self.config[self.tracker_name]["login_url"]) + + def click_login_button(self): + login_button = self.driver.find_element(By.NAME, "btn") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/thedarkcommunity.py b/trackers/thedarkcommunity.py new file mode 100644 index 0000000..3652a92 --- /dev/null +++ b/trackers/thedarkcommunity.py @@ -0,0 +1,21 @@ +from selenium.webdriver.common.by import By +from .base_tracker import BaseTracker + + +class CathoderaytubeTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "cathode-raytube" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login(login_url=self.config[self.tracker_name]["login_url"]) + + def click_login_button(self): + login_button = self.driver.find_element(By.CLASS_NAME, "submit") + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/torrentleech.py b/trackers/torrentleech.py new file mode 100644 index 0000000..708648f --- /dev/null +++ b/trackers/torrentleech.py @@ -0,0 +1,82 @@ +import time +import pyotp +from selenium.webdriver.common.by import By + +from utils import get_decrypted_secrets + +from .base_tracker import BaseTracker + + +class TorrentleechTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "torrentleech" + super().__init__(driver, config, self.tracker_name) + + def login(self): + super().login() + + def click_login_button(self): + login_button = self.driver.find_element(By.CLASS_NAME, "btn") + login_button.click() + + prefcode = self.driver.find_element(By.ID, "prefcode") + + if prefcode: + # if auto_2fa is enabled, use the 2fa secret from decrypted_secrets + if self.config["settings"]["auto_2fa"] == "true": + decrypted_secrets = get_decrypted_secrets() + totp = pyotp.TOTP(decrypted_secrets[self.tracker_name]) + code = totp.now() + else: + code = input("Please enter the 2FA code: ") + + code_fields = self.driver.find_elements(By.CLASS_NAME, "prefcode_otp") + for i in range(6): + code_fields[i].send_keys(code[i]) + + continue_button = self.driver.find_element( + By.CLASS_NAME, "button2facontinue" + ) + + time.sleep(5) + + continue_button.click() + + profile_url = self.config[self.tracker_name]["profile_url"] + self.driver.get(profile_url) + + self.hide_secrets() + + def hide_secrets(self): + irc_tr = self.driver.find_element(By.XPATH, "//td[text()='IRC Key']/..") + irc_td = irc_tr.find_elements(By.XPATH, "./*")[1] + self.driver.execute_script("arguments[0].textContent = 'Hidden';", irc_td) + + rss_tr = self.driver.find_element(By.XPATH, "//td[text()='RSS Key']/..") + rss_td = rss_tr.find_elements(By.XPATH, "./*")[1] + self.driver.execute_script("arguments[0].textContent = 'Hidden';", rss_td) + + passkey_tr = self.driver.find_element( + By.XPATH, "//td[text()='Torrent Passkey']/.." + ) + passkey_td = passkey_tr.find_elements(By.XPATH, "./*")[1] + self.driver.execute_script("arguments[0].textContent = 'Hidden';", passkey_td) + + alt_2fa_tr = self.driver.find_element( + By.XPATH, "//td[text()='Alt 2FA Token']/.." + ) + alt_2fa_td = alt_2fa_tr.find_elements(By.XPATH, "./*")[1] + self.driver.execute_script("arguments[0].textContent = 'Hidden';", alt_2fa_td) + + vpn_msg_placeholder = self.driver.find_element( + By.CLASS_NAME, "vpn-msg-placeholder" + ) + self.driver.execute_script( + "arguments[0].style.display = 'none';", vpn_msg_placeholder + ) + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/trackers/tv-vault.py b/trackers/tv-vault.py new file mode 100644 index 0000000..043f6bb --- /dev/null +++ b/trackers/tv-vault.py @@ -0,0 +1,35 @@ +from selenium.webdriver.common.by import By + +from .base_tracker import BaseTracker + + +class TvvaultTracker(BaseTracker): + def __init__(self, driver, config): + self.tracker_name = "tv-vault" + super().__init__(driver, config, self.tracker_name) + + def login(self): + username = self.config[self.tracker_name]["username"] + password = self.config[self.tracker_name]["password"] + profile_url = self.config[self.tracker_name]["profile_url"] + + # Open the profile URL + self.driver.get(profile_url) + + # Find the username, password and login button elements + username_field = self.driver.find_element(By.NAME, "username") + password_field = self.driver.find_element(By.NAME, "password") + login_button = self.driver.find_element(By.NAME, "login") + + # Send username and password + username_field.send_keys(username) + password_field.send_keys(password) + + # Click on the login button + login_button.click() + + def take_screenshot(self, tracker_name, is_load_at_runtime=False): + super().take_screenshot(self.tracker_name) + + def run(self): + super().run() diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..3520c26 --- /dev/null +++ b/utils.py @@ -0,0 +1,105 @@ +import base64 +import configparser +import os +import sys +from getpass import getpass + +from argon2 import PasswordHasher +from argon2.exceptions import VerifyMismatchError +from cryptography.fernet import Fernet +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC + +_cached_master_password = None + + +# Generate a key from the master password +def generate_key(): + # Read the config file + config = configparser.ConfigParser() + config.read("config.ini") + + # Get the salt from the config file + salt = bytes.fromhex(config["settings"]["salt"]) + password = _cached_master_password + + # Derive a key using PBKDF2HMAC + kdf = PBKDF2HMAC( + algorithm=hashes.SHA256(), + length=32, + salt=salt, + iterations=100000, + backend=default_backend(), + ) + key = base64.urlsafe_b64encode(kdf.derive(password.encode("utf-8"))) + return key + + +# Encrypt the 2FA secrets +def encrypt_secrets(secrets): + key = generate_key() + + fernet = Fernet(key) + encrypted_secrets = {} + for tracker, secret in secrets.items(): + if secret == "0": + encrypted_secrets[tracker] = "0" + else: + encrypted_secrets[tracker] = fernet.encrypt(secret.encode("utf-8")).decode( + "utf-8" + ) + return encrypted_secrets + + +# Decrypt the 2FA secrets +def decrypt_secrets(encrypted_secrets): + key = generate_key() + + fernet = Fernet(key) + decrypted_secrets = {} + for tracker, encrypted_secret in encrypted_secrets.items(): + if encrypted_secret == "0": + decrypted_secrets[tracker] = "0" + else: + decrypted_secrets[tracker] = fernet.decrypt( + encrypted_secret.encode("utf-8") + ).decode("utf-8") + return decrypted_secrets + + +def get_cached_master_password(): + global _cached_master_password + return _cached_master_password + + +def get_decrypted_secrets(): + global _cached_master_password + + # Read the secrets file, create it if it doesn't exist + if not os.path.exists("secrets.ini"): + with open("secrets.ini", "w") as secretsfile: + secretsfile.write("[secrets]\n") + secrets_config = configparser.ConfigParser() + secrets_config.read("secrets.ini") + + # Read the config file + config = configparser.ConfigParser() + config.read("config.ini") + + # Verify the master password + if _cached_master_password is None: + _cached_master_password = getpass("Enter the master password: " + "\n") + + master_password_hash = config["settings"]["master_password"] + ph = PasswordHasher() + try: + ph.verify(master_password_hash, _cached_master_password) + except VerifyMismatchError: + sys.exit(1) + + # Decrypt the secrets + encrypted_secrets = secrets_config["secrets"] + decrypted_secrets = decrypt_secrets(encrypted_secrets) + + return decrypted_secrets