autoreg-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok60915d52e8425
2026-10-20 02:16:32 +03:00
commit f58eafeb48
565 changed files with 60064 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
# -*- coding: utf-8 -*-
"""
plane.so FULL COMBO - autoreg + workspace + API token gateway, end-to-end automated
====================================================================================
One account in ~20s, zero captcha. Pipeline per account:
1. POST /auth/email-check/ -> confirm email free (MAGIC_CODE flow)
2. POST /auth/magic-generate/ -> 6-digit code sent to mailbox
3. IMAP poll -> read code from SUBJECT "Plane login code is NNNNNN"
4. GET /auth/get-csrf-token/ -> csrftoken (mandatory, else CSRF failure page)
5. POST /auth/magic-sign-up/ -> 302 + session-id cookie (account created, email auto-verified)
6. GET /api/users/me/ -> verify session
7. POST /api/workspaces/ -> create workspace (name+slug)
8. POST /api/users/api-tokens/ -> issue API token (plane_api_*, 60/min, shown ONCE)
9. GET /api/v1/users/me/ (X-API-Key) -> verify token live
10. append full record to accounts.jsonl
Backend: api.plane.so (app.plane.so = SPA only, 405 on /auth).
Throttle: auth 10/min per IP -> bulk sleeps 7s.
Reverse source: github.com/makeplane/plane (preview branch):
apps/api/plane/authentication/urls.py, views/app/magic.py, app/views/api.py
CONFIG: fill IMAP_* + EMAIL_* below, or pass --emails file (email:imap_host:imap_user:imap_pass).
Usage:
python plane_full_combo.py <alias> # one account via +alias
python plane_full_combo.py --bulk N [out.jsonl] # mass run
python plane_full_combo.py --emails list.txt [out.jsonl]
Token use afterwards:
curl https://api.plane.so/api/v1/users/me/ -H "X-API-Key: [REDACTED]"
workspace-scoped: https://api.plane.so/api/v1/workspaces/<slug>/projects/ etc.
"""
import imaplib, email as emaillib, email.utils, re, time, json, sys, random, ssl
import urllib.request, urllib.error, http.cookiejar
from urllib.request import Request, urlopen
from urllib.parse import urlencode
# ============ CONFIG - FILL YOUR OWN ============
IMAP_HOST = "" # imap.gmail.com / outlook.office365.com / ...
IMAP_USER = ""
IMAP_PASS = "" # app password recommended
EMAIL_DOMAIN = "" # gmail.com
EMAIL_LOCAL = "" # yourname -> yourname+prNNNNNN@gmail.com
WORKSPACE_NAME = "farm lab"
WORKSPACE_SLUG_PREFIX = "farmlab"
# ================================================
API = "https://api.plane.so"
UA = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Origin": "https://app.plane.so", "Referer": "https://app.plane.so/sign-up/"}
def post_json(path, payload, cookie=None, csrf=None, extra=None):
hdrs = {"Content-Type": "application/json", **UA}
if cookie: hdrs["Cookie"] = cookie
if csrf: hdrs["X-CSRFToken"] = csrf
if extra: hdrs.update(extra)
req = Request(API + path, data=json.dumps(payload).encode(), headers=hdrs)
try:
with urlopen(req, timeout=30) as r:
return r.status, json.loads(r.read().decode() or "{}")
except urllib.error.HTTPError as e:
try: body = json.loads(e.read().decode() or "{}")
except Exception: body = {}
return e.code, body
def get_csrf():
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
req = urllib.request.Request(API + "/auth/get-csrf-token/", headers=UA)
with opener.open(req, timeout=30) as r:
r.read()
token = [REDACTED] for c in cj if c.name == "csrftoken"), None)
return token, "; ".join(f"{c.name}={c.value}" for c in cj)
def post_form(path, data, cookies=None, csrf=None):
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, *a, **k): return None
opener = urllib.request.build_opener(NoRedirect)
hdrs = {"Content-Type": "application/x-www-form-urlencoded", **UA}
if cookies: hdrs["Cookie"] = cookies
if csrf: hdrs["X-CSRFToken"] = csrf
req = urllib.request.Request(API + path, data=urlencode(data).encode(), headers=hdrs)
try:
r = opener.open(req, timeout=30)
return r.status, r.read().decode(errors="ignore"), r.headers
except urllib.error.HTTPError as e:
return e.code, e.read().decode(errors="ignore"), e.headers
def get_json(path, cookie=None, api_key=None):
hdrs = {"User-Agent": UA["User-Agent"]}
if cookie: hdrs["Cookie"] = cookie
if api_key: hdrs["X-API-Key"] = api_key
req = Request(API + path, headers=hdrs)
try:
with urlopen(req, timeout=30) as r:
return r.status, json.loads(r.read().decode() or "{}")
except urllib.error.HTTPError as e:
return e.code, {}
def read_otp(match_suffix, host, user, passwd, tries=24, wait=5, since_ts=None):
for _ in range(tries):
try:
m = imaplib.IMAP4_SSL(host, ssl_context=ssl.create_default_context())
m.login(user, passwd); m.select("INBOX")
_, data = m.search(None, 'SUBJECT "Plane login code"')
best = None
for num in data[0].split()[-10:]:
_, msg = m.fetch(num, "(RFC822)")
raw = msg[0][1]
try:
mime = emaillib.message_from_bytes(raw)
full = ""
for part in mime.walk():
if part.get_content_type() in ("text/plain", "text/html"):
try: full += part.get_payload(decode=True).decode(errors="ignore")
except Exception: pass
full += " " + str(mime.get("Subject", "")) + " " + str(mime.get("To", ""))
except Exception:
full = raw.decode(errors="ignore")
if match_suffix.lower() not in full.lower():
continue
mm = re.search(r"login code is (\d{6})", full)
dm = re.search(r"^Date: (.+)$", raw.decode(errors="ignore"), re.M)
ts = 0
if dm:
try: ts = email.utils.mktime_tz(email.utils.parsedate_tz(dm.group(1)))
except Exception: ts = 0
if mm and (best is None or ts >= best[0]):
best = (ts, mm.group(1))
m.logout()
if best and (since_ts is None or best[0] >= since_ts - 180):
return best[1]
except Exception as e:
print("imap err:", e, file=sys.stderr)
time.sleep(wait)
return None
def full_combo(email_addr, match_suffix, imap_host, imap_user, imap_pass, slug=None):
rec = {"email": email_addr, "ts": int(time.time())}
# 1-2. email check + magic generate
st, js = post_json("/auth/email-check/", {"email": email_addr})
if js.get("existing"):
rec["result"] = "EXISTS"; return rec
t0 = time.time()
st, js = post_json("/auth/magic-generate/", {"email": email_addr})
if st != 200:
rec["result"] = f"GEN_FAIL_{st}"; return rec
# 3. OTP
code = read_otp(match_suffix, imap_host, imap_user, imap_pass, since_ts=t0)
if not code:
rec["result"] = "NO_OTP"; return rec
# 4-5. csrf + sign-up
csrf_tok, csrf_cookie = get_csrf()
st, body, hdrs = post_form("/auth/magic-sign-up/", {"email": email_addr, "code": code},
cookies=csrf_cookie, csrf=csrf_tok)
loc = hdrs.get("Location", "")
if "error_code" in loc:
rec["result"] = "SIGNUP_ERR:" + loc[:150]; return rec
cookies = hdrs.get_all("Set-Cookie") or []
sess = "; ".join(c.split(";")[0] for c in cookies)
cookie = ((sess + "; ") if sess else "") + csrf_cookie
csrf_val = next((c.split(";")[0].split("=", 1)[1] for c in cookies if c.startswith("csrftoken=")), csrf_tok)
# 6. verify session
st, me = get_json("/api/users/me/", cookie=cookie)
if st != 200 or not me.get("email"):
rec["result"] = f"SESSION_FAIL_{st}"; return rec
rec["user_id"] = me["id"]
# 7. create workspace
slug = slug or (WORKSPACE_SLUG_PREFIX + str(random.randint(10000, 99999)))
st, ws = post_json("/api/workspaces/", {"name": WORKSPACE_NAME, "slug": slug},
cookie=cookie, csrf=csrf_val,
extra={"Referer": "https://app.plane.so/"})
if st not in (200, 201):
rec["result"] = f"WS_FAIL_{st}:{str(ws)[:100]}"; rec["session_cookie"] = cookie; return rec
rec["workspace"] = {"slug": ws.get("slug"), "id": ws.get("id")}
# 8. API token
st, tk = post_json("/api/users/api-tokens/", {"label": "combo-" + slug, "description": "farm"},
cookie=cookie, csrf=csrf_val,
extra={"Referer": "https://app.plane.so/"})
if st not in (200, 201) or not tk.get("token"):
rec["result"] = f"TOKEN_FAIL_{st}:{str(tk)[:100]}"; rec["session_cookie"] = cookie; return rec
rec["api_token"] = tk["token"]
rec["rate_limit"] = tk.get("allowed_rate_limit")
# 9. verify token on public v1
st, v1 = get_json("/api/v1/users/me/", api_key=tk["token"])
rec["token_live"] = (st == 200)
rec["session_cookie"] = cookie
rec["result"] = "FULL_OK" if st == 200 else "TOKEN_UNVERIFIED"
return rec
def gen_alias_email():
alias = "pr" + str(random.randint(100000, 999999))
return f"{EMAIL_LOCAL}+{alias}@{EMAIL_DOMAIN}", alias
def run_one(target, imap_host=None, imap_user=None, imap_pass=None):
h = imap_host or IMAP_HOST; u = imap_user or IMAP_USER; p = imap_pass or IMAP_PASS
if "@" in target:
addr, suffix = target, target
else:
if not (EMAIL_LOCAL and EMAIL_DOMAIN):
print("ERROR: fill EMAIL_LOCAL/EMAIL_DOMAIN or pass full email"); sys.exit(1)
addr = f"{EMAIL_LOCAL}+{target}@{EMAIL_DOMAIN}"; suffix = target
rec = full_combo(addr, suffix, h, u, p)
print(json.dumps(rec, indent=2, default=str))
return rec
def main():
args = sys.argv[1:]
if not args:
print(__doc__); sys.exit(1)
if args[0] == "--bulk":
n = int(args[1]) if len(args) > 1 else 10
outfile = args[2] if len(args) > 2 else "plane_accounts.jsonl"
ok = 0
with open(outfile, "a", encoding="utf-8") as f:
for i in range(n):
addr, alias = gen_alias_email()
try:
rec = full_combo(addr, alias, IMAP_HOST, IMAP_USER, IMAP_PASS)
except Exception as e:
rec = {"email": addr, "result": "EXC:" + str(e)}
f.write(json.dumps(rec, default=str) + "\n"); f.flush()
if rec.get("result") == "FULL_OK": ok += 1
print(f"[{i+1}/{n}] {addr} -> {rec.get('result')} token={rec.get('api_token','-')[:20]} (full_ok={ok})")
time.sleep(7)
print(f"DONE {ok}/{n} -> {outfile}")
elif args[0] == "--emails":
outfile = args[2] if len(args) > 2 else "plane_accounts.jsonl"
ok = 0
with open(args[1], encoding="utf-8") as f, open(outfile, "a", encoding="utf-8") as o:
for i, line in enumerate(f):
line = line.strip()
if not line: continue
parts = line.split(":")
if len(parts) == 4:
addr, h, u, p = parts
else:
addr, h, u, p = line, IMAP_HOST, IMAP_USER, IMAP_PASS
try:
rec = full_combo(addr, addr, h, u, p)
except Exception as e:
rec = {"email": addr, "result": "EXC:" + str(e)}
o.write(json.dumps(rec, default=str) + "\n"); o.flush()
if rec.get("result") == "FULL_OK": ok += 1
print(f"[{i+1}] {addr} -> {rec.get('result')} (full_ok={ok})")
time.sleep(7)
print(f"DONE {ok} -> {outfile}")
else:
run_one(args[0])
if __name__ == "__main__":
main()