From 5c111631804929f3e020ec3248863f5033b424e5 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Fri, 24 May 2019 21:02:52 -0400 Subject: [PATCH 01/12] Integrate changes that allow selecting year --- deletefb/deletefb.py | 14 ++++++++++++-- deletefb/tools/login.py | 2 -- deletefb/tools/wall.py | 10 +++++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index b6f3715..d3d3ddb 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -53,6 +53,15 @@ def run_delete(): help="Run browser in headless mode (no gui)" ) + parser.add_argument( + "-Y", + "--year", + required=False, + dest="year", + type=str, + help="The year(s) you want posts deleted." + ) + args = parser.parse_args() args_user_password = args.password or getpass.getpass('Enter your password: ') @@ -60,12 +69,13 @@ def run_delete(): driver = login( user_email_address=args.email, user_password=args_user_password, - user_profile_url=args.profile_url, is_headless=args.is_headless, two_factor_token=args.two_factor_token ) - wall.delete_posts(driver) + wall.delete_posts(driver, + args.profile_url, + year=args.year) if __name__ == "__main__": run_delete() diff --git a/deletefb/tools/login.py b/deletefb/tools/login.py index 38aa5bf..012253d 100644 --- a/deletefb/tools/login.py +++ b/deletefb/tools/login.py @@ -5,7 +5,6 @@ from seleniumrequests import Chrome def login(user_email_address, user_password, - user_profile_url, is_headless, two_factor_token): """ @@ -66,5 +65,4 @@ def login(user_email_address, time.sleep(20) print("Continuing execution") - driver.get(user_profile_url) return driver diff --git a/deletefb/tools/wall.py b/deletefb/tools/wall.py index 3005dd1..0017a4c 100644 --- a/deletefb/tools/wall.py +++ b/deletefb/tools/wall.py @@ -5,10 +5,18 @@ from .common import SELENIUM_EXCEPTIONS MAX_POSTS = 5000 -def delete_posts(driver): +def delete_posts(driver, + user_profile_url, + year=None): """ Deletes or hides all posts from the wall """ + + if not year is None: + user_profile_url = "{0}/timeline?year={1}".format(user_profile_url, year) + + driver.get(user_profile_url) + for _ in range(MAX_POSTS): post_button_sel = "_4xev" From d0be69bbbb6c0249d6124c5a27aad04e6d7476a3 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Fri, 24 May 2019 21:32:51 -0400 Subject: [PATCH 02/12] (Hopefully) less buggy 2FA --- deletefb/tools/login.py | 48 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/deletefb/tools/login.py b/deletefb/tools/login.py index 012253d..ce0f424 100644 --- a/deletefb/tools/login.py +++ b/deletefb/tools/login.py @@ -2,6 +2,7 @@ import time from selenium.webdriver.chrome.options import Options from seleniumrequests import Chrome +from selenium.common.exceptions import NoSuchElementException def login(user_email_address, user_password, @@ -46,23 +47,34 @@ def login(user_email_address, loginelement = driver.find_element_by_id(login) loginelement.click() - if "two-factor authentication" in driver.page_source.lower(): - if two_factor_token: - - 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() - else: - # Allow time to enter 2FA code - print("Pausing to enter 2FA code") - time.sleep(20) - print("Continuing execution") + # 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 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 return driver From 266b5697731660336e6e8e01b2d6d7dc4593a73c Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Fri, 24 May 2019 22:09:25 -0400 Subject: [PATCH 03/12] Add a warning when 2FA is enabled --- deletefb/tools/login.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/deletefb/tools/login.py b/deletefb/tools/login.py index ce0f424..2dea088 100644 --- a/deletefb/tools/login.py +++ b/deletefb/tools/login.py @@ -58,6 +58,12 @@ def login(user_email_address, 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) From db015cc28183545185c2e2ed48ab788e7d48d3b1 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Sat, 25 May 2019 14:07:12 -0400 Subject: [PATCH 04/12] Add new `mode` parameter, work on unliking pages --- deletefb/deletefb.py | 26 +++++++++++++++++++++++--- deletefb/tools/likes.py | 20 ++++++++++++++++++-- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index d3d3ddb..b51915f 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -3,11 +3,25 @@ import argparse import getpass +from sys import exit from deletefb.tools.login import login import deletefb.tools.wall as wall +import deletefb.tools.likes as likes def run_delete(): parser = argparse.ArgumentParser() + + parser.add_argument( + "-M", + "--mode", + required=False, + default="wall", + dest="mode", + type=str, + choices=["wall", "unlike_pages"], + help="The mode you want to run in. Default is `wall' which deletes wall posts" + ) + parser.add_argument( "-E", "--email", @@ -73,9 +87,15 @@ def run_delete(): two_factor_token=args.two_factor_token ) - wall.delete_posts(driver, - args.profile_url, - year=args.year) + if args.mode == "wall": + wall.delete_posts(driver, + args.profile_url, + year=args.year) + elif args.mode == "unlike_pages": + likes.unlike_pages(driver, args.profile_url) + else: + print("Please enter a valid mode") + exit(1) if __name__ == "__main__": run_delete() diff --git a/deletefb/tools/likes.py b/deletefb/tools/likes.py index 80c6b0a..edc1669 100644 --- a/deletefb/tools/likes.py +++ b/deletefb/tools/likes.py @@ -1,8 +1,24 @@ +from time import sleep from selenium.webdriver.common.action_chains import ActionChains from .common import SELENIUM_EXCEPTIONS -def unlike_pages(driver): +def unlike_pages(driver, + user_profile_url): """ Unlike all pages """ - return + + actions = ActionChains(driver) + + driver.get("https://www.facebook.com/pages/?category=liked") + + pages_list = driver.find_element_by_css_selector("#all_liked_pages") + + actions.move_to_element(pages_list) + + unlike_buttons = pages_list.find_elements_by_xpath("//button") + + for button in unlike_buttons: + print(button) + + sleep(1000) From e10f57751dcf0e28c8d7cf83ac1339a444c20a24 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Sun, 26 May 2019 12:42:24 -0400 Subject: [PATCH 05/12] Updates to unlikes (not quite working yet) --- deletefb/tools/common.py | 29 +++++++++++++++++++++++++++++ deletefb/tools/likes.py | 28 ++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/deletefb/tools/common.py b/deletefb/tools/common.py index 92405c4..0bf3df1 100644 --- a/deletefb/tools/common.py +++ b/deletefb/tools/common.py @@ -1,3 +1,32 @@ from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException +from time import sleep +from json import dumps +from os.path import abspath, relpath, split SELENIUM_EXCEPTIONS = (NoSuchElementException, StaleElementReferenceException) + +def try_move(actions, el): + for _ in range(10): + try: + actions.move_to_element(el).perform() + except StaleElementReferenceException: + sleep(5) + continue + + +def archiver(category): + """ + category: the category of logs you want to log + return values: (log_file_handle, archiver) + + call archiver like archive("some content") + """ + log_path = abspath(relpath(split(category)[-1], ".")) + + log_file = open(log_path, mode="wt", buffering=1) + + def log(content): + structured_content = {"category" : category, "content" : content} + log_file.write("{0}\n".format(dumps(structured_content))) + + return (log_file, log) diff --git a/deletefb/tools/likes.py b/deletefb/tools/likes.py index edc1669..ed01fff 100644 --- a/deletefb/tools/likes.py +++ b/deletefb/tools/likes.py @@ -1,6 +1,9 @@ from time import sleep +from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains -from .common import SELENIUM_EXCEPTIONS +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from .common import SELENIUM_EXCEPTIONS, archiver def unlike_pages(driver, user_profile_url): @@ -8,17 +11,34 @@ def unlike_pages(driver, Unlike all pages """ + like_log, archive_likes = archiver("likes") + actions = ActionChains(driver) driver.get("https://www.facebook.com/pages/?category=liked") - pages_list = driver.find_element_by_css_selector("#all_liked_pages") + wait = WebDriverWait(driver, 20) - actions.move_to_element(pages_list) + wait.until( + EC.presence_of_element_located((By.XPATH, "//div[text()='Liked']")) + ) + sleep(10) + + pages_list = driver.find_element_by_css_selector("#all_liked_pages") + actions.move_to_element(pages_list).perform() unlike_buttons = pages_list.find_elements_by_xpath("//button") for button in unlike_buttons: + try: + actions.move_to_element(button).perform() + page_name = button.find_element_by_xpath("./../..").text.split("\n")[0] + archive_likes(page_name) + + except SELENIUM_EXCEPTIONS as e: + print(e) + continue print(button) - sleep(1000) + # Explicitly close the log file when we're done with it + like_log.close() From fddd373d142a36f0161406b7975fb920632bf88f Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Sun, 26 May 2019 15:08:32 -0400 Subject: [PATCH 06/12] Bug the user if they do not have chromedriver installed --- deletefb/tools/common.py | 6 ++++++ deletefb/tools/login.py | 12 +++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/deletefb/tools/common.py b/deletefb/tools/common.py index 0bf3df1..4b6cbea 100644 --- a/deletefb/tools/common.py +++ b/deletefb/tools/common.py @@ -30,3 +30,9 @@ def archiver(category): log_file.write("{0}\n".format(dumps(structured_content))) return (log_file, log) + + +no_chrome_driver = """ +You need to 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 2dea088..0a1ddd7 100644 --- a/deletefb/tools/login.py +++ b/deletefb/tools/login.py @@ -1,8 +1,10 @@ import time +from sys import stderr, exit from selenium.webdriver.chrome.options import Options from seleniumrequests import Chrome from selenium.common.exceptions import NoSuchElementException +from .common import no_chrome_driver def login(user_email_address, user_password, @@ -28,7 +30,15 @@ def login(user_email_address, chrome_options.add_argument('--disable-gpu') chrome_options.add_argument('log-level=2') - driver = Chrome(options=chrome_options) + try: + driver = Chrome(options=chrome_options) + except Exception as e: + # The user does not have chromedriver installed + # Tell them to install it + stderr.write(str(e)) + stderr.write(no_chrome_driver) + exit(1) + driver.implicitly_wait(10) driver.get("https://facebook.com") From a26fcf42f3e6a4407c864088848d33341b9e74d0 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Sun, 26 May 2019 16:41:31 -0400 Subject: [PATCH 07/12] Unliking pages working --- deletefb/tools/common.py | 8 +++-- deletefb/tools/likes.py | 66 ++++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/deletefb/tools/common.py b/deletefb/tools/common.py index 4b6cbea..29d9341 100644 --- a/deletefb/tools/common.py +++ b/deletefb/tools/common.py @@ -1,9 +1,13 @@ -from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException +from selenium.common.exceptions import (NoSuchElementException, + StaleElementReferenceException, + TimeoutException) from time import sleep from json import dumps from os.path import abspath, relpath, split -SELENIUM_EXCEPTIONS = (NoSuchElementException, StaleElementReferenceException) +SELENIUM_EXCEPTIONS = (NoSuchElementException, + StaleElementReferenceException, + TimeoutException) def try_move(actions, el): for _ in range(10): diff --git a/deletefb/tools/likes.py b/deletefb/tools/likes.py index ed01fff..e74ec7a 100644 --- a/deletefb/tools/likes.py +++ b/deletefb/tools/likes.py @@ -1,10 +1,28 @@ -from time import sleep from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from .common import SELENIUM_EXCEPTIONS, archiver +def load_likes(driver): + """ + Loads the page that lists all pages you like + """ + driver.get("https://www.facebook.com/pages/?category=liked") + + wait = WebDriverWait(driver, 20) + + try: + wait.until( + EC.presence_of_element_located((By.XPATH, "//button/div/div[text()='Liked']")) + ) + + wait.until( + EC.presence_of_element_located((By.XPATH, "//button/div/i[@aria-hidden=\"true\"]")) + ) + except SELENIUM_EXCEPTIONS: + return + def unlike_pages(driver, user_profile_url): """ @@ -15,30 +33,40 @@ def unlike_pages(driver, actions = ActionChains(driver) - driver.get("https://www.facebook.com/pages/?category=liked") + load_likes(driver) - wait = WebDriverWait(driver, 20) + pages_list = driver.find_element_by_css_selector("#all_liked_pages") - wait.until( - EC.presence_of_element_located((By.XPATH, "//div[text()='Liked']")) - ) + actions.move_to_element(pages_list).perform() - sleep(10) + unlike_buttons = pages_list.find_elements_by_xpath("//button/div/div[text()='Liked']/../..") - pages_list = driver.find_element_by_css_selector("#all_liked_pages") - actions.move_to_element(pages_list).perform() - unlike_buttons = pages_list.find_elements_by_xpath("//button") + while unlike_buttons: + for button in unlike_buttons: + try: + if "Liked" in button.text: + page_name = button.find_element_by_xpath("./../..").text.split("\n")[0] + + print("Trying to unlike {0}".format(page_name)) + + driver.execute_script("arguments[0].click();", button) + + archive_likes(page_name) + + print("{0} was unliked".format(page_name)) + + except SELENIUM_EXCEPTIONS as e: + continue - for button in unlike_buttons: + load_likes(driver) try: - actions.move_to_element(button).perform() - page_name = button.find_element_by_xpath("./../..").text.split("\n")[0] - archive_likes(page_name) - - except SELENIUM_EXCEPTIONS as e: - print(e) - continue - print(button) + pages_list = driver.find_element_by_css_selector("#all_liked_pages") + actions.move_to_element(pages_list).perform() + unlike_buttons = pages_list.find_elements_by_xpath("//button") + if not unlike_buttons: + break + except SELENIUM_EXCEPTIONS: + break # Explicitly close the log file when we're done with it like_log.close() From 6bfd72912539ef7298c55d807de40fe2e9127c98 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Sun, 26 May 2019 16:45:02 -0400 Subject: [PATCH 08/12] Remove unnecessary parameter --- deletefb/deletefb.py | 2 +- deletefb/tools/likes.py | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index b51915f..4507c68 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -92,7 +92,7 @@ def run_delete(): args.profile_url, year=args.year) elif args.mode == "unlike_pages": - likes.unlike_pages(driver, args.profile_url) + likes.unlike_pages(driver) else: print("Please enter a valid mode") exit(1) diff --git a/deletefb/tools/likes.py b/deletefb/tools/likes.py index e74ec7a..6914145 100644 --- a/deletefb/tools/likes.py +++ b/deletefb/tools/likes.py @@ -23,8 +23,7 @@ def load_likes(driver): except SELENIUM_EXCEPTIONS: return -def unlike_pages(driver, - user_profile_url): +def unlike_pages(driver): """ Unlike all pages """ @@ -47,8 +46,6 @@ def unlike_pages(driver, if "Liked" in button.text: page_name = button.find_element_by_xpath("./../..").text.split("\n")[0] - print("Trying to unlike {0}".format(page_name)) - driver.execute_script("arguments[0].click();", button) archive_likes(page_name) From 9bb624eaa5d89c614b6a79753a2abbe4fab0a0a3 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Sun, 26 May 2019 16:51:26 -0400 Subject: [PATCH 09/12] Guard against invalid combos of options --- deletefb/deletefb.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index 4507c68..da96208 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -78,6 +78,9 @@ def run_delete(): args = parser.parse_args() + if args.year and args.mode != "wall": + parser.error("The --year option is only supported in wall mode") + args_user_password = args.password or getpass.getpass('Enter your password: ') driver = login( From 99a30df3de327ec44672b704c0e992c0f614db11 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Mon, 27 May 2019 01:52:25 -0400 Subject: [PATCH 10/12] Remove stray import --- deletefb/deletefb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index 72d223a..0e91240 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -4,7 +4,6 @@ import argparse import getpass from sys import exit -from deletefb.tools.login import login from .tools.login import login from .tools.wall import delete_posts from .tools.likes import unlike_pages From 643929d3dd96048ef3e15d89d124f1f4293aa3a0 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Tue, 28 May 2019 01:21:51 -0400 Subject: [PATCH 11/12] Archive wall posts, include timestamp --- deletefb/tools/common.py | 11 ++++++++--- deletefb/tools/wall.py | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/deletefb/tools/common.py b/deletefb/tools/common.py index 29d9341..4b95ea1 100644 --- a/deletefb/tools/common.py +++ b/deletefb/tools/common.py @@ -25,12 +25,17 @@ def archiver(category): call archiver like archive("some content") """ - log_path = abspath(relpath(split(category)[-1], ".")) + log_path = "{0}.log".format(abspath(relpath(split(category)[-1], "."))) log_file = open(log_path, mode="wt", buffering=1) - def log(content): - structured_content = {"category" : category, "content" : content} + def log(content, timestamp=False): + structured_content = { + "category" : category, + "content" : content, + "timestamp" : timestamp + } + log_file.write("{0}\n".format(dumps(structured_content))) return (log_file, log) diff --git a/deletefb/tools/wall.py b/deletefb/tools/wall.py index 0017a4c..a318c54 100644 --- a/deletefb/tools/wall.py +++ b/deletefb/tools/wall.py @@ -1,9 +1,10 @@ import time from selenium.webdriver.common.action_chains import ActionChains -from .common import SELENIUM_EXCEPTIONS +from .common import SELENIUM_EXCEPTIONS, archiver -MAX_POSTS = 5000 +# Used as a threshold to avoid running forever +MAX_POSTS = 15000 def delete_posts(driver, user_profile_url, @@ -17,12 +18,23 @@ def delete_posts(driver, driver.get(user_profile_url) + wall_log, archive_wall_post = archiver("wall") + for _ in range(MAX_POSTS): post_button_sel = "_4xev" + post_content_sel = "_5_jv" + + post_timestamp_sel = "timestamp" while True: try: timeline_element = driver.find_element_by_class_name(post_button_sel) + + post_content_element = driver.find_element_by_class_name(post_content_sel) + post_content_ts = driver.find_element_by_class_name(post_timestamp_sel) + + archive_wall_post(post_content_element.text, timestamp=post_content_ts.text) + actions = ActionChains(driver) actions.move_to_element(timeline_element).click().perform() From 056fd75aae9983285d27bfd3d5449c311d566ff7 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Tue, 28 May 2019 01:46:01 -0400 Subject: [PATCH 12/12] Add feature to disable logging --- README.md | 13 +++++++++++++ deletefb/deletefb.py | 12 ++++++++++++ deletefb/tools/common.py | 3 +++ 3 files changed, 28 insertions(+) diff --git a/README.md b/README.md index aa9e64a..b6eaa6b 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,24 @@ requirements.txt`, then you can just run `python -m deletefb.deletefb.py` in the * It is recommended that you disable Two-Factor Authentication tempoprarily while you are running the script, in order to get the best experience. +* If you run into issues with Facebook complaining about your browser, + currently the only workaround is to manually click through them. + * If you do have 2-Factor Auth configured then the script will pause for 20 seconds to allow you to enter your code and log in. * You may also pass in a code by using the `-F` argument, e.g. `-F 111111`. +## Delete by year +* The tool supports passing the `--year` flag in order to delete wall posts by + year. It is incompatible with any mode other than `wall`. + +## Archival +* The tool will archive everything being deleted by default in `.log` files. + Currently they are simply stored as JSON objects for each line in the log. It + will archive the content, and a timestamp if it is available. You may disable + this feature by using `--no-archive`. + ## Headless mode * The tool supports running Chrome in headless mode with the `--headless` option, which may be preferable if you plan on running it in the background. diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index 0e91240..23e275d 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -4,6 +4,7 @@ import argparse import getpass from sys import exit +from os import environ from .tools.login import login from .tools.wall import delete_posts from .tools.likes import unlike_pages @@ -67,6 +68,14 @@ def run_delete(): help="Run browser in headless mode (no gui)" ) + parser.add_argument( + "--no-archive", + action="store_true", + dest="archive_off", + default=True, + help="Turn off archiving (on by default)" + ) + parser.add_argument( "-Y", "--year", @@ -78,6 +87,9 @@ def run_delete(): args = parser.parse_args() + if args.archive_off: + environ["DELETEFB_ARCHIVE"] = "false" if args.archive_off else "true" + if args.year and args.mode != "wall": parser.error("The --year option is only supported in wall mode") diff --git a/deletefb/tools/common.py b/deletefb/tools/common.py index 4b95ea1..9dc9e38 100644 --- a/deletefb/tools/common.py +++ b/deletefb/tools/common.py @@ -4,6 +4,7 @@ from selenium.common.exceptions import (NoSuchElementException, from time import sleep from json import dumps from os.path import abspath, relpath, split +from os import environ SELENIUM_EXCEPTIONS = (NoSuchElementException, StaleElementReferenceException, @@ -30,6 +31,8 @@ def archiver(category): log_file = open(log_path, mode="wt", buffering=1) def log(content, timestamp=False): + if environ.get("DELETEFB_ARCHIVE", "true") == "false": + return structured_content = { "category" : category, "content" : content,