/** * protocol.js - ChatAIBot.pro 纯 HTTP 协议注册模块 * * 已确认的 API 端点 (Express + Apache/Ubuntu): * POST /api/register → 201 {"success":true} (注册, 返回 connect.sid session cookie) * POST /api/register/verify → 200 (验证, 需要 {email, token}) * POST /api/login → 200 (登录, 需要 {email, password}) * POST /api/logout → 200 OK * * 注册流程 (逆向自前端 sign-up chunk + module 40933): * 1. POST /api/register { email, password, isAdvertisingAccepted, mainSiteUrl, * utmSource, utmCampaign, connectBusiness, yandexClientId } * Headers: Content-Type: application/json, Accept-Language: en * → 201 {"success":true} + Set-Cookie: connect.sid * 2. 邮件中包含 6 位数字验证码 (token) * 格式: "Your code: 528135" * 3. POST /api/register/verify { email, token, connectBusiness, syncToken } * → 验证完成,账号激活 * 4. POST /api/login { email, password } * → 获取 session */ import { request, get, post, sleep } from './http.js'; import config from './config.js'; const API_BASE = config.siteBase; // ==================== 工具函数 ==================== function humanDelay(baseMs) { return Math.floor(baseMs * (0.8 + Math.random() * 1.7)); } // ==================== 注册步骤 ==================== /** * Step 1: 注册账号 * POST /api/register * 逆向自前端 sign-up-d2a668c82094de73.js + module 40933 * 浏览器发送的完整字段和 headers */ async function stepRegister(account) { console.log(' [Step 1] 提交注册...'); const resp = await post(`${API_BASE}/api/register`, { email: account.email, password: account.password, isAdvertisingAccepted: false, mainSiteUrl: `${config.siteBase}/api`, utmSource: '', utmCampaign: '', connectBusiness: '', yandexClientId: '', }, { headers: { 'Origin': config.siteBase, 'Referer': config.signupUrl, 'Accept-Language': 'en', }, }); const body = resp.text(); console.log(` 状态: ${resp.status}`); console.log(` 响应: ${body.substring(0, 200)}`); if (resp.status === 201 || resp.ok) { const sessionCookie = resp.cookies.get('connect.sid'); console.log(` Session: ${sessionCookie ? sessionCookie.substring(0, 50) + '...' : '无'}`); return { success: true, cookies: resp.cookies }; } let errorMsg = body; try { const json = JSON.parse(body); errorMsg = json.message || json.error || body; } catch {} throw new Error(`注册失败 (${resp.status}): ${errorMsg}`); } /** * Step 2: 从邮箱获取 6 位验证码 * chataibot.pro 的验证码就是 token,是一个 6 位数字 */ async function stepGetVerifyToken(mailProvider, senderFilter) { console.log(' [Step 2] 等待验证邮件...'); const pollOptions = { initialDelay: 8000, maxAttempts: 15, pollInterval: 5000, }; const code = await mailProvider.fetchVerificationCode(senderFilter, pollOptions); if (code) { console.log(` 验证码: ${code}`); return code; } return null; } /** * Step 3: 提交验证码 * POST /api/register/verify { email, token, connectBusiness, syncToken } * 逆向自前端: verify 还发送 connectBusiness 和 syncToken */ async function stepVerify(email, token, cookies) { console.log(' [Step 3] 提交验证...'); const resp = await post(`${API_BASE}/api/register/verify`, { email, token, connectBusiness: '', syncToken: '', }, { cookies, headers: { 'Origin': config.siteBase, 'Referer': `${config.siteBase}/app/verify`, 'Accept-Language': 'en', }, }); const body = resp.text(); console.log(` 状态: ${resp.status}`); console.log(` 响应: ${body.substring(0, 300)}`); if (resp.ok) { let data; try { data = JSON.parse(body); } catch { data = { raw: body }; } return { success: true, data, cookies: resp.cookies }; } throw new Error(`验证失败 (${resp.status}): ${body.substring(0, 200)}`); } /** * Step 4: 登录获取 session * POST /api/login */ async function stepLogin(email, password) { console.log(' [Step 4] 登录...'); await sleep(humanDelay(1000)); const resp = await post(`${API_BASE}/api/login`, { email, password, }, { headers: { 'Origin': config.siteBase, 'Referer': `${config.siteBase}/app/auth/sign-in`, 'Accept-Language': 'en', }, }); const body = resp.text(); console.log(` 状态: ${resp.status}`); console.log(` 响应: ${body.substring(0, 300)}`); if (resp.ok) { let data; try { data = JSON.parse(body); } catch { data = { raw: body }; } return { success: true, data, cookies: resp.cookies, sessionCookie: resp.cookies.get('connect.sid'), }; } console.log(' 登录失败(可能需要先验证邮箱)'); return { success: false, status: resp.status, body }; } // ==================== 主注册流程 ==================== /** * 纯协议注册 ChatAIBot.pro 账号 * * @param {object} account - { email, password, firstName, lastName, fullName } * @param {object} mailProvider - 邮箱 provider 实例 * @returns {object} { success, account, session, error } */ export async function register(account, mailProvider) { console.log(`\n ══════════════════════════════════════════════════`); console.log(` 注册: ${account.email}`); console.log(` ══════════════════════════════════════════════════\n`); try { // Step 1: 注册 await sleep(humanDelay(500)); const regResult = await stepRegister(account); // Step 2: 获取 6 位验证码 const senderFilter = config.senderFilter || 'chataibot'; const token = await stepGetVerifyToken(mailProvider, senderFilter); if (!token) { console.log('\n [警告] 未获取到验证码,账号已创建但未验证'); console.log(' 请手动检查邮箱完成验证'); return { success: true, verified: false, account, session: { cookies: regResult.cookies }, cookies: regResult.cookies, }; } // Step 3: 提交验证 await sleep(humanDelay(1000)); const verifyResult = await stepVerify(account.email, token, regResult.cookies); // Step 4: 登录 await sleep(humanDelay(1500)); const loginResult = await stepLogin(account.email, account.password); return { success: true, verified: true, account, session: loginResult.data || verifyResult.data, cookies: loginResult.cookies || verifyResult.cookies || regResult.cookies, loginSuccess: loginResult.success, }; } catch (e) { console.log(`\n [错误] ${e.message}`); return { success: false, account, error: e.message, }; } } /** * 探测 API (保留供调试用) */ export async function probe() { console.log('\n ┌──────────────────────────────────────────────────┐'); console.log(' │ ChatAIBot.pro API 探测 │'); console.log(' └──────────────────────────────────────────────────┘\n'); const endpoints = [ ['GET', '/api/register', null], ['POST', '/api/register', { email: 'probe@test.com', password: 'Probe123!' }], ['POST', '/api/register/verify', { email: 'probe@test.com', token: 'test' }], ['POST', '/api/login', { email: 'probe@test.com', password: 'Probe123!' }], ['POST', '/api/logout', {}], ]; const results = []; for (const [method, path, body] of endpoints) { try { const opts = { headers: { 'Origin': config.siteBase, 'Referer': config.signupUrl, }, followRedirect: false, timeout: 10000, }; let resp; if (method === 'POST') { resp = await post(`${API_BASE}${path}`, body, opts); } else { resp = await get(`${API_BASE}${path}`, opts); } const text = resp.text(); const status = resp.status; console.log(` ${status} ${method} ${path}`); console.log(` ${text.substring(0, 200)}`); console.log(` Cookies: ${[...resp.cookies.keys()].join(', ') || '无'}`); results.push({ method, path, status, body: text.substring(0, 200) }); } catch (e) { results.push({ method, path, status: 0, error: e.message }); } } return results; }