diff --git a/deletefb/exceptions.py b/deletefb/exceptions.py new file mode 100644 index 0000000..6f22085 --- /dev/null +++ b/deletefb/exceptions.py @@ -0,0 +1,2 @@ +class UnknownOSException(Exception): + pass diff --git a/deletefb/tools/chrome_driver.py b/deletefb/tools/chrome_driver.py new file mode 100644 index 0000000..d6549ba --- /dev/null +++ b/deletefb/tools/chrome_driver.py @@ -0,0 +1,117 @@ +import re +import zipfile +import os, sys, stat, platform +from urllib.request import urlretrieve +from collections import namedtuple + +from clint.textui import puts, colored +import progressbar + +from selenium import webdriver + +from .common import NO_CHROME_DRIVER +from ..exceptions import UnknownOSException + + +_ = namedtuple('WebDrivers', 'mac linux windows') +drivers = ['https://chromedriver.storage.googleapis.com/78.0.3904.70/chromedriver_mac64.zip', + 'https://chromedriver.storage.googleapis.com/78.0.3904.70/chromedriver_linux64.zip', + 'https://chromedriver.storage.googleapis.com/78.0.3904.70/chromedriver_win32.zip' + ] +WebDriver = _(drivers[0], drivers[1], drivers[2]) + + +def extract_zip(filename): + """ + Uses zipfile package to extract a single zipfile + :param filename: + :return: new filename + """ + try: + _file = zipfile.ZipFile(filename, 'r') + except FileNotFoundError: + puts(colored.red(f"{filename} Does not exist")) + sys.exit(1) + + # Save the name of the new file + new_file_name = _file.namelist()[0] + + # Extract the file and make it executable + _file.extractall() + + driver_stat = os.stat(new_file_name) + os.chmod(new_file_name, driver_stat.st_mode | stat.S_IEXEC) + + _file.close() + os.remove(filename) + return new_file_name + + +def setup_selenium(driver_path, options): + # Configures selenium to use a custom path + return webdriver.Chrome(executable_path=driver_path, options=options) + + +def get_webdriver(): + """ + Ensure a webdriver is available + If Not, Download it. + """ + cwd = os.listdir(os.getcwd()) + webdriver_regex = re.compile('chromedriver') + web_driver = list(filter(webdriver_regex.match, cwd)) + + if web_driver: + # check if a extracted copy already exists + if not os.path.isfile('chromedriver'): + # Extract file + extract_zip(web_driver[0]) + + return "{0}/chromedriver".format(os.getcwd()) + + else: + # Download it according to the current machine + + os_platform = platform.system() + if os_platform == 'Darwin': + chrome_webdriver = WebDriver.mac + elif os_platform == 'Linux': + chrome_webdriver = WebDriver.linux + elif os_platform == 'Windows': + chrome_webdriver = WebDriver.windows + else: + raise UnknownOSException("Unknown Operating system platform") + + global total_size + + def show_progress(*res): + global total_size + pbar = None + downloaded = 0 + block_num, block_size, total_size = res + + if not pbar: + pbar = progressbar.ProgressBar(maxval=total_size) + pbar.start() + downloaded += block_num * block_size + + if downloaded < total_size: + pbar.update(downloaded) + else: + pbar.finish() + + puts(colored.yellow("Downloading Chrome Webdriver")) + file_name = chrome_webdriver.split('/')[-1] + response = urlretrieve(chrome_webdriver, file_name, show_progress) + + if int(response[1].get('Content-Length')) == total_size: + puts(colored.green(f"DONE!")) + + return "{0}/{1}".format(os.getcwd(), extract_zip(file_name)) + + else: + puts(colored.red("An error Occurred While trying to download the driver.")) + # remove the downloaded file and exit + os.remove(file_name) + sys.stderr.write(NO_CHROME_DRIVER) + sys.exit(1) diff --git a/deletefb/tools/common.py b/deletefb/tools/common.py index de0d679..bb24989 100644 --- a/deletefb/tools/common.py +++ b/deletefb/tools/common.py @@ -5,15 +5,13 @@ from selenium.webdriver.common.by import By from selenium.common.exceptions import ( NoSuchElementException, StaleElementReferenceException, - TimeoutException, - JavascriptException + TimeoutException ) import json import logging import logging.config import os -import pendulum SELENIUM_EXCEPTIONS = ( NoSuchElementException, @@ -21,12 +19,14 @@ SELENIUM_EXCEPTIONS = ( TimeoutException ) + def click_button(driver, el): """ Click a button using Javascript """ driver.execute_script("arguments[0].click();", el) + def scroll_to(driver, el): """ Scroll an element into view, using JS @@ -36,6 +36,7 @@ def scroll_to(driver, el): except SELENIUM_EXCEPTIONS: return + def logger(name): """ Args: @@ -66,7 +67,8 @@ def wait_xpath(driver, expr): except SELENIUM_EXCEPTIONS: return + NO_CHROME_DRIVER = """ -You need to install the chromedriver for Selenium\n +You need to manually install the chromedriver for Selenium\n Please see this link https://github.com/weskerfoot/DeleteFB#how-to-use-it\n """ diff --git a/deletefb/tools/login.py b/deletefb/tools/login.py index 73fe08b..dd3ce05 100644 --- a/deletefb/tools/login.py +++ b/deletefb/tools/login.py @@ -1,11 +1,11 @@ -from .common import NO_CHROME_DRIVER from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.chrome.options import Options -from seleniumrequests import Chrome -import sys import time +from .chrome_driver import get_webdriver, setup_selenium + + def login(user_email_address, user_password, is_headless, @@ -37,15 +37,8 @@ def login(user_email_address, chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('log-level=2') - try: - driver = Chrome(options=chrome_options) - except Exception as e: - # The user does not have chromedriver installed - # Tell them to install it - sys.stderr.write(str(e)) - sys.stderr.write(NO_CHROME_DRIVER) - sys.exit(1) - + driver_path = get_webdriver() + driver = setup_selenium(driver_path, chrome_options) driver.implicitly_wait(10) driver.get("https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110") diff --git a/requirements.txt b/requirements.txt index 9b578c6..25df0c8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,11 +4,13 @@ bleach==3.1.0 cattrs==0.9.0 certifi==2018.11.29 chardet==3.0.4 +clint==0.5.1 docutils==0.14 idna==2.8 lxml==4.4.0 pendulum==2.0.5 pkginfo==1.5.0.1 +progressbar==2.5 pybloom-live==3.0.0 Pygments==2.4.2 python-dateutil==2.8.0 diff --git a/setup.py b/setup.py index b83d23b..49e119d 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,9 @@ setuptools.setup( "attrs", "cattrs", "lxml", - "pendulum" + "pendulum", + "clint", + "progressbar" ], classifiers= [ "Programming Language :: Python :: 3",