Spaces:
Sleeping
Sleeping
import gradio as gr | |
import time | |
import os | |
import subprocess | |
import sys | |
from PIL import Image | |
import io | |
import base64 | |
import logging | |
import traceback | |
from datetime import datetime | |
# 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) | |
# Global variable to track browser installation | |
BROWSERS_INSTALLED = False | |
def download_playwright_browsers(): | |
"""Download and install Playwright browsers""" | |
global BROWSERS_INSTALLED | |
if BROWSERS_INSTALLED: | |
return "Playwright browsers already installed." | |
try: | |
print("Installing Playwright browsers...") | |
# First install playwright itself if needed | |
subprocess.run([sys.executable, "-m", "pip", "install", "playwright==1.39.0"], check=True) | |
# Then install the browsers | |
result = subprocess.run( | |
[sys.executable, "-m", "playwright", "install", "chromium"], | |
check=True, | |
capture_output=True, | |
text=True | |
) | |
print("Installation output:", result.stdout) | |
if result.stderr: | |
print("Installation errors:", result.stderr) | |
BROWSERS_INSTALLED = True | |
return "Playwright browsers installed successfully." | |
except Exception as e: | |
error_msg = f"Error installing browsers: {str(e)}" | |
print(error_msg) | |
return error_msg | |
def save_screenshot(name): | |
"""Save a placeholder screenshot if we can't get a real one""" | |
try: | |
timestamp = int(time.time()) | |
filename = f"screenshots/{name}_{timestamp}.png" | |
# Create a simple colored image as a placeholder | |
img = Image.new('RGB', (400, 300), color=(73, 109, 137)) | |
img.save(filename) | |
logger.info(f"Saved placeholder screenshot: {filename}") | |
return filename | |
except Exception as e: | |
logger.error(f"Error creating placeholder: {e}") | |
return None | |
def login_and_like_posts(username, password, max_likes): | |
"""Main function to login to Instagram and like posts""" | |
status_updates = ["Starting Instagram Auto-Liker..."] | |
image_path = save_screenshot("start") | |
# First ensure browsers are installed | |
install_msg = download_playwright_browsers() | |
status_updates.append(install_msg) | |
try: | |
# Only import playwright after ensuring it's installed | |
from playwright.sync_api import sync_playwright | |
status_updates.append("Launching browser...") | |
with sync_playwright() as p: | |
browser = p.chromium.launch( | |
headless=True, | |
args=['--no-sandbox', '--disable-dev-shm-usage'] | |
) | |
# Create a context with realistic user agent | |
context = browser.new_context( | |
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', | |
viewport={'width': 1280, 'height': 720} | |
) | |
# Create a new page | |
page = context.new_page() | |
# First test browser by visiting a simple site | |
status_updates.append("Testing browser connection...") | |
page.goto("https://www.google.com") | |
page.wait_for_load_state("networkidle") | |
status_updates.append(f"Browser working. Title: {page.title()}") | |
# Take test screenshot | |
try: | |
test_screenshot = f"screenshots/browser_test_{int(time.time())}.png" | |
page.screenshot(path=test_screenshot) | |
image_path = test_screenshot | |
status_updates.append(f"Browser test screenshot saved") | |
except Exception as e: | |
status_updates.append(f"Error taking screenshot: {str(e)}") | |
# Instagram login | |
status_updates.append("Navigating to Instagram...") | |
page.goto("https://www.instagram.com/") | |
page.wait_for_load_state("networkidle") | |
# Take screenshot of Instagram landing | |
try: | |
landing_screenshot = f"screenshots/instagram_landing_{int(time.time())}.png" | |
page.screenshot(path=landing_screenshot) | |
image_path = landing_screenshot | |
status_updates.append("Instagram home page loaded") | |
except Exception as e: | |
status_updates.append(f"Error taking landing screenshot: {str(e)}") | |
# Handle cookie consent if present | |
try: | |
if page.query_selector('text=Accept') or page.query_selector('text=Allow'): | |
status_updates.append("Handling cookie consent...") | |
# Try different button text variants | |
for button_text in ["Accept", "Allow", "Accept All", "Allow All Cookies"]: | |
try: | |
button = page.query_selector(f'text={button_text}') | |
if button: | |
button.click() | |
status_updates.append(f"Clicked '{button_text}' button") | |
page.wait_for_timeout(2000) | |
break | |
except Exception as btn_error: | |
logger.warning(f"Error clicking {button_text}: {str(btn_error)}") | |
continue | |
except Exception as e: | |
status_updates.append(f"No cookie dialog or error: {str(e)}") | |
# Wait for and fill login form | |
status_updates.append("Looking for login form...") | |
try: | |
page.wait_for_selector('input[name="username"]', state="visible", timeout=10000) | |
# Take pre-login screenshot | |
try: | |
pre_login_screenshot = f"screenshots/pre_login_{int(time.time())}.png" | |
page.screenshot(path=pre_login_screenshot) | |
image_path = pre_login_screenshot | |
except Exception as e: | |
status_updates.append(f"Error taking pre-login screenshot: {str(e)}") | |
# Enter credentials | |
status_updates.append(f"Entering username: {username}") | |
page.fill('input[name="username"]', username) | |
page.fill('input[name="password"]', password) | |
status_updates.append("Credentials entered") | |
# Click login button | |
status_updates.append("Clicking login button...") | |
page.click('button[type="submit"]') | |
# Wait for navigation | |
page.wait_for_load_state("networkidle") | |
page.wait_for_timeout(5000) # Additional wait for elements | |
# Take post-login screenshot | |
try: | |
post_login_screenshot = f"screenshots/post_login_{int(time.time())}.png" | |
page.screenshot(path=post_login_screenshot) | |
image_path = post_login_screenshot | |
except Exception as e: | |
status_updates.append(f"Error taking post-login screenshot: {str(e)}") | |
# Handle "Save Login Info" popup if it appears | |
try: | |
not_now_button = page.query_selector('text="Not Now"') | |
if not_now_button: | |
not_now_button.click() | |
status_updates.append("Dismissed 'Save Login Info' popup") | |
page.wait_for_timeout(2000) | |
except Exception as e: | |
status_updates.append(f"No 'Save Login Info' popup or error: {str(e)}") | |
# Handle notifications popup if it appears | |
try: | |
not_now_button = page.query_selector('text="Not Now"') | |
if not_now_button: | |
not_now_button.click() | |
status_updates.append("Dismissed notifications popup") | |
page.wait_for_timeout(2000) | |
except Exception as e: | |
status_updates.append(f"No notifications popup or error: {str(e)}") | |
# Verify we're on the feed | |
try: | |
feed_screenshot = f"screenshots/feed_{int(time.time())}.png" | |
page.screenshot(path=feed_screenshot) | |
image_path = feed_screenshot | |
status_updates.append("Successfully logged in! On Instagram feed now.") | |
except Exception as e: | |
status_updates.append(f"Error taking feed screenshot: {str(e)}") | |
# 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: | |
page.wait_for_selector('article', timeout=10000) | |
status_updates.append("Found posts on feed") | |
while likes_count < max_likes and scroll_count < max_scrolls: | |
# Find like buttons | |
like_buttons = page.query_selector_all('article svg[aria-label="Like"]') | |
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 | |
button.scroll_into_view_if_needed() | |
page.wait_for_timeout(500) | |
# Click like | |
button.click() | |
likes_count += 1 | |
status_updates.append(f"Liked post {likes_count}/{max_likes}") | |
# Wait between likes | |
page.wait_for_timeout(2000) | |
except Exception as e: | |
status_updates.append(f"Error liking post {i+1}: {str(e)}") | |
continue | |
# Scroll down to load more | |
page.evaluate("window.scrollBy(0, 1000)") | |
status_updates.append(f"Scrolled down to load more posts") | |
page.wait_for_timeout(3000) | |
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 | |
browser.close() | |
status_updates.append("Browser closed") | |
return "\n".join(status_updates), image_path | |
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 | |
# Simple interface for testing | |
def test_functionality(): | |
"""Simple function to test if the app is working""" | |
return "Instagram Auto-Liker is operational", save_screenshot("test") | |
# 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") | |
test_btn = gr.Button("Test App Function") | |
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] | |
) | |
test_btn.click( | |
fn=test_functionality, | |
inputs=[], | |
outputs=[status_output, image_output] | |
) | |
return app | |
# Make sure we install browsers first at module level | |
try: | |
download_playwright_browsers() | |
except Exception as e: | |
print(f"Warning: Failed to install browsers at startup: {e}") | |
# Launch the app | |
if __name__ == "__main__": | |
print("Creating interface...") | |
app = create_interface() | |
print("Launching interface...") | |
app.launch(server_name="0.0.0.0", server_port=7860, share=True) | |
print("Interface launched.") |