import gradio as gr import time import os import subprocess import sys from PIL import Image import io import logging import traceback # Configure logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Create screenshots directory if it doesn't exist os.makedirs('screenshots', exist_ok=True) def install_playwright(): """Install Playwright and its browsers""" try: logger.info("Installing Playwright browsers...") subprocess.run([sys.executable, "-m", "pip", "install", "playwright==1.39.0"], check=True) subprocess.run([sys.executable, "-m", "playwright", "install", "chromium"], check=True) return "Playwright browsers installed successfully." except Exception as e: error_msg = f"Error installing browsers: {str(e)}" logger.error(error_msg) return error_msg def save_placeholder_image(name): """Create a placeholder image when no screenshot is available""" timestamp = int(time.time()) filename = f"screenshots/{name}_{timestamp}.png" # Create a simple colored image img = Image.new('RGB', (400, 300), color=(73, 109, 137)) d = Image.new('RGB', (400, 300), color=(200, 200, 200)) # Add some text if possible try: from PIL import ImageDraw, ImageFont draw = ImageDraw.Draw(img) draw.text((10, 150), f"Instagram Auto-Liker - {name}", fill=(255, 255, 255)) except: pass img.save(filename) logger.info(f"Saved placeholder image: {filename}") return filename def run_with_selenium(username, password, max_likes): """Run the Instagram auto-liker with Selenium""" status_updates = ["Starting Instagram Auto-Liker with Selenium..."] image_path = save_placeholder_image("start") try: # Import Selenium components from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC status_updates.append("Setting up Chrome driver...") # Configure Chrome options chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-dev-shm-usage') chrome_options.add_argument('--disable-gpu') chrome_options.add_argument('--window-size=1280,720') # Start Chrome driver driver = webdriver.Chrome(options=chrome_options) driver.set_page_load_timeout(60) # Test browser by visiting Google status_updates.append("Testing browser connection...") driver.get("https://www.google.com") status_updates.append(f"Browser working. Title: {driver.title}") # Take a screenshot if possible try: test_screenshot = f"screenshots/test_{int(time.time())}.png" driver.save_screenshot(test_screenshot) image_path = test_screenshot status_updates.append("Browser screenshot saved") except Exception as e: status_updates.append(f"Error taking screenshot: {str(e)}") # Navigate to Instagram status_updates.append("Navigating to Instagram...") driver.get("https://www.instagram.com/") time.sleep(5) # Wait for page to load # Take a screenshot try: landing_screenshot = f"screenshots/landing_{int(time.time())}.png" driver.save_screenshot(landing_screenshot) image_path = landing_screenshot except Exception as e: status_updates.append(f"Error taking screenshot: {str(e)}") # Handle cookie dialog if present try: cookie_buttons = [ "//button[contains(text(), 'Accept')]", "//button[contains(text(), 'Allow')]", "//button[contains(text(), 'Only allow essential cookies')]" ] for button_xpath in cookie_buttons: try: cookie_btn = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.XPATH, button_xpath)) ) cookie_btn.click() status_updates.append("Clicked cookie consent button") time.sleep(2) break except: continue except: status_updates.append("No cookie dialog detected or it was bypassed") # Wait for login form status_updates.append("Looking for login form...") try: username_field = WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='username']")) ) # Enter credentials status_updates.append(f"Entering username: {username}") username_field.clear() username_field.send_keys(username) password_field = driver.find_element(By.CSS_SELECTOR, "input[name='password']") password_field.clear() password_field.send_keys(password) status_updates.append("Credentials entered") # Take a screenshot try: creds_screenshot = f"screenshots/credentials_{int(time.time())}.png" driver.save_screenshot(creds_screenshot) image_path = creds_screenshot except: pass # Click login button login_button = driver.find_element(By.CSS_SELECTOR, "button[type='submit']") status_updates.append("Clicking login button...") login_button.click() # Wait for login to complete time.sleep(5) # Take post-login screenshot try: post_login_screenshot = f"screenshots/post_login_{int(time.time())}.png" driver.save_screenshot(post_login_screenshot) image_path = post_login_screenshot except: pass # Check if login was successful current_url = driver.current_url if "/accounts/login" in current_url: # Still on login page - check for error messages try: error_message = driver.find_element(By.ID, "slfErrorAlert").text status_updates.append(f"Login failed: {error_message}") except: status_updates.append("Login failed: Reason unknown") driver.quit() return "\n".join(status_updates), image_path # Handle "Save Login Info" popup if it appears try: not_now_button = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Not Now')]")) ) not_now_button.click() status_updates.append("Dismissed 'Save Login Info' popup") time.sleep(2) except: status_updates.append("No 'Save Login Info' popup detected") # Handle notifications popup if it appears try: not_now_button = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Not Now')]")) ) not_now_button.click() status_updates.append("Dismissed notifications popup") time.sleep(2) except: status_updates.append("No notifications popup detected") # Take feed screenshot try: feed_screenshot = f"screenshots/feed_{int(time.time())}.png" driver.save_screenshot(feed_screenshot) image_path = feed_screenshot except: pass status_updates.append("Successfully logged in! On Instagram feed now.") # Start liking posts status_updates.append(f"Starting to like posts (target: {max_likes})...") # Like posts likes_count = 0 scroll_count = 0 max_scrolls = 30 # Try to find posts try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, "article")) ) status_updates.append("Found posts on feed") while likes_count < max_likes and scroll_count < max_scrolls: # Find like buttons like_buttons = driver.find_elements(By.XPATH, "//article//section//button//*[contains(@aria-label, 'Like') and not(contains(@aria-label, 'Unlike'))]/../.." ) status_updates.append(f"Found {len(like_buttons)} like buttons on scroll {scroll_count}") if len(like_buttons) == 0 and scroll_count > 5: status_updates.append("No more like buttons found. Stopping.") break # Click like buttons for i, button in enumerate(like_buttons): if likes_count >= max_likes: break try: # Scroll to button driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", button) time.sleep(1) # Click like button.click() likes_count += 1 status_updates.append(f"Liked post {likes_count}/{max_likes}") # Take screenshot occasionally if likes_count % 5 == 0: try: like_screenshot = f"screenshots/like_{likes_count}_{int(time.time())}.png" driver.save_screenshot(like_screenshot) image_path = like_screenshot except: pass # Wait between likes time.sleep(2) except Exception as e: status_updates.append(f"Error liking post {i+1}: {str(e)}") continue # Scroll down to load more driver.execute_script("window.scrollBy(0, 1000);") status_updates.append(f"Scrolled down to load more posts") time.sleep(3) scroll_count += 1 # Final status final_message = f"Finished! Liked {likes_count} posts." status_updates.append(final_message) except Exception as e: status_updates.append(f"Error finding or liking posts: {str(e)}") except Exception as e: status_updates.append(f"Error with login form: {str(e)}") # Close the browser driver.quit() status_updates.append("Browser closed") except Exception as e: error_message = f"Error: {str(e)}" logger.error(error_message) status_updates.append(error_message) status_updates.append(traceback.format_exc()) return "\n".join(status_updates), image_path def run_with_playwright(username, password, max_likes): """Run the Instagram auto-liker with Playwright""" status_updates = ["Starting Instagram Auto-Liker with Playwright..."] image_path = save_placeholder_image("start") try: from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch( headless=True, args=['--no-sandbox', '--disable-dev-shm-usage'] ) # Rest of Playwright code... # (Similar to previous implementation but with better error handling) except ImportError: status_updates.append("Playwright not available. Using Selenium instead.") return run_with_selenium(username, password, max_likes) except Exception as e: error_message = f"Error with Playwright: {str(e)}" logger.error(error_message) status_updates.append(error_message) status_updates.append("Falling back to Selenium...") return run_with_selenium(username, password, max_likes) def login_and_like_posts(username, password, max_likes): """Main entry point - tries Playwright first, falls back to Selenium""" # Install dependencies first install_msg = install_playwright() # First try with Selenium which tends to be more reliable on Hugging Face return run_with_selenium(username, password, max_likes) # Gradio Interface def create_interface(): with gr.Blocks(title="Instagram Auto-Liker") as app: gr.Markdown("# Instagram Auto-Liker") gr.Markdown("Enter your Instagram credentials and the number of posts to like.") with gr.Row(): with gr.Column(scale=1): username = gr.Textbox(label="Instagram Username") password = gr.Textbox(label="Instagram Password", type="password") max_likes = gr.Slider(minimum=1, maximum=100, value=10, step=1, label="Number of Posts to Like") submit_btn = gr.Button("Start Liking Posts") with gr.Column(scale=2): status_output = gr.Textbox(label="Status Log", lines=15) image_output = gr.Image(label="Latest Screenshot", type="filepath") submit_btn.click( fn=login_and_like_posts, inputs=[username, password, max_likes], outputs=[status_output, image_output] ) return app # Launch the app if __name__ == "__main__": # Install dependencies first print("Installing dependencies...") install_msg = install_playwright() print(install_msg) # Start the app print("Starting the application...") app = create_interface() app.launch(server_name="0.0.0.0", server_port=7860, share=True)