| import os |
| import time |
| import random |
| import threading |
| from http.server import SimpleHTTPRequestHandler, HTTPServer |
| from playwright.sync_api import sync_playwright |
| from groq import Groq |
| from dotenv import load_dotenv |
|
|
| load_dotenv() |
|
|
| |
| def run_health_server(): |
| """Starts a lightweight server on port 7860 so HF knows the Space is alive""" |
| class HealthHandler(SimpleHTTPRequestHandler): |
| def do_GET(self): |
| self.send_response(200) |
| self.send_header("Content-type", "text/html") |
| self.end_headers() |
| self.wfile.write(b"Bot is running actively in the background!") |
|
|
| |
| port = int(os.environ.get("PORT", 7860)) |
| server = HTTPServer(("0.0.0.0", port), HealthHandler) |
| print(f"Health check server listening on port {port}...") |
| server.serve_forever() |
|
|
| |
| groq_client = Groq(api_key=os.getenv("GROQ_API_KEY")) |
| KIMI_MODEL = "moonshotai/kimi-k2.6" |
|
|
| def get_ai_response(user_message): |
| try: |
| completion = groq_client.chat.completions.create( |
| model=KIMI_MODEL, |
| messages=[ |
| {"role": "system", "content": "You are a helpful Instagram DM automation assistant. Give direct, crisp, and concise replies under 3 sentences. No internal reasoning."}, |
| {"role": "user", "content": user_message} |
| ] |
| ) |
| return completion.choices[0].message.content |
| except Exception as e: |
| print(f"LLM Error: {e}") |
| return "Hey! I'm processing your request. Give me just a moment." |
|
|
| def human_type(element, text): |
| for char in text: |
| element.type(char) |
| time.sleep(random.uniform(0.05, 0.15)) |
|
|
| def run_bot(): |
| with sync_playwright() as p: |
| print("Launching visible Chromium browser instance...") |
| browser = p.chromium.launch( |
| headless=False, |
| args=["--no-sandbox", "--disable-setuid-sandbox"] |
| ) |
| |
| context = browser.new_context(viewport={"width": 1366, "height": 768}) |
| page = context.new_page() |
| |
| print("Navigating to Instagram...") |
| page.goto("https://www.instagram.com/accounts/login/", wait_until="networkidle") |
| |
| time.sleep(random.uniform(2, 4)) |
| page.fill("input[name='username']", os.getenv("IG_USERNAME")) |
| time.sleep(random.uniform(1, 2)) |
| page.fill("input[name='password']", os.getenv("IG_PASSWORD")) |
| time.sleep(random.uniform(1, 2)) |
| |
| page.click("button[type='submit']") |
| print("Login credentials submitted.") |
| |
| page.wait_for_url("**/instagram.com/**", timeout=60000) |
| time.sleep(5) |
| |
| print("Navigating to Inbox...") |
| page.goto("https://www.instagram.com/direct/inbox/", wait_until="networkidle") |
| |
| while True: |
| try: |
| unread_chats = page.query_selector_all("div[style*='font-weight: 600']") |
| if unread_chats: |
| print(f"Found {len(unread_chats)} unread conversation thread(s)!") |
| for chat in unread_chats: |
| chat.click() |
| time.sleep(2) |
| |
| message_bubbles = page.query_selector_all("div[role='row'] >> span") |
| if not message_bubbles: |
| continue |
| |
| last_message_text = message_bubbles[-1].inner_text() |
| print(f"Received Message: {last_message_text}") |
| |
| ai_reply = get_ai_response(last_message_text) |
| print(f"Kimi K2.6 Reply: {ai_reply}") |
| |
| message_input = page.wait_for_selector("div[role='textbox'][aria-label*='Message']") |
| message_input.click() |
| human_type(message_input, ai_reply) |
| |
| time.sleep(1) |
| page.keyboard.press("Enter") |
| print("Reply successfully dispatched.") |
| time.sleep(random.uniform(2, 4)) |
| except Exception as loop_error: |
| print(f"Error checking messages: {loop_error}") |
| |
| time.sleep(30) |
|
|
| if __name__ == "__main__": |
| if not os.getenv("IG_USERNAME") or not os.getenv("IG_PASSWORD"): |
| print("Missing environment configurations! Set IG_USERNAME and IG_PASSWORD.") |
| else: |
| |
| health_thread = threading.Thread(target=run_health_server, daemon=True) |
| health_thread.start() |
| |
| |
| run_bot() |