// Smart account-text parser — ported from xinghuo-windsurf accountTextParser.js // (users own project). Pure string parsing, no network. Recognizes mixed formats: // devin-session-token$ / show-auth-token URL / Firebase-refresh-JWT / email----password / // labeled pairs (邮箱:xxx + Token:auth1_xxx). CommonJS→ESM: exports at bottom. 'use strict'; function isValidEmail(arg1) { if (!arg1 || typeof arg1 !== "string") { return false; } const trimResult = arg1.trim(); if (trimResult.length < 5 || trimResult.length > 254) { return false; } if (/[\s|;,,;\t]/.test(trimResult)) { return false; } return /^[A-Za-z0-9._+\-]+@[A-Za-z0-9](?:[A-Za-z0-9\-]*[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9\-]*[A-Za-z0-9])?)*\.[A-Za-z]{2,}$/.test(trimResult); } function stripWxHints(arg1) { if (!arg1) { return arg1; } let v2; let v3 = arg1; do { v2 = v3; v3 = v3.replace(/[((]\s*(?:无任何空格|去掉点|去点|去掉空格|无空格)\s*[))]/g, "").replace(/\s+账号管理器\s*[::==]\s*\S+/, "").trim(); } while (v3 !== v2 && v3.length > 0); return v3; } function isNoiseLine(arg1) { if (!arg1) { return true; } if (/^(?:您的|您好|自动发货|订单编号|订单号|交易号|发货时间|订单时间|发货成功|交易成功|尊敬的)/.test(arg1)) { return true; } if (/^\s*\d{4}[\-\/年]\d{1,2}[\-\/月]\d{1,2}[\s\d::年月日时分秒]*$/.test(arg1)) { return true; } if (/^(?:账号管理器|管理面板|管理后台|官网|官方网站|官方地址|商城|售后|客服|发货)\s*[::==]/.test(arg1)) { return true; } return false; } const RE_TOKEN_PREFIX = /^(devin-session-token\$|auth1_|sk-)/i; const RE_JWT = /^eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+$/; // Any absolute URL scheme, not just http(s): the desktop app's sign-in // callback is `windsurf://codeium.windsurf?access_token=…` (F4). const ABSOLUTE_URL_RE = /^[a-z][a-z0-9+.\-]*:\/\//i; function looksLikeToken(arg1) { if (!arg1) { return false; } if (arg1.includes("@")) { return false; } if (/[\s|]|----/.test(arg1)) { return false; } if (RE_TOKEN_PREFIX.test(arg1)) { return true; } if (RE_JWT.test(arg1)) { return true; } if (arg1.length >= 60 && /^[A-Za-z0-9_\-\.\$\/+=]+$/.test(arg1)) { return true; } return false; } function tryPair(arg1, arg2) { const trimResult = (arg1 || "").trim(); const trimResult2 = (arg2 || "").trim(); if (!trimResult || !trimResult2) { return null; } const isvalidemailResult = isValidEmail(trimResult); const isvalidemailResult2 = isValidEmail(trimResult2); if (isvalidemailResult && !isvalidemailResult2) { return { email: trimResult, password: trimResult2 }; } if (isvalidemailResult2 && !isvalidemailResult) { return { email: trimResult2, password: trimResult }; } if (isvalidemailResult && isvalidemailResult2) { return { email: trimResult, password: trimResult2 }; } return null; } function parseSingleLine(arg1) { if (/----+/.test(arg1)) { const searchResult = arg1.search(/----+/); const matchResult2 = arg1.substring(searchResult).match(/^----+/); if (matchResult2) { const trypairResult = tryPair(arg1.substring(0, searchResult), arg1.substring(searchResult + matchResult2[0].length)); if (trypairResult) { return trypairResult; } } } if (arg1.includes("\t")) { const indexofResult = arg1.indexOf("\t"); const trypairResult = tryPair(arg1.substring(0, indexofResult), arg1.substring(indexofResult + 1)); if (trypairResult) { return trypairResult; } } if (!ABSOLUTE_URL_RE.test(arg1)) { const searchResult = arg1.search(/[::==]/); if (searchResult !== -1) { const trypairResult = tryPair(arg1.substring(0, searchResult), arg1.substring(searchResult + 1)); if (trypairResult) { return trypairResult; } } } if (arg1.includes("|")) { const indexofResult = arg1.indexOf("|"); const trypairResult = tryPair(arg1.substring(0, indexofResult), arg1.substring(indexofResult + 1)); if (trypairResult) { return trypairResult; } } for (const v1 of [",", ";", ",", ";"]) { if (arg1.includes(v1)) { const splitResult = arg1.split(v1); if (splitResult.length === 2) { const trypairResult = tryPair(splitResult[0], splitResult[1]); if (trypairResult) { return trypairResult; } } } } const matchResult = arg1.match(/^(\S+)\s+(\S.*?)\s*$/); if (matchResult) { const trypairResult = tryPair(matchResult[1], matchResult[2]); if (trypairResult) { return trypairResult; } } return null; } const RE_LABEL_EMAIL = /^\s*(?:邮箱|邮件|账号|账户|帐号|帐户|用户名|用户名称|用户|登录名|登陆名|登录账号|登陆账号|登录账户|卡号|号码|账户名|e[\-\s]?mail|email|account|user(?:name)?|login|mail|id|number|num)\s*\d*\s*[::==]\s*/i; const RE_LABEL_PASS = /^\s*(?:密码|登录密码|登陆密码|口令|秘钥|密钥|卡密|令牌|password|pass(?:word|wd)?|pwd|secret|key|token|access(?:[\-_]?token)?)\s*\d*\s*[::==]\s*/i; function parseAccountText(content) { const arr = []; const arr2 = []; const arr3 = []; const arr4 = []; if (!content || typeof content !== "string") { return { accounts: arr, tokens: arr2, tokenPairs: arr3, githubAccounts: arr4 }; } const trimResult = content.trim(); if (trimResult.startsWith("[") && trimResult.endsWith("]")) { try { const parseResult = JSON.parse(trimResult); if (Array.isArray(parseResult) && parseResult.length > 0) { let v12 = true; const arr6 = []; const arr7 = []; const arr8 = []; const arr9 = []; for (const v13 of parseResult) { if (!v13 || typeof v13 !== "object") { v12 = false; break; } const v14 = v13.username || v13.user || v13.login; const v22 = v13.password || v13.pass || v13.pwd; const v32 = v13.totp_secret || v13.totp || v13.totpSecret; if (v14 && v22 && v32) { arr9.push({ username: String(v14).trim(), password: String(v22).trim(), totpSecret: String(v32).trim() }); continue; } const v4 = v13.email || v13.username || v13.account || v13.user || v13.mail || v13.login; const v5 = v13.password || v13.pass || v13.pwd || v13.passwd || v13.secret; const v6 = v13.token || v13.sessionToken || v13.session_token || v13.authToken || v13.access_token; if (v4 && v5 && isValidEmail(String(v4).trim())) { arr6.push({ email: String(v4).trim(), password: String(v5).trim() }); } else if (v6 && v4 && isValidEmail(String(v4).trim())) { arr8.push({ email: String(v4).trim(), token: String(v6).trim() }); } else if (v6) { arr7.push(String(v6).trim()); } else { v12 = false; break; } } if (v12 && (arr6.length > 0 || arr7.length > 0 || arr8.length > 0 || arr9.length > 0)) { return { accounts: arr6, tokens: arr7, tokenPairs: arr8, githubAccounts: arr9 }; } } } catch (err) {} } const arr5 = []; for (const v12 of content.split(/\r?\n/)) { let trimResult2 = v12.trim(); if (!trimResult2 || trimResult2.startsWith("#") || trimResult2.startsWith("//")) { continue; } trimResult2 = stripWxHints(trimResult2); if (!trimResult2) { continue; } if (isNoiseLine(trimResult2)) { continue; } if (/----/.test(trimResult2)) { const mapResult = trimResult2.split(/----+/).map(arg1 => arg1.trim()); if (mapResult.length === 3 && mapResult[0] && mapResult[1] && mapResult[2]) { arr4.push({ username: mapResult[0], password: mapResult[1], totpSecret: mapResult[2] }); continue; } } if (ABSOLUTE_URL_RE.test(trimResult2)) { try { const inner = unwrapPastedSecret(trimResult2); arr5.push({ type: "token", raw: inner }); } catch { // Keep the URL so import-text reports failed (ERR_NO_TOKEN_IN_INPUT) // instead of added=0 skipped=0 failed=0. arr5.push({ type: "token", raw: trimResult2 }); } continue; } if (looksLikeToken(trimResult2)) { arr5.push({ type: "token", raw: trimResult2 }); continue; } if (trimResult2.startsWith("{") && trimResult2.endsWith("}")) { try { const parseResult = JSON.parse(trimResult2); const v13 = parseResult.email || parseResult.username || parseResult.account || parseResult.user || parseResult.mail || parseResult.login; const v22 = parseResult.password || parseResult.pass || parseResult.pwd || parseResult.passwd || parseResult.secret; if (v13 && v22 && isValidEmail(String(v13).trim())) { arr5.push({ type: "pair", email: String(v13).trim(), password: String(v22).trim() }); continue; } const v32 = parseResult.token || parseResult.sessionToken || parseResult.session_token || parseResult.authToken || parseResult.access_token; if (v32) { arr5.push({ type: "token", raw: String(v32).trim() }); continue; } } catch (err) {} } const matchResult = trimResult2.match(RE_LABEL_PASS); if (matchResult) { const trimResult3 = trimResult2.substring(matchResult[0].length).trim(); if (trimResult3) { if (ABSOLUTE_URL_RE.test(trimResult3)) { try { arr5.push({ type: "token", raw: unwrapPastedSecret(trimResult3) }); } catch { arr5.push({ type: "token", raw: trimResult3 }); } } else if (looksLikeToken(trimResult3)) { arr5.push({ type: "token", raw: trimResult3 }); } else { arr5.push({ type: "pass", password: trimResult3 }); } continue; } continue; } const matchResult2 = trimResult2.match(RE_LABEL_EMAIL); if (matchResult2) { const trimResult3 = trimResult2.substring(matchResult2[0].length).trim(); if (isValidEmail(trimResult3)) { arr5.push({ type: "email", email: trimResult3 }); continue; } trimResult2 = trimResult3 || trimResult2; } const parsesinglelineResult = parseSingleLine(trimResult2); if (parsesinglelineResult) { arr5.push({ type: "pair", email: parsesinglelineResult.email, password: parsesinglelineResult.password }); continue; } if (isValidEmail(trimResult2)) { arr5.push({ type: "email", email: trimResult2 }); continue; } if (trimResult2.length >= 40 && /^[A-Za-z0-9_\-\.\$\/+=]+$/.test(trimResult2) && !trimResult2.includes("@")) { arr5.push({ type: "token", raw: trimResult2 }); continue; } } let v1 = null; let v2 = null; let v3 = null; for (const v12 of arr5) { if (v12.type === "pair") { if (v12.email && v12.password && isValidEmail(v12.email)) { arr.push({ email: v12.email, password: v12.password }); } v1 = null; v2 = null; } else if (v12.type === "email") { if (v3) { arr3.push({ email: v12.email, token: v3 }); v3 = null; v1 = null; } else if (v2) { arr.push({ email: v12.email, password: v2 }); v2 = null; v1 = null; } else { v1 = v12.email; } } else if (v12.type === "pass") { if (v1) { arr.push({ email: v1, password: v12.password }); v1 = null; } else { v2 = v12.password; } } else if (v12.type === "token") { if (v12.raw) { if (v1) { arr3.push({ email: v1, token: v12.raw }); v1 = null; } else { if (v3) { arr2.push(v3); } v3 = v12.raw; } } } } if (v3) { arr2.push(v3); } return { accounts: arr, tokens: arr2, tokenPairs: arr3, githubAccounts: arr4 }; } // Pull a token out of a show-auth-token / OAuth redirect URL. Bare strings // pass through. A URL with no token query/hash throws ERR_NO_TOKEN_IN_INPUT // so POST /accounts does not send the whole URL to RegisterUser (#257). // // Any absolute scheme counts, not just http(s): the desktop app's callback is // `windsurf://codeium.windsurf?access_token=…` and it used to be handed to // RegisterUser verbatim as an 88-char "token" (F4). function unwrapPastedSecret(input) { const raw = String(input || '').trim(); if (!raw) return ''; if (!ABSOLUTE_URL_RE.test(raw)) return raw; try { const u = new URL(raw); const pick = (params) => (params.get('access_token') || params.get('token') || params.get('auth_token') || '').trim(); const fromQuery = pick(u.searchParams); if (fromQuery) return fromQuery; const frag = u.hash.startsWith('#') ? u.hash.slice(1) : u.hash; if (frag) { const fromHash = pick(new URLSearchParams(frag)); if (fromHash) return fromHash; } } catch (e) { if (e && e.code === 'ERR_NO_TOKEN_IN_INPUT') throw e; } const err = new Error('ERR_NO_TOKEN_IN_INPUT'); err.code = 'ERR_NO_TOKEN_IN_INPUT'; throw err; } function classifyToken(arg1) { const trimResult = (arg1 || "").trim(); if (!trimResult) { return "unknown"; } if (trimResult.startsWith("devin-session-token$")) { return "session"; } if (trimResult.startsWith("auth1_") && trimResult.length >= 20) { return "auth1"; } if (trimResult.length > 100 && !trimResult.includes(" ") && !trimResult.includes("@") && !trimResult.startsWith("devin-") && !trimResult.startsWith("auth1_")) { return "refresh"; } if (/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(trimResult) && trimResult.length > 100) { return "refresh"; } return "unknown"; } export { parseAccountText, isValidEmail, looksLikeToken, classifyToken, unwrapPastedSecret }; // Whitelabel: decode a devin-session-token$ payload to harvest email/exp // without any network call (ported from devinSessionImporter.js). auth1_ tokens // are not JWTs → returns nulls. export function parseDevinJwtPayload(t) { const o = { email: null, sub: null, exp: null }; if (!t || typeof t !== 'string') return o; let v = t; if (t.startsWith('devin-session-token$')) v = t.slice('devin-session-token$'.length); else if (t.startsWith('auth1_')) return o; const s = v.split('.'); if (s.length < 2) return o; try { let b = s[1].replace(/-/g, '+').replace(/_/g, '/'); while (b.length % 4) b += '='; const p = JSON.parse(Buffer.from(b, 'base64').toString('utf8')); return { email: typeof p.email === 'string' ? p.email : null, sub: typeof p.sub === 'string' ? p.sub : null, exp: typeof p.exp === 'number' ? p.exp : null }; } catch { return o; } }