# Notion Opus/GPT-6.1 free farm — FULL PIPELINE # 1. Voidash mailbox 2. Signup + code 3. Onboarding 4. Model select + test message # Usage: python farm.py N [model] import asyncio, json, re, sys, time, random, string, os import httpx from playwright.async_api import async_playwright BASE = "C:/Users/User/tmp/notion_autoreg" OUT = BASE + "/farm_accounts.jsonl" UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36" VOIDASH_DOMAINS = ["voidash.bond"] NOTION_SIGNUP = "https://www.notion.so/signup" FIRSTS = ["alex", "maria", "peter", "laura", "stef", "anna", "tony", "nina", "eric", "sara", "luca", "jana", "tom", "lena", "paul", "kate"] # 1024proxy residential DE — sticky session per account PX_USER = "YOUR_PROXY_USER" PX_PASS = "YOUR_PASSWORD" PX_HOST = "hk.1024proxy.io:3000" def de_proxy(sess=None): if sess is None: sess = random.randint(100000, 999999) return {"server": f"http://{PX_HOST}", "username": f"{PX_USER}-region-de-sess{sess}", "password": PX_PASS} async def goto_retry(page, url, tries=5, timeout=90000): for i in range(tries): try: await page.goto(url, wait_until="domcontentloaded", timeout=timeout) return True except Exception as e: print("goto retry", i, str(e)[:70]) await asyncio.sleep(4) return False def voidash_create(): domain = random.choice(VOIDASH_DOMAINS) with httpx.Client(timeout=25, trust_env=False) as c: r = c.post("https://api.voidash.com/api/v1/inboxes", json={"domain": domain}) if r.status_code not in (200, 201): return None, f"voidash {r.status_code}: {r.text[:100]}" d = r.json() return d["address"], d["session_key"] def voidash_wait_code(session_key, deadline_s=240, since_ts=None): t0 = time.time() if since_ts is None: since_ts = t0 headers = {"Authorization": f"Bearer {session_key}"} with httpx.Client(timeout=25, trust_env=False, headers=headers) as c: while time.time() - t0 < deadline_s: try: r = c.get("https://api.voidash.com/api/v1/messages") if r.status_code == 200: msgs = r.json() if isinstance(msgs, dict): msgs = msgs.get("messages", msgs.get("data", [])) for m in msgs: try: created = m.get("created_at") or "" if created and since_ts: from datetime import datetime, timezone cts = datetime.fromisoformat(created.replace("Z", "+00:00")).timestamp() if cts < since_ts - 120: continue except Exception: pass subj = (m.get("subject") or "").lower() frm = json.dumps(m.get("from", {})).lower() if "notion" in subj or "notion" in frm: full_body = m.get("body") or m.get("text") or "" if not full_body: try: r2 = c.get(f"https://api.voidash.com/api/v1/messages/{m['id']}") full_body = r2.json().get("body") or r2.json().get("text") or "" except Exception: pass lines = [l.strip() for l in full_body.splitlines() if l.strip()] for l in lines[:4]: if re.fullmatch(r'[A-Za-z0-9]{6,8}', l): return l m2 = re.search(r'\b([A-Za-z0-9]{6})\b', full_body[:200]) if m2: return m2.group(1) except Exception as e: print("voidash err:", str(e)[:120]) time.sleep(6) return None async def farm_one(model="Opus"): res = {"status": "error", "step": "init", "model": model} # 1) mailbox addr, key = voidash_create() if not addr: res["error"] = key return res res["email"] = addr res["voidash_key"] = key print("MAILBOX:", addr) async with async_playwright() as p: browser = await p.chromium.launch(headless=True, args=["--no-sandbox"], proxy=de_proxy()) ctx = await browser.new_context(user_agent=UA, viewport={"width": 1600, "height": 1000}) page = await ctx.new_page() try: # ===== 2) signup ===== await goto_retry(page, NOTION_SIGNUP) await page.wait_for_timeout(6000) email_input = page.locator("input[type=email]").first for _t in range(5): try: await email_input.wait_for(state="visible", timeout=30000) break except Exception: print("email input not visible, reload", _t) await page.reload(wait_until="domcontentloaded", timeout=60000) await page.wait_for_timeout(5000) else: res["error"] = "email-input-never-visible" return res await email_input.fill(addr) await page.wait_for_timeout(600) cont = page.get_by_role("button", name=re.compile("Continue", re.I)).first if await cont.count(): await cont.click() else: await email_input.press("Enter") await page.wait_for_timeout(5000) body = (await page.inner_text("body")).lower() if "invalid email domain" in body or "problem" in body: res["error"] = "rejected: " + body[:150] await page.screenshot(path=f"{BASE}/err_{int(time.time())}.png") return res # ===== 3) code ===== if "verification" in body or "code" in body: sent_ts = time.time() code = await asyncio.to_thread(voidash_wait_code, key, 240, sent_ts) if not code: res["error"] = "otp-not-found" await page.screenshot(path=f"{BASE}/err_{int(time.time())}.png") return res res["otp"] = code print("CODE:", code) code_input = page.locator("input[autocomplete=one-time-code], input[inputmode=numeric], input[name=code]").first if await code_input.count(): await code_input.fill(code) else: inputs = page.locator("input") cnt = await inputs.count() filled = False for j in range(cnt): inp = inputs.nth(j) t = await inp.get_attribute("type") or "" ph = (await inp.get_attribute("placeholder") or "").lower() if t not in ("email", "password") and "mail" not in ph: await inp.fill(code) filled = True break if not filled: cells = page.locator("input[maxlength=1]") cc = await cells.count() for j, ch in enumerate(code): if j < cc: await cells.nth(j).fill(ch) await page.wait_for_timeout(600) cont2 = page.get_by_role("button", name=re.compile("Continue", re.I)).first if await cont2.count(): await cont2.click() await page.wait_for_timeout(7000) # password (если есть) body = (await page.inner_text("body")).lower() pw_input = page.locator("input[type=password]").first if "password" in body and await pw_input.count(): pw = "Not!" + ''.join(random.choices(string.ascii_letters + string.digits, k=10)) res["password"] = pw await pw_input.fill(pw) await page.wait_for_timeout(400) cont3 = page.get_by_role("button", name=re.compile("Continue|Sign up|Create", re.I)).first if await cont3.count(): await cont3.click() else: await pw_input.press("Enter") await page.wait_for_timeout(7000) # ===== 3.5) workspace via API (надёжнее браузерного онбординга) ===== try: cks = await ctx.cookies() tv2 = next((c["value"] for c in cks if c["name"] == "token_v2"), None) if tv2: api = httpx.Client(timeout=30, trust_env=False, headers={"User-Agent": UA, "Content-Type": "application/json"}) gs = api.post("https://app.notion.com/api/v3/getSpaces", json={}, cookies={"token_v2": tv2}) has_space = False if gs.status_code == 200: for uid, rec in gs.json().items(): if rec.get("space"): has_space = True if not has_space: cs = api.post("https://app.notion.com/api/v3/createSpace", json={"name": "My Space", "type": "personal", "planType": "personal"}, cookies={"token_v2": tv2}) res["api_create_space"] = cs.status_code print("API createSpace:", cs.status_code) else: res["api_create_space"] = "exists" api.close() except Exception as e: res["api_create_space_err"] = str(e)[:120] # ===== 4) onboarding ===== for attempt in range(15): body = (await page.inner_text("body")).lower() if "customize your profile" in body or "your name" in body: name_inputs = page.locator("input[type=text], input:not([type])") cnt = await name_inputs.count() for j in range(min(cnt, 1)): await name_inputs.nth(j).fill(random.choice(FIRSTS).capitalize() + " " + random.choice(FIRSTS).capitalize()) cont = page.get_by_role("button", name=re.compile("Continue", re.I)).first if await cont.count(): await cont.click() for _ in range(10): await page.wait_for_timeout(1500) b2 = (await page.inner_text("body")).lower() if "customize your profile" not in b2 and "your name" not in b2: break continue if "how do you want to use" in body: opt = page.get_by_text(re.compile("for personal|for myself", re.I)).first if await opt.count(): await opt.click() await page.wait_for_timeout(2000) cont = page.get_by_role("button", name=re.compile("Continue", re.I)).first if await cont.count(): await cont.click() await page.wait_for_timeout(3000) continue if "start with your real work" in body or "connect email" in body: btn = page.get_by_role("button", name=re.compile("Start from scratch", re.I)).first if await btn.count(): await btn.click() # ждём смены экрана for _ in range(10): await page.wait_for_timeout(1500) b2 = (await page.inner_text("body")).lower() if "start with your real work" not in b2: break continue if "create" in body and "workspace" in body: btn = page.get_by_role("button", name=re.compile("Create new workspace", re.I)).first if await btn.count(): await btn.click() await page.wait_for_timeout(4000) continue if "desktop" in body and ("skip" in body or "faster" in body): skip = page.get_by_role("button", name=re.compile("skip for now|skip", re.I)).first if await skip.count(): await skip.click() await page.wait_for_timeout(3000) continue if "/onboarding" not in page.url: break # generic continue — только кликабельные кнопки без disabled cont = page.locator('button:enabled, [role=button]:not([aria-disabled="true"])').filter(has_text=re.compile(r"^\s*(Continue|Next|Get started)\s*$", re.I)).first if await cont.count(): await cont.click() await page.wait_for_timeout(3000) else: break res["post_onboarding_url"] = page.url print("POST-ONBOARDING:", page.url) # ===== 5) model select + test ===== # Если после онбординга мы уже на /chat — НЕ делаем goto (перезагрузка убивает чат-сессию) if "/chat" not in page.url: await page.goto("https://app.notion.com/chat", wait_until="domcontentloaded", timeout=60000) try: await page.locator('[aria-label="Choose AI model"]').first.wait_for(state="visible", timeout=45000) except Exception: # fallback: перезагрузка + повторное ожидание try: await page.goto("https://app.notion.com/chat", wait_until="domcontentloaded", timeout=60000) await page.locator('[aria-label="Choose AI model"]').first.wait_for(state="visible", timeout=45000) except Exception: res["error"] = "chat/model button missing" await ctx.storage_state(path=f"{BASE}/state_{addr.replace('@', '_at_').replace('.', '_')}.json") res["state_path"] = f"{BASE}/state_{addr.replace('@', '_at_').replace('.', '_')}.json" res["status"] = "registered-no-chat" await browser.close() return res await page.wait_for_timeout(2000) await page.locator('[aria-label="Choose AI model"]').first.click() await page.wait_for_timeout(2500) items = page.locator('[role=menuitem]') cnt = await items.count() target = None for j in range(cnt): t = await items.nth(j).inner_text() if model.lower() in t.lower(): target = items.nth(j) break if target is None: res["error"] = f"model {model} not in menu" else: await target.click() await page.wait_for_timeout(2000) print("MODEL SELECTED:", model) # test message chat_box = page.locator('[contenteditable=true]').first await chat_box.click() await chat_box.fill("Hello! Which model are you? Answer in one short sentence.") await page.wait_for_timeout(500) submit = page.locator('[aria-label="Submit AI message"]').first if await submit.count(): await submit.click() else: await chat_box.press("Enter") # wait response for i in range(40): await page.wait_for_timeout(2500) body = (await page.inner_text("body")).lower() if "working on your request" not in body and "connecting the details" not in body: if "hello! which model" in body: break body_full = await page.inner_text("body") # extract reply: текст после нашего промпта try: idx = body_full.lower().rfind("hello! which model") reply = body_full[idx + 200:idx + 600].strip() res["ai_reply"] = reply[:300] except Exception: pass res["model_active"] = model res["final_url"] = page.url state_path = f"{BASE}/state_{addr.replace('@', '_at_').replace('.', '_')}.json" await ctx.storage_state(path=state_path) res["state_path"] = state_path if "signup" not in page.url and "login" not in page.url and "appeals" not in page.url: res["status"] = "ok" else: res["status"] = "incomplete" await page.screenshot(path=f"{BASE}/final_{int(time.time())}.png") except Exception as e: res["error"] = str(e)[:300] try: await page.screenshot(path=f"{BASE}/err_{int(time.time())}.png") except Exception: pass finally: await browser.close() return res async def main(): n = int(sys.argv[1]) if len(sys.argv) > 1 else 1 model = sys.argv[2] if len(sys.argv) > 2 else "Opus" for i in range(n): print(f"=== farm {i+1}/{n} model={model} ===") res = await farm_one(model) with open(OUT, "a", encoding="utf-8") as f: f.write(json.dumps(res, ensure_ascii=False) + "\n") print("RESULT:", json.dumps(res, ensure_ascii=False)[:700]) if res.get("status") != "ok" and i + 1 < n: print("-> continuing to next account") if __name__ == "__main__": asyncio.run(main())