Spaces:
Runtime error
Runtime error
| import feedparser | |
| import time | |
| import random | |
| from playwright.sync_api import sync_playwright | |
| import os | |
| X_USERNAME = os.environ.get("X_USERNAME") | |
| X_PASSWORD = os.environ.get("X_PASSWORD") | |
| RSS_FEEDS = [ | |
| "https://feeds.feedburner.com/TechCrunch", | |
| "https://www.theverge.com/rss/index.xml", | |
| "https://hnrss.org/frontpage", | |
| ] | |
| def get_tech_news(): | |
| all_items = [] | |
| for feed_url in RSS_FEEDS: | |
| try: | |
| feed = feedparser.parse(feed_url) | |
| for entry in feed.entries[:5]: | |
| title = entry.get("title", "") | |
| link = entry.get("link", "") | |
| if title and link: | |
| all_items.append(f"{title} {link}") | |
| except: | |
| continue | |
| return random.choice(all_items) if all_items else "Check out the latest in tech!" | |
| def login(page): | |
| print("Navigating to X login...") | |
| page.goto("https://twitter.com/i/flow/login", wait_until="networkidle", timeout=60000) | |
| page.wait_for_timeout(5000) | |
| print("Page loaded, looking for input...") | |
| # Try multiple selectors | |
| selectors = [ | |
| 'input[autocomplete="username"]', | |
| 'input[name="text"]', | |
| 'input[type="text"]', | |
| '[data-testid="ocfEnterTextTextInput"]', | |
| ] | |
| username_filled = False | |
| for selector in selectors: | |
| try: | |
| if page.locator(selector).is_visible(timeout=5000): | |
| page.locator(selector).fill(X_USERNAME) | |
| username_filled = True | |
| print(f"Username filled using: {selector}") | |
| break | |
| except: | |
| continue | |
| if not username_filled: | |
| print("Could not find username field!") | |
| return False | |
| page.keyboard.press("Enter") | |
| page.wait_for_timeout(4000) | |
| # Handle possible verification step | |
| for selector in selectors: | |
| try: | |
| if page.locator(selector).is_visible(timeout=3000): | |
| print("Verification step detected!") | |
| page.locator(selector).fill(X_USERNAME) | |
| page.keyboard.press("Enter") | |
| page.wait_for_timeout(3000) | |
| break | |
| except: | |
| continue | |
| # Fill password | |
| password_selectors = [ | |
| 'input[name="password"]', | |
| 'input[type="password"]', | |
| 'input[autocomplete="current-password"]', | |
| ] | |
| password_filled = False | |
| for selector in password_selectors: | |
| try: | |
| if page.locator(selector).is_visible(timeout=8000): | |
| page.locator(selector).fill(X_PASSWORD) | |
| password_filled = True | |
| print(f"Password filled using: {selector}") | |
| break | |
| except: | |
| continue | |
| if not password_filled: | |
| print("Could not find password field!") | |
| return False | |
| page.keyboard.press("Enter") | |
| page.wait_for_timeout(6000) | |
| print("Login done!") | |
| return True | |
| def post_tweet(page): | |
| try: | |
| news = get_tech_news() | |
| page.goto("https://twitter.com/compose/tweet", wait_until="networkidle", timeout=30000) | |
| page.wait_for_timeout(3000) | |
| tweet_selectors = [ | |
| '[data-testid="tweetTextarea_0"]', | |
| '.public-DraftEditor-content', | |
| '[contenteditable="true"]', | |
| ] | |
| for selector in tweet_selectors: | |
| try: | |
| if page.locator(selector).is_visible(timeout=5000): | |
| page.locator(selector).click() | |
| page.keyboard.type(news[:280]) | |
| page.wait_for_timeout(1000) | |
| break | |
| except: | |
| continue | |
| # Click tweet button | |
| btn_selectors = [ | |
| '[data-testid="tweetButtonInline"]', | |
| '[data-testid="tweetButton"]', | |
| ] | |
| for selector in btn_selectors: | |
| try: | |
| if page.locator(selector).is_visible(timeout=5000): | |
| page.locator(selector).click() | |
| break | |
| except: | |
| continue | |
| page.wait_for_timeout(3000) | |
| print(f"Posted: {news[:50]}...") | |
| except Exception as e: | |
| print(f"Post failed: {e}") | |
| def run_bot(): | |
| with sync_playwright() as p: | |
| browser = p.chromium.launch( | |
| headless=True, | |
| args=[ | |
| "--no-sandbox", | |
| "--disable-setuid-sandbox", | |
| "--disable-dev-shm-usage", | |
| "--disable-blink-features=AutomationControlled", | |
| ] | |
| ) | |
| context = browser.new_context( | |
| user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", | |
| viewport={"width": 1280, "height": 720}, | |
| locale="en-US", | |
| ) | |
| page = context.new_page() | |
| # Hide automation flags | |
| page.add_init_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})") | |
| logged_in = login(page) | |
| if not logged_in: | |
| print("Login failed, exiting.") | |
| return | |
| while True: | |
| print("--- Starting post session ---") | |
| for i in range(5): | |
| post_tweet(page) | |
| print(f"Tweet {i+1}/5 done") | |
| time.sleep(720) | |
| print("--- Sleeping for 2 hours ---") | |
| time.sleep(7200) | |
| run_bot() |