class Logout: def __init__(self, driver): self.driver = driver self.utils = Utils(driver) def logout(self): logged_in = Login(self.driver).logged_in if not logged_in: self.utils.quit() self.driver.get('https://twitter.com/logout') try: confirm_logout_btn = WebDriverWait(self.driver, 3).until( EC.presence_of_element_located( (By.XPATH, '//div[@data-testid="confirmationSheetConfirm"]'))) except NoSuchElementException: self.utils.handle_error( "Logout: confirm logout button xpath outdated") else: self.utils.click_js(confirm_logout_btn) self.utils.quit()
class Followers: def __init__(self, driver): self.driver = driver self.utils = Utils(driver) def __find_followable_people_element(self): tries = 0 while True: tries += 1 try: follow_element = WebDriverWait(self.driver, 2).until(EC.presence_of_element_located((By.XPATH, '//div[contains(@style,"position: absolute;") and .//div[contains(@data-testid, "-follow")]]'))) except Exception as error: if tries > 2: self.utils.handle_error(error) self.utils.scroll_to_end() continue else: return follow_element def __find_username_and_follow_btn(self, follow_element): try: username = follow_element.find_element_by_xpath('.//div[contains(@class, "r-1re7ezh r-18u37iz")]/span').text follow_btn = follow_element.find_element_by_xpath('.//div[contains(@data-testid, "-follow")]') except: self.utils.handle_error("Followers: username or follow_btn xpath outdated") return (username, follow_btn) def __handle_if_error_occured(self, username, last_followed_user): if username == last_followed_user: try: error = WebDriverWait(self.driver, 2).until(EC.presence_of_element_located((By.XPATH, '//div[@data-testid="toast"]//div[contains(@class, "r-16dba41")]//span'))).text except NoSuchElementException: error = "Followers: Xpath for error text of followers is outdated" except: error = "Followers: Unexpected error" self.utils.handle_error(error) def __wait_before_next_follow(self): delay = round(random.uniform(2, 4), 3) print(f"Waiting {delay} seconds before next follow") time.sleep(delay) def follow(self, username_or_query, is_username=True, limit=400): if is_username: self.utils.navigate(TwitterUrls.get_link_of_user_followers(username_or_query)) else: self.utils.navigate(TwitterUrls.get_twitter_users_link(username_or_query)) current_iteration = 1 last_followed_user = None while current_iteration <= limit: current_iteration += 1 follow_element = self.__find_followable_people_element() username, follow_btn = self.__find_username_and_follow_btn(follow_element) self.__handle_if_error_occured(username, last_followed_user) self.utils.click_js(follow_btn) print(f"Just followed {username}") last_followed_user = username self.__wait_before_next_follow()
class Home: def __init__(self, driver, username): self.driver = driver self.utils = Utils(driver) self.username = username def __find_post(self): tries = 0 while True: tries += 1 try: post = WebDriverWait(self.driver, 5).until( EC.presence_of_element_located(( By.XPATH, f'//div[ .//div[@data-testid="like"] and contains(@style, "position: absolute") and .//div[ contains( @class, "css-bfa6kz r-1re7ezh")]//span[text() != "{self.username}" ] ]' ))) except Exception as error: if (tries > 2): playsound('./alert_sound.mp3') print(error) if input("Do you want to quitr? y/n").lower() == 'n': tries = 0 continue self.utils.quit() self.utils.scroll_to_end() continue else: return post def __find_required_elements(self, post): try: username = post.find_element_by_xpath( './/div[ contains( @class, "css-bfa6kz r-1re7ezh")]//span' ).text like_btn = post.find_element_by_xpath( './/div[@data-testid="like"]') reply_btn = post.find_element_by_xpath( './/div[@data-testid="reply"]') except: self.utils.handle_error( "Home: username, likebtn or reply btn xpath outdated") return (username, like_btn, reply_btn) def __reply(self, reply_btn, comment): self.utils.click_js(reply_btn) try: reply_input = self.driver.find_element_by_xpath( '(//div[@data-testid="tweetTextarea_0"])[1]') except: self.utils.handle_error("Home: Reply input field xpath outdated") else: reply_input.send_keys(comment, Keys.CONTROL + Keys.ENTER) def __get_comment(self): comments = [ f"Nice post", f"Awesome work", f"Impressive work", f"Coool" ] return comments[random.randint(0, len(comments) - 1)] def __handle_like_error(self, like_btn): print(like_btn.get_attribute('data-testid')) if like_btn.get_attribute('data-testid') != 'unlike': try: error = WebDriverWait(self.driver, 3).until( EC.presence_of_element_located( (By.XPATH, '//div[@data-testid="toast" and @role="alert"]//span' ))).text except NoSuchElementException: error = """Home: Like error occured...\nPossible Reasons:\n1: Slow internet\n2: Xpath for error text of like is outdated OR error text is not displayed by twitter""" except: error = 'Home: Unexpected error' self.utils.handle_error(error) def like_and_comment(self, like_only=True, limit=1000): self.utils.navigate(TwitterUrls.twitter_home_url) current_iteration = 1 while current_iteration <= limit: post = self.__find_post() username, like_btn, reply_btn = self.__find_required_elements(post) print(":" * 20 + f"POST OF user {username} found" + ":" * 20) self.utils.click_js(like_btn) print("-->post liked") time.sleep(random.uniform(.5, .8)) self.__handle_like_error(like_btn) if not like_only: self.__reply(reply_btn, self.__get_comment()) print("-->replied to the post") delay = random.uniform(2, 4) print(f"Waiting {delay} seconds.") time.sleep(delay)