From 1875b754ab946c575998198b206b3711d70bfc19 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot <378351+weskerfoot@users.noreply.github.com> Date: Mon, 7 Sep 2020 17:09:25 -0400 Subject: [PATCH] Fixes for new facebook site (#129) * make work with the mobile site instead, bypasses changes to new facebook * fix timestamp selection * fix conversations mode --- deletefb/tools/conversations.py | 19 +++++++----- deletefb/tools/wall.py | 51 ++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/deletefb/tools/conversations.py b/deletefb/tools/conversations.py index bcbd089..c21b070 100644 --- a/deletefb/tools/conversations.py +++ b/deletefb/tools/conversations.py @@ -6,6 +6,7 @@ from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import Select from pendulum import now from json import loads +from time import sleep import lxml.html as lxh @@ -29,12 +30,13 @@ def get_conversations(driver): date = None if url and "messages/read" in url: - - date = convo.find_element_by_xpath("../../..//abbr").text - conversation_name = convo.find_element_by_xpath("../../../div/div/header/h3").text.strip() - - assert(conversation_name) - assert(url) + try: + date = convo.find_element_by_xpath("../../..//abbr").text + conversation_name = convo.find_element_by_xpath("../../../div/div/header/h3").text.strip() + assert(conversation_name) + assert(url) + except (SELENIUM_EXCEPTIONS + (AssertionError,)): + continue conversations.append( Conversation( @@ -49,7 +51,10 @@ def get_conversations(driver): find_element_by_xpath("a"). get_attribute("href")) - except SELENIUM_EXCEPTIONS: + print("next_url", next_url) + + except SELENIUM_EXCEPTIONS as e: + print(e) break if not next_url: break diff --git a/deletefb/tools/wall.py b/deletefb/tools/wall.py index 81d1002..8cc4d27 100644 --- a/deletefb/tools/wall.py +++ b/deletefb/tools/wall.py @@ -26,21 +26,39 @@ def delete_posts(driver, driver.get(user_profile_url) - for _ in range(MAX_POSTS): - post_button_sel = "_4xev" + finished = False - post_content_sel = "userContent" - post_timestamp_sel = "timestampContent" + with archiver("wall") as archive_wall_post: + for _ in range(MAX_POSTS): + if finished: + break + post_button_sel = "_4s19" - button_types = ["FeedDeleteOption", "HIDE_FROM_TIMELINE", "UNTAG"] + post_content_sel = "userContent" + post_timestamp_sel = "timestampContent" + + confirmation_button_exp = "//div[contains(@data-sigil, 'undo-content')]//*/a[contains(@href, 'direct_action_execute')]" + + # Cannot return a text node, so it returns the parent. + # Tries to be pretty resilient against DOM re-organizations + timestamp_exp = "//article//*/header//*/div/a[contains(@href, 'story_fbid')]//text()/.." + + button_types = ["Delete post", "Remove Tag", "Hide from timeline"] - with archiver("wall") as archive_wall_post: while True: try: - timeline_element = driver.find_element_by_class_name(post_button_sel) + try: + timeline_element = driver.find_element_by_xpath("//div[@data-sigil='story-popup-causal-init']/a") + except SELENIUM_EXCEPTIONS: + print("Could not find any posts") + finished = True + break - post_content_element = driver.find_element_by_class_name(post_content_sel) - post_content_ts = driver.find_element_by_class_name(post_timestamp_sel) + post_content_element = driver.find_element_by_xpath("//article/div[@class='story_body_container']/div") + post_content_ts = driver.find_element_by_xpath(timestamp_exp) + + if not (post_content_element or post_content_ts): + break # Archive the post archive_wall_post.archive( @@ -53,15 +71,18 @@ def delete_posts(driver, actions = ActionChains(driver) actions.move_to_element(timeline_element).click().perform() - wait_xpath(driver, "//*[@id='feed_post_menu']/..") - - menu = driver.find_element_by_xpath("//*[@id='feed_post_menu']/..") + # Wait until the buttons show up + wait_xpath(driver, "//*[contains(@data-sigil, 'removeStoryButton')]") delete_button = None + # Search for visible buttons in priority order + # Delete -> Untag -> Hide for button_type in button_types: try: - delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"{0}\"]".format(button_type)) + delete_button = driver.find_element_by_xpath("//*[text()='{0}']".format(button_type)) + if not delete_button.is_displayed(): + continue break except SELENIUM_EXCEPTIONS as e: print(e) @@ -72,8 +93,10 @@ def delete_posts(driver, break click_button(driver, delete_button) - confirmation_button = driver.find_element_by_class_name("layerConfirm") + wait_xpath(driver, confirmation_button_exp) + confirmation_button = driver.find_element_by_xpath(confirmation_button_exp) + print(confirmation_button) click_button(driver, confirmation_button) except SELENIUM_EXCEPTIONS as e: