Browse Source

Fix chromedriver (#120)

* add appdirs for managing user data

* use cache_dir for downloading chromedriver

* cleanly shut down selenium when an exception happens
pull/121/head
Wesley Kerfoot 4 years ago
committed by GitHub
parent
commit
cc5a5b8b32
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      deletefb/deletefb.py
  2. 10
      deletefb/quit_driver.py
  3. 29
      deletefb/tools/chrome_driver.py
  4. 114
      deletefb/tools/login.py
  5. 6
      deletefb/version.py
  6. 2
      requirements.txt
  7. 3
      setup.py

37
deletefb/deletefb.py

@ -6,6 +6,7 @@ from .tools.login import login
from .tools.wall import delete_posts
from .tools.conversations import traverse_conversations
from .tools.comments import delete_comments
from .quit_driver import quit_driver_and_reap_children
import argparse
import getpass
@ -116,22 +117,26 @@ def run_delete():
chrome_binary_path=args.chromebin
)
if args.mode == "wall":
delete_posts(
driver,
args.profile_url,
year=args.year
)
elif args.mode == "unlike_pages":
unlike_pages(driver, args.profile_url)
elif args.mode == "conversations":
traverse_conversations(driver, year=args.year)
else:
print("Please enter a valid mode")
sys.exit(1)
try:
if args.mode == "wall":
delete_posts(
driver,
args.profile_url,
year=args.year
)
elif args.mode == "unlike_pages":
unlike_pages(driver, args.profile_url)
elif args.mode == "conversations":
traverse_conversations(driver, year=args.year)
else:
print("Please enter a valid mode")
sys.exit(1)
except:
if driver:
quit_driver_and_reap_children(driver)
if __name__ == "__main__":
run_delete()

10
deletefb/quit_driver.py

@ -0,0 +1,10 @@
import os
def quit_driver_and_reap_children(driver):
driver.quit()
try:
pid = True
while pid:
pid = os.waitpid(-1, os.WNOHANG)
except ChildProcessError:
pass

29
deletefb/tools/chrome_driver.py

@ -5,12 +5,22 @@ from selenium import webdriver
from shutil import which
from subprocess import check_output
from urllib.request import urlretrieve
from appdirs import AppDirs
from ..version import version
import os, sys, stat, platform
import progressbar
import re
import zipfile
import requests
import pathlib
cache_dir = AppDirs("DeleteFB", version=version).user_cache_dir
try:
pathlib.Path(cache_dir).mkdir(parents=True, exist_ok=True)
except FileExistsError:
pass
def extract_zip(filename):
"""
@ -25,10 +35,10 @@ def extract_zip(filename):
sys.exit(1)
# Save the name of the new file
new_file_name = _file.namelist()[0]
new_file_name = f"{cache_dir}/{_file.namelist()[0]}"
# Extract the file and make it executable
_file.extractall()
_file.extractall(path=cache_dir)
driver_stat = os.stat(new_file_name)
os.chmod(new_file_name, driver_stat.st_mode | stat.S_IEXEC)
@ -55,7 +65,6 @@ def get_chrome_version(chrome_binary_path=None):
driver_locations = [which(loc) for loc in ["google-chrome", "google-chrome-stable", "chromium", "chrome.exe"]]
for location in driver_locations:
print(location)
if location:
return parse_version(check_output([location, "--version"]).strip())
return None
@ -94,17 +103,19 @@ def get_webdriver(chrome_binary_path):
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))
web_driver = list(filter(webdriver_regex.match, cache_dir))
if web_driver:
# check if a extracted copy already exists
if not os.path.isfile('chromedriver'):
if not os.path.isfile(f"{cache_dir}/chromedriver"):
# Extract file
extract_zip(web_driver[0])
return "{0}/chromedriver".format(os.getcwd())
return "{0}/chromedriver".format(cache_dir)
else:
# Download it according to the current machine
@ -133,13 +144,13 @@ def get_webdriver(chrome_binary_path):
pbar.finish()
puts(colored.yellow("Downloading Chrome Webdriver"))
file_name = chrome_webdriver.split('/')[-1]
file_name = f"{cache_dir}/{chrome_webdriver.split('/')[-1]}"
response = urlretrieve(chrome_webdriver, file_name, show_progress)
if int(response[1].get("Content-Length")) == total_size:
puts(colored.green("Completed downloading the Chrome Driver."))
return "{0}/{1}".format(os.getcwd(), extract_zip(file_name))
return extract_zip(file_name)
else:
puts(colored.red("An error Occurred While trying to download the driver."))

114
deletefb/tools/login.py

@ -1,6 +1,7 @@
from .chrome_driver import get_webdriver, setup_selenium
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.chrome.options import Options
from ..quit_driver import quit_driver_and_reap_children
import time
@ -42,59 +43,62 @@ def login(user_email_address,
driver_path = get_webdriver(chrome_binary_path)
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")
email = "email"
password = "pass"
login_button = "loginbutton"
approvals_code = "approvals_code"
driver.find_element_by_name(email).send_keys(user_email_address)
driver.find_element_by_name(password).send_keys(user_password)
driver.find_element_by_id(login_button).click()
# Defaults to no 2fa
has_2fa = False
try:
# If this element exists, we've reached a 2FA page
driver.find_element_by_xpath("//form[@class=\"checkpoint\"]")
driver.find_element_by_xpath("//input[@name=\"approvals_code\"]")
has_2fa = True
except NoSuchElementException:
has_2fa = "two-factor authentication" in driver.page_source.lower() or has_2fa
if has_2fa:
print("""
Two-Factor Auth is enabled.
Please file an issue at https://github.com/weskerfoot/DeleteFB/issues if you run into any problems
""")
if two_factor_token and has_2fa:
twofactorelement = driver.find_element_by_name(approvals_code)
twofactorelement.send_keys(two_factor_token)
# Submits after the code is passed into the form, does not validate 2FA code.
contelement = driver.find_element_by_id("checkpointSubmitButton")
contelement.click()
# Defaults to saving this new browser, this occurs on each new automated login.
save_browser = driver.find_element_by_id("checkpointSubmitButton")
save_browser.click()
elif has_2fa:
# Allow time to enter 2FA code
print("Pausing to enter 2FA code")
time.sleep(35)
print("Continuing execution")
else:
pass
# block until we have reached the main page
# print a message warning the user
while driver.current_url != "https://www.facebook.com/":
print("Execution blocked: Please navigate to https://www.facebook.com to continue")
time.sleep(5)
return driver
driver.implicitly_wait(10)
driver.get("https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110")
email = "email"
password = "pass"
login_button = "loginbutton"
approvals_code = "approvals_code"
driver.find_element_by_name(email).send_keys(user_email_address)
driver.find_element_by_name(password).send_keys(user_password)
driver.find_element_by_id(login_button).click()
# Defaults to no 2fa
has_2fa = False
try:
# If this element exists, we've reached a 2FA page
driver.find_element_by_xpath("//form[@class=\"checkpoint\"]")
driver.find_element_by_xpath("//input[@name=\"approvals_code\"]")
has_2fa = True
except NoSuchElementException:
has_2fa = "two-factor authentication" in driver.page_source.lower() or has_2fa
if has_2fa:
print("""
Two-Factor Auth is enabled.
Please file an issue at https://github.com/weskerfoot/DeleteFB/issues if you run into any problems
""")
if two_factor_token and has_2fa:
twofactorelement = driver.find_element_by_name(approvals_code)
twofactorelement.send_keys(two_factor_token)
# Submits after the code is passed into the form, does not validate 2FA code.
contelement = driver.find_element_by_id("checkpointSubmitButton")
contelement.click()
# Defaults to saving this new browser, this occurs on each new automated login.
save_browser = driver.find_element_by_id("checkpointSubmitButton")
save_browser.click()
elif has_2fa:
# Allow time to enter 2FA code
print("Pausing to enter 2FA code")
time.sleep(35)
print("Continuing execution")
else:
pass
# block until we have reached the main page
# print a message warning the user
while driver.current_url != "https://www.facebook.com/":
print("Execution blocked: Please navigate to https://www.facebook.com to continue")
time.sleep(5)
return driver
except:
quit_driver_and_reap_children(driver)

6
deletefb/version.py

@ -0,0 +1,6 @@
import pkg_resources # part of setuptools
try:
version = pkg_resources.require("delete-facebook-posts")[0].version
except pkg_resources.DistributionNotFound:
version = "source"

2
requirements.txt

@ -1,3 +1,5 @@
appdirs==1.4.3
args==0.1.0
attrs==19.1.0
bitarray==0.9.3
bleach==3.1.1

3
setup.py

@ -29,7 +29,8 @@ setuptools.setup(
"lxml",
"pendulum",
"clint",
"progressbar"
"progressbar",
"appdirs"
],
classifiers= [
"Programming Language :: Python :: 3",

Loading…
Cancel
Save