Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

about to crashout over this tweet button , cant get the PR fix to work either . #100

Open
ragnorcap opened this issue Feb 16, 2025 · 3 comments

Comments

@ragnorcap
Copy link

ℹ️ => Fetching songs...

============ OPTIONS ============

  1. YouTube Shorts Automation
  2. Twitter Bot
  3. Affiliate Marketing
  4. Outreach
  5. Quit
    =================================

Select an option: 2
ℹ️ Starting Twitter Bot...
+----+--------------------------------------+----------+-------------------+
| ID | UUID | Nickname | Account Topic |
+----+--------------------------------------+----------+-------------------+
| 1 | 4568db8e-8f05-4238-96d1-f0af9ebaff61 | rtts | music pop culture |
+----+--------------------------------------+----------+-------------------+
❓ Select an account to start: 1

============ OPTIONS ============

  1. Post something
  2. Reply to something
  3. Show all Posts
  4. Setup CRON Job
  5. Quit
    =================================

❓ Select an option: 1
ℹ️ Generating a post...
ℹ️ Length of post: 269
ℹ️ Generating a post...
ℹ️ Length of post: 225
=> Posting to Twitter: 🎶✨ The resurgence of 90s pop i...
Traceback (most recent call last):
File "/Users/acetwotimes/MoneyPrinterV2/src/classes/Twitter.py", line 83, in post
bot.find_element(By.XPATH, "//a[@data-testid='SideNav_NewTweet_Button']").click()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/anaconda3/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 888, in find_element
return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/anaconda3/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 429, in execute
self.error_handler.check_response(response)
File "/usr/local/anaconda3/lib/python3.11/site-packages/selenium/webdriver/remote/errorhandler.py", line 232, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //a[@data-testid='SideNav_NewTweet_Button']; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
Stacktrace:
RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:197:5
NoSuchElementError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:527:5
dom.find/</<@chrome://remote/content/shared/DOM.sys.mjs:136:16

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/acetwotimes/MoneyPrinterV2/src/main.py", line 438, in
main()
File "/Users/acetwotimes/MoneyPrinterV2/src/main.py", line 277, in main
twitter.post()
File "/Users/acetwotimes/MoneyPrinterV2/src/classes/Twitter.py", line 86, in post
bot.find_element(By.XPATH, "//a[@data-testid='SideNav_NewTweet_Button']").click()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/anaconda3/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 888, in find_element
return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/anaconda3/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py", line 429, in execute
self.error_handler.check_response(response)
File "/usr/local/anaconda3/lib/python3.11/site-packages/selenium/webdriver/remote/errorhandler.py", line 232, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //a[@data-testid='SideNav_NewTweet_Button']; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
Stacktrace:
RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:197:5
NoSuchElementError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:527:5
dom.find/</<@chrome://remote/content/shared/DOM.sys.mjs:136:16

##########################################################################

❓ Select an option: 3
+----+----------------------+-------------------------------------------------------------------+
| ID | Date | Content |
+----+----------------------+-------------------------------------------------------------------+
| 1 | 02/16/2025, 03:04:45 | 🎶✨ The resurgence of 90s pop icons in today's music scene is... |
+----+----------------------+-------------------------------------------------------------------+

============ OPTIONS ============

  1. Post something
  2. Reply to something
  3. Show all Posts
  4. Setup CRON Job
  5. Quit
    =================================

❓ Select an option: 1
ℹ️ Generating a post...
ℹ️ Length of post: 208
=> Preparing to post on Twitter: 🎶✨ The resurgence of 90s pop i...
Failed to find the text box element.
Tweet content (printed to terminal):
🎶✨ The resurgence of 90s pop icons in today's music scene is a nostalgic treat for fans! From remixes to surprise collaborations, it's a reminder that great music never truly fades away. #90sPop #MusicRevival

x#########################################################################

so i can generate but not type or find the buttons or boxes, even tried flipping the cod so i can type first...didnt work either . any suggestions? ive been stuck on this part for a imnute, and ive done all the fixes ive found so far including using css selector . i get nada.

twitter.py code

import re
import g4f
import sys
import os
import json
from cache import *
from config import *
from status import *
from constants import *
from typing import List
from datetime import datetime
from termcolor import colored
from selenium_firefox import *
from selenium import webdriver
from selenium.common import exceptions
from selenium.webdriver.common import keys
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

Import joblib for parallel processing

from joblib import Parallel, delayed

class Twitter:
"""
Class for the Bot that grows a Twitter account.
"""
def init(self, account_uuid: str, account_nickname: str, fp_profile_path: str, topic: str) -> None:
"""
Initializes the Twitter Bot.

    Args:
        account_uuid (str): The account UUID
        account_nickname (str): The account nickname
        fp_profile_path (str): The path to the Firefox profile
        topic (str): The topic to generate posts about

    Returns:
        None
    """
    self.account_uuid: str = account_uuid
    self.account_nickname: str = account_nickname
    self.fp_profile_path: str = fp_profile_path
    self.topic: str = topic

    # Initialize the Firefox options
    self.options: Options = Options()

    # Set headless state of browser if enabled
    if get_headless():
        self.options.add_argument("--headless")

    # Set the Firefox profile path
    self.options.set_preference("profile", fp_profile_path)

    # Initialize the Firefox service
    self.service: Service = Service(GeckoDriverManager().install())

    # Initialize the browser
    self.browser: webdriver.Firefox = webdriver.Firefox(service=self.service, options=self.options)

    # Initialize the wait instance
    self.wait: WebDriverWait = WebDriverWait(self.browser, 40)

def post(self, text: str = None) -> None:
    """
    Starts the Twitter Bot.

    Args:
        text (str): The text to post

    Returns:
        None
    """
    bot: webdriver.Firefox = self.browser
    verbose: bool = get_verbose()

    bot.get("https://x.com/compose/post")

    post_content: str = self.generate_post()
    now: datetime = datetime.now()

    # Show a preview of the tweet content
    print(colored(" => Preparing to post on Twitter:", "blue"), post_content[:30] + "...")
    
    # Determine the tweet content (either generated or provided)
    body = post_content if text is None else text

    # Try to find the text box and type the content
    text_box = None
    selectors = [
        (By.CSS_SELECTOR, "div.notranslate.public-DraftEditor-content[role='textbox']"),
        (By.XPATH, "//div[@data-testid='tweetTextarea_0']//div[@role='textbox']")
    ]
    for selector in selectors:
        try:
            text_box = self.wait.until(EC.element_to_be_clickable(selector))
            text_box.click()
            text_box.send_keys(body)
            break
        except exceptions.TimeoutException:
            continue

    # If the text box wasn't found, print error, cache the post, and exit gracefully
    if text_box is None:
        print(colored("Failed to find the text box element.", "red"))
        print(colored("Tweet content (printed to terminal):", "yellow"))
        print(body)
        self.add_post({
            "content": post_content,
            "date": now.strftime("%m/%d/%Y, %H:%M:%S")
        })
        return

    # Try to find the "Post" button and click it
    tweet_button = None
    selectors = [
        (By.XPATH, "//span[contains(@class, 'css-1jxf684') and text()='Post']"),
        (By.XPATH, "//*[text()='Post']")
    ]
    for selector in selectors:
        try:
            tweet_button = self.wait.until(EC.element_to_be_clickable(selector))
            tweet_button.click()
            break
        except exceptions.TimeoutException:
            continue

    # If the tweet button wasn't found, print error, cache the post, and exit gracefully
    if tweet_button is None:
        print(colored("Failed to find the tweet button element.", "red"))
        print(colored("Tweet content (printed to terminal):", "yellow"))
        print(body)
        self.add_post({
            "content": post_content,
            "date": now.strftime("%m/%d/%Y, %H:%M:%S")
        })
        return

    if verbose:
        print(colored(" => Pressed [ENTER] Button on Twitter..", "blue"))
    # Wait for confirmation that the tweet has been posted
    self.wait.until(EC.presence_of_element_located((By.XPATH, "//div[@data-testid='tweetButton']")))

    # Add the post to the cache
    self.add_post({
        "content": post_content,
        "date": now.strftime("%m/%d/%Y, %H:%M:%S")
    })

    success("Posted to Twitter successfully!")

def get_posts(self) -> List[dict]:
    """
    Gets the posts from the cache.

    Returns:
        posts (List[dict]): The posts
    """
    if not os.path.exists(get_twitter_cache_path()):
        # Create the cache file if it doesn't exist
        with open(get_twitter_cache_path(), 'w') as file:
            json.dump({"posts": []}, file, indent=4)

    with open(get_twitter_cache_path(), 'r') as file:
        parsed = json.load(file)

        # Find our account and its posts
        accounts = parsed.get("accounts", [])
        for account in accounts:
            if account["id"] == self.account_uuid:
                posts = account.get("posts", [])
                return posts
    return []

def add_post(self, post: dict) -> None:
    """
    Adds a post to the cache.

    Args:
        post (dict): The post to add

    Returns:
        None
    """
    posts = self.get_posts()
    posts.append(post)

    with open(get_twitter_cache_path(), 'r') as file:
        previous_json = json.load(file)

    # Find our account and append the new post
    accounts = previous_json.get("accounts", [])
    for account in accounts:
        if account["id"] == self.account_uuid:
            account["posts"].append(post)

    # Commit changes to the cache
    with open(get_twitter_cache_path(), "w") as f:
        json.dump(previous_json, f, indent=4)

def generate_post(self) -> str:
    """
    Generates a post for the Twitter account based on the topic.

    Returns:
        post (str): The post
    """
    completion = g4f.ChatCompletion.create(
        model=parse_model(get_model()),
        messages=[
            {
                "role": "user",
                "content": f"Generate a Twitter post about: {self.topic} in {get_twitter_language()}. "
                           "The limit is 2 sentences. Choose a specific sub-topic of the provided topic."
            }
        ]
    )

    if get_verbose():
        info("Generating a post...")

    if completion is None:
        error("Failed to generate a post. Please try again.")
        sys.exit(1)

    # Remove asterisks and quotes from the generated content
    completion = re.sub(r"\*", "", completion).replace("\"", "")

    if get_verbose():
        info(f"Length of post: {len(completion)}")
    # Instead of recursively generating a new post, trim it if it's too long.
    max_length = 260
    if len(completion) > max_length:
        # Optionally, you could trim on a word boundary instead of a strict character limit.
        trimmed = completion[:max_length].rsplit(" ", 1)[0] + "..."
        if get_verbose():
            info(f"Trimmed post to {len(trimmed)} characters.")
        return trimmed

    return completion
@FujiwaraChoki
Copy link
Owner

Brother, for the love of God, reduce the amount of Text I have to read!

@ragnorcap
Copy link
Author

lol my bad, but im having issues finding the element . i can generate but cant find the boxes or buttons .

    try:
        bot.find_element(By.XPATH, "//a[@data-testid='SideNav_NewTweet_Button']").click()
    except exceptions.NoSuchElementException:
        time.sleep(3)
        bot.find_element(By.XPATH, "//a[@data-testid='SideNav_NewTweet_Button']").click()

this doesnt work on my end for some reason, likely somthing im doing , ive tried plenty of other combos, went to read documentation and tried what the one guy put in the PR.

@farukhsk09
Copy link

farukhsk09 commented Feb 18, 2025

is it because the element is addButton ??

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants