Files
autoreg-skills-max/skills/ai-provider-autoreg/references/remalt-better-auth-autoreg.md

5.5 KiB
Raw Blame History

Remalt.com — better-auth авторег без капчи + разведка триалов (проверено 2026-10-08)

Репо с рабочим кодом: aaronjaworski710/remalt-autoreg (remalt_autoreg.py, trial_probe.py). Локально: C:/Users/User/tmp/remalt/.

Generic-паттерн: better-auth сайты (Next.js)

Remalt — эталонный пример стека Next.js + better-auth + Supabase. Паттерн переносим на любой better-auth сайт:

  1. Детект стека: скачать signup-страницу → собрать все /_next/static/chunks/*.js → grep чанков на sign-up/email, better-auth, supabase, /api/auth/. better-auth всегда exposes REST: POST /api/auth/sign-up/email {email, password, name}, POST /api/auth/sign-in/email, GET /api/auth/get-session, verify через GET /api/auth/verify-email?token=***.
  2. Капчи обычно НЕТ: better-auth-регистрация проходит чистым curl/urllib (User-Agent Mozilla). Пробовать API-путь ПЕРЕД любым браузерным флоу.
  3. Session: sign-in возвращает cookie/token на ~30 дней; для последующих API-проб держать cookiejar.

Флоу Remalt (10 сек/акк, лимитов на IP не обнаружено)

  1. Voidash inbox: POST https://api.voidash.com/api/v1/inboxes {"domain":"voidash.bond"} → address + session_key (Bearer). Другие домены (eu.cc и т.п.) могут быть BLOCKED — voidash.bond рабочий.
  2. POST /api/auth/sign-up/email → 200 + user id.
  3. Poll GET /api/v1/messages (Bearer session_key) ~5 сек до письма "Verify your email".
  4. Verify-ссылку брать из поля magic_link полного сообщения (GET /api/v1/messages/{id}), НЕ regex'ом по html-телу: html экранирует & в query-параметрах → токен режется → verify 401. Fallback regex по `https:///api/auth/verify-email?token=*** только если magic_link пуст.
  5. GET magic_link → 302 на главную = успех (302 не ошибка).
  6. POST /api/auth/sign-in/email → session. Выход в accounts.jsonl (email, password, user_id, session_token).

Разведка entitlements/гейтов нового акка

  • GET /api/stripe/subscription → storedCredits: 500, trialEligible: true, но tokenBalance.locked: true — кредиты есть, но за paywall до оплаты.
  • Генерация (/api/chat, /api/image/generate, /api/linkedin/generate-post) → REMALT_FULL_ACCESS_REQUIRED. Гейт-строку greпать в JS-чанках, чтобы отличать «нужен план» от «эндпоинта нет» (HTML404).
  • /api/webpage/analyze работает БЕЗ плана (мелкие URL) — халявная функция.
  • /api/health открыт наружу: сливает supabase project id, build sha, статусы stripe/razorpay — всегда проверять /api/health, /health, /api/status на любом Next.js таргете.

Триалы: маркетинг vs реальность

  • Stripe «7-day free trial» — наебалово: POST /api/stripe/checkout {"item":"starter"} → checkout показывает $29 due today. Перед вбиванием карты ВСЕГДА читать сумму «due today» на странице чекаута (скрин + vision), а не верить лендингу.
  • Razorpay starter_promo = настоящий месяц бесплатно (INR): POST /api/razorpay/order {"item":"starter_promo"} → order с key, subscriptionId, prefill. Оплата только через checkout.razorpay.com/v1/checkout.js (модаль), verify → POST /api/razorpay/verify.
  • Драйвер модали через camoufox на origin сайта (same-origin fetch для verify с cookies): инжектить checkout.js динамически и НЕ полагаться на script.onload в инжектированном контексте — поллить typeof Razorpay !== 'undefined' через setInterval, только потом конструировать实例 и .open(). Handler платежа → fetch /api/razorpay/verify с credentials:'include'.
  • Влад решает сам, вбивать ли карту в платный чекаут: при «триале», который сразу списывает деньги, — clarify (3 варианта: настоящий триал-путь / пробить платный / не вбивать). Он отверг Stripe $29, хотел именно триал.

Питфолы

  • curl в MSYS /tmp vs Windows-путь: файлы, скачанные curl'ом в /tmp, не видны Python-коду с Windows-путями и наоборот — все артефакты держать в C:/Users/User/AppData/Local/Temp или в project-дире, пути сверять.
  • page.reload() сразу после evaluate-fetch sign-in может оборвать session-cookie flow — ждать wait_for_load_state в try/except, не reload вслепую.
  • В репо НЕ пушить card.json/accounts.jsonl (gitignore), скрипты читать секреты из локальных файлов рядом (pathlib.Path(__file__).parent).