From d55fe215b7bfe8a84659bd620a4fc9c2a5d5d41a Mon Sep 17 00:00:00 2001 From: Abhorrent_Anger Date: Wed, 20 Dec 2023 11:42:59 +0200 Subject: [PATCH] Initial commit --- .gitignore | 141 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 9 ++- classes/__init__.py | 0 classes/browser.py | 71 ++++++++++++++++++++++ main.py | 90 ++++++++++++++++++++++++++++ 5 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 classes/__init__.py create mode 100644 classes/browser.py create mode 100644 main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4431509 --- /dev/null +++ b/.gitignore @@ -0,0 +1,141 @@ +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# VSCode +.vscode + +# Sensitive configs +users +designs + +# Run-time +chromedriver* +geckodriver.log \ No newline at end of file diff --git a/README.md b/README.md index d5ec9fc..d158eea 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ # ScrapTFRaffleBotSelenium -Enters Public Raffles. Now with Selenium. \ No newline at end of file +Enters Public Raffles. Call as `python main.py `. + +Deprecated due to undetected-chromedriver and seleniumbase Cloudflare issues. + +## Dependencies: +``` +pip install undetected-chromedriver seleniumbase urllib2 termcolor +``` \ No newline at end of file diff --git a/classes/__init__.py b/classes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/classes/browser.py b/classes/browser.py new file mode 100644 index 0000000..71e7cfd --- /dev/null +++ b/classes/browser.py @@ -0,0 +1,71 @@ +import undetected_chromedriver as uc +import time +import os +import sys +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +# from seleniumbase import Driver +from termcolor import colored + +CHROMEDRIVER = "chromedriver" + +class Browser(): + def __init__(self, timeout=15): + chromedriver_path = os.path.join( + os.path.dirname(__file__) + '/../', CHROMEDRIVER) + if os.path.exists(chromedriver_path): + uc.install( + executable_path=chromedriver_path, + ) + else: + print(colored( + f"Couldn't find a dedicated 'chromedriver'! Relying on an installed browser instead...", "yellow")) + options = uc.ChromeOptions() + options.add_argument('--disable-blink-features=AutomationControlled') + self.instance = uc.Chrome(use_subprocess=False, options=options, incognito=True) + # self.instance = Driver(uc=True, incognito=True) + self.timeout = timeout + self.instance.implicitly_wait(self.timeout) + + def quit(self): + self.instance.quit() + + def open(self, url): + self.instance.get(url) + + def get_element(self, selector): + return self.instance.find_element(By.CSS_SELECTOR, selector) + + def get_elements(self, selector): + return self.instance.find_elements(By.CSS_SELECTOR, selector) + + def element_exists(self, selector): + try: + self.get_element(selector) + return True + except Exception: + return False + + def click_element(self, selector): + try: + self.get_element(selector).click_safe() + return True + except Exception as e: + print(colored(f"Couldn't click on {'selector'}: {e}", "red")) + return False + + def find_element(self, selector, text, visible=False): + try: + for element in self.get_element(selector): + if not visible or element.is_displayed(): + return element + except Exception: + pass + return False + + def add_cookie(self, key, value, cookie_domain, url): + self.instance.add_cookie({"name": key, "value": value, "domain": cookie_domain}) + + def scroll_down(self): + self.get_element('body').send_keys(Keys.END) \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..d129e97 --- /dev/null +++ b/main.py @@ -0,0 +1,90 @@ +import time +import sys +from termcolor import colored +from classes.browser import Browser +from selenium.webdriver.common.by import By + +SCRAPTF = '' +USERNAME = '' +COOKIE_DOMAIN = '.scrap.tf' +BASE_URL = 'https://scrap.tf' +RAFFLE_URL = '/raffles/' +PAGINATION_ATTEMPTS = 0 +BROWSER = None + +def load_arguments(): + global SCRAPTF, USERNAME + SCRAPTF = sys.argv[1] + USERNAME = sys.argv[2] + +def start_browser(): + global BROWSER + try: + BROWSER = Browser() + except KeyboardInterrupt as e: + print( + colored(f"Received an interrupt signal (Ctrl+C) during browser instance creation, assuming panic and shutting down. {e}", "yellow")) + sys.exit() + except Exception as e: + print( + colored(f"Fatal error during browser instance creation: {e}", "red")) + +def set_cookies(): + global BROWSER + BROWSER.open(BASE_URL + RAFFLE_URL) + BROWSER.add_cookie('scraptf', SCRAPTF, COOKIE_DOMAIN, BASE_URL) + BROWSER.add_cookie('ncmp-cc', '', COOKIE_DOMAIN, BASE_URL) + BROWSER.add_cookie('ncmp', 'CP3FdEAP3FdEADyvJAENAeEgAP_gAEPgACiQg1NX_H__bX9v-Xr36ft0eY1f99j77sQxBhfJs-4FyLvW_JwX32EyNE26tqYKmRIEu3ZBIQFtHJnURVihaogVrzHsYkGcgTNKJ-BkgHMRa2dYCF5vmYtj-QKZ5_p_d3f52T_9_dv-3dzzz9Vnv3e9fmdlcKida59tH_n_bRKb-7Ie9_7-_4v09N_rk2_eTVv_9evv71-u_t____9_9__AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAEQamr_j__tr-3_L179P26PMav--x992IYgwvk2fcC5F3rfk4L77CZGibdW1MFTIkCXbsgkIC2jkzqIqxQtUQK15j2MSDOQJmlE_AyQDmItbOsBC83zMWx_IFM8_0_u7v87J_-_u3_bu555-qz37vevzOyuFROtc-2j_z_tolN_dkPe_9_f8X6em_1ybfvJq3_-vX396_Xf2____-_-__gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAA.YAAAAAAAAAAA', COOKIE_DOMAIN, BASE_URL) + +def close_browser(): + global BROWSER + if BROWSER: + BROWSER.quit() + +def check_notifications(): + global BROWSER + notices = BROWSER.get_element('.user-notices-count').text + if notices != '0': + print(colored('You have ' + notices + ' new notices!', 'red')) + +def unentered_raffles(): + global BROWSER + BROWSER.open(BASE_URL + RAFFLE_URL) + for x in range(0, PAGINATION_ATTEMPTS): + BROWSER.scroll_down() + if BROWSER.element_exists('.panel-body raffle-pagination-done'): + break + raffles = BROWSER.get_elements('#raffles-list .panel-raffle:not(.raffle-entered)') + raffle_list = [] + for element in raffles: + link_element = element.find_element(By.CSS_SELECTOR, 'a') + relative_url = link_element.get_attribute('href').replace(BASE_URL, '').replace(RAFFLE_URL, '') + if relative_url: + raffle_list.append(relative_url) + print(colored('There are ' + str(len(raffle_list)) + ' raffles to enter for ' + USERNAME + '...', 'blue')) + check_notifications() + return raffle_list + +def enter_raffle(raffle): + global BROWSER + BROWSER.open(BASE_URL + RAFFLE_URL + raffle) + result = BROWSER.click_element('button.btn-lg:not(#raffle-enter)') + if result: + if BROWSER.find_element('.raffle-entered-msg', True): + print(colored('Succesfully entered ' + BROWSER.get_element('title').text[:-19] + ' (' + raffle + ')!', 'green')) + time.sleep(5) + else: + print(colored('Couldn\'t enter ' + BROWSER.get_element('title').text[:-19] + ' (' + raffle + '), check the browser instance for Captcha!', 'red')) + input("Press Enter to continue...") + return result + +def enter_raffles(): + raffles = unentered_raffles() + for raffle in raffles: + enter_raffle(raffle) + +load_arguments() +start_browser() +set_cookies() +enter_raffles() +close_browser() \ No newline at end of file