domain setup
This commit is contained in:
+154
-10
@@ -15,7 +15,7 @@ import { readFileSync, appendFileSync, existsSync } from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
|
||||
import { MimoRegistration } from './index.js';
|
||||
import { MimoRegistration, parseProxy, loadProxyList } from './index.js';
|
||||
import './extras.js'; // attach getReferralCode
|
||||
import { generateFingerprint, buildInitScript, buildExtraHeaders } from './fingerprint.js';
|
||||
|
||||
@@ -43,6 +43,27 @@ const outputFile = outputIdx !== -1
|
||||
|
||||
const failLog = join(outputDir, 'regis-fail.log');
|
||||
|
||||
const proxyIdx = args.indexOf('--proxy');
|
||||
let proxyList = [];
|
||||
if (proxyIdx !== -1) {
|
||||
const nextArg = args[proxyIdx + 1];
|
||||
let proxyPath = 'proxy.txt';
|
||||
if (nextArg && !nextArg.startsWith('-')) {
|
||||
proxyPath = nextArg;
|
||||
}
|
||||
const resolvedPath = join(__dirname, proxyPath);
|
||||
if (existsSync(resolvedPath)) {
|
||||
proxyList = loadProxyList(resolvedPath);
|
||||
console.log(`Loaded ${proxyList.length} proxies from ${proxyPath}`);
|
||||
} else if (nextArg && !nextArg.startsWith('-')) {
|
||||
proxyList = [nextArg];
|
||||
} else {
|
||||
console.log(`Proxy option enabled but ${proxyPath} not found.`);
|
||||
}
|
||||
} else if (config.proxy) {
|
||||
proxyList = [config.proxy];
|
||||
}
|
||||
|
||||
// ---- File helpers -----------------------------------------------------
|
||||
|
||||
function saveResult(row) {
|
||||
@@ -76,6 +97,12 @@ async function runIteration(idx, total) {
|
||||
|
||||
// Per-iter: clone config + set referral link to direct URL (no referral parameter)
|
||||
const iterConfig = JSON.parse(JSON.stringify(config));
|
||||
if (proxyList && proxyList.length > 0) {
|
||||
const selectedProxy = proxyList[idx % proxyList.length];
|
||||
iterConfig.proxy = selectedProxy;
|
||||
const cleanProxyName = selectedProxy.split('@').pop();
|
||||
console.log(` ↳ Using proxy [${(idx % proxyList.length) + 1}/${proxyList.length}]: ${cleanProxyName}`);
|
||||
}
|
||||
iterConfig.xiaomi.inviteCode = '';
|
||||
iterConfig.xiaomi.referralLink = 'https://platform.xiaomimimo.com/';
|
||||
|
||||
@@ -95,12 +122,12 @@ async function runIteration(idx, total) {
|
||||
|
||||
try {
|
||||
// 1. Tempmail
|
||||
console.log('[1/7] Creating temporary email...');
|
||||
console.log('[1/8] Creating temporary email...');
|
||||
email = await reg.tempmail.createInbox();
|
||||
console.log(`✓ Email: ${email}`);
|
||||
|
||||
// 2. Browser
|
||||
console.log('[2/7] Launching browser...');
|
||||
console.log('[2/8] Launching browser...');
|
||||
const fp = generateFingerprint();
|
||||
reg.fingerprint = fp;
|
||||
console.log(` ↳ Chrome ${fp.chromeMajor}, ${fp.viewport.width}x${fp.viewport.height}, ${fp.locale}/${fp.timezone}`);
|
||||
@@ -108,6 +135,7 @@ async function runIteration(idx, total) {
|
||||
reg.browser = await chromium.launch({
|
||||
headless: iterConfig.browser.headless,
|
||||
channel: 'chrome',
|
||||
proxy: parseProxy(iterConfig.proxy),
|
||||
args: [
|
||||
`--window-size=${fp.viewport.width},${fp.viewport.height}`,
|
||||
'--disable-blink-features=AutomationControlled',
|
||||
@@ -134,31 +162,135 @@ async function runIteration(idx, total) {
|
||||
};
|
||||
|
||||
// 3. Open registration page directly
|
||||
console.log('[3/7] Opening registration page...');
|
||||
console.log('[3/8] Opening registration page...');
|
||||
await reg.page.goto(iterConfig.xiaomi.referralLink, {
|
||||
waitUntil: 'networkidle',
|
||||
timeout: iterConfig.browser.timeout,
|
||||
});
|
||||
|
||||
// 4. Sign up form
|
||||
console.log('[4/7] Filling Sign up form...');
|
||||
console.log('[4/8] Filling Sign up form...');
|
||||
await reg.fillRegistrationForm(email);
|
||||
await reg.submitRegistration();
|
||||
|
||||
// 5. Captcha
|
||||
console.log('[5/7] Handling captcha...');
|
||||
console.log('[5/8] Handling captcha...');
|
||||
await reg.handleXiaomiCaptcha();
|
||||
await reg.handleImageCaptcha();
|
||||
|
||||
// 6. Verify email
|
||||
console.log('[6/7] Verifying email...');
|
||||
console.log('[6/8] Verifying email...');
|
||||
await reg.verifyEmail(email);
|
||||
|
||||
// 7. Skip Redeem
|
||||
console.log('[Info] Skipping redeem/enter invite code step.');
|
||||
// 7. Check Balance (Terms modal will be handled here if opened)
|
||||
console.log('[7/8] Checking balance...');
|
||||
try {
|
||||
// 1. Klik menu "Console" dulu — biar navigasi-nya mirip user beneran
|
||||
await reg.clickConsoleMenu();
|
||||
|
||||
// 2. Navigasi ke balance page jika belum
|
||||
let url = reg.page.url();
|
||||
if (!url.includes('/console/balance')) {
|
||||
console.log(` Not on balance page yet (current: ${url}), navigating...`);
|
||||
|
||||
const balanceClicked = await reg.page.evaluate(() => {
|
||||
const links = Array.from(document.querySelectorAll('a, [role="link"], li, [role="menuitem"]'));
|
||||
const target = links.find(el => {
|
||||
const txt = (el.textContent || '').trim();
|
||||
return /^Balance$/i.test(txt) && el.offsetHeight > 0;
|
||||
});
|
||||
if (target) {
|
||||
target.scrollIntoView({ block: 'center' });
|
||||
target.click();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (balanceClicked) {
|
||||
console.log(' ✓ Clicked Balance link in console sidebar');
|
||||
await reg.page.waitForURL(/\/console\/balance/, { timeout: 8000 }).catch(() => {});
|
||||
await reg.page.waitForLoadState('networkidle', { timeout: 8000 }).catch(() => {});
|
||||
} else {
|
||||
console.log(' ! Balance link not found, falling back to direct goto...');
|
||||
await reg.page.goto('https://platform.xiaomimimo.com/console/balance', {
|
||||
waitUntil: 'networkidle',
|
||||
timeout: iterConfig.browser.timeout,
|
||||
});
|
||||
}
|
||||
}
|
||||
await reg.page.waitForTimeout(2500);
|
||||
|
||||
await reg.handleOAuthRedirect();
|
||||
await reg.page.waitForTimeout(2000);
|
||||
|
||||
// Close cookies banner if any
|
||||
console.log(' Checking for cookies banner...');
|
||||
const acceptCookiesBtn = await reg.page.waitForSelector('button:has-text("Accept All"), button:has-text("Accept"), button:has-text("Allow All")', { timeout: 4000 }).catch(() => null);
|
||||
if (acceptCookiesBtn) {
|
||||
await acceptCookiesBtn.click({ force: true }).catch(() => {});
|
||||
console.log(' ✓ Accepted cookies banner');
|
||||
await reg.page.waitForTimeout(2000);
|
||||
}
|
||||
|
||||
// Terms modal
|
||||
await reg.handleTermsModal();
|
||||
|
||||
// Overlays
|
||||
await reg.waitForOverlaysGone();
|
||||
|
||||
// Take screenshot
|
||||
await reg.page.screenshot({ path: 'screenshot-balance.png', fullPage: false });
|
||||
console.log(' ✓ Captured screenshot-balance.png');
|
||||
|
||||
// Cek apakah ada notifikasi risk control / block/ restricted
|
||||
const restrictionMsg = await reg.page.evaluate(() => {
|
||||
const text = document.body.innerText || '';
|
||||
const patterns = [
|
||||
/risk\s*control\s*restriction/i,
|
||||
/account\s+has\s+risk\s+control/i,
|
||||
/contact\s+customer\s+service/i,
|
||||
/account\s+(is\s+)?restricted/i,
|
||||
];
|
||||
for (const re of patterns) {
|
||||
const m = text.match(new RegExp('([^\\n]{0,200}' + re.source + '[^\\n]{0,200})', re.flags));
|
||||
if (m) return m[1].trim();
|
||||
}
|
||||
return null;
|
||||
}).catch(() => null);
|
||||
|
||||
if (restrictionMsg) {
|
||||
console.log(' ❌ ACCOUNT RESTRICTED:');
|
||||
console.log(` ${restrictionMsg}`);
|
||||
try {
|
||||
await reg.page.screenshot({
|
||||
path: `error-restriction-${Date.now()}.png`,
|
||||
fullPage: true,
|
||||
});
|
||||
} catch (e) {}
|
||||
const err = new Error(`ACCOUNT_RESTRICTED: ${restrictionMsg}`);
|
||||
err.code = 'ACCOUNT_RESTRICTED';
|
||||
err.restrictionMsg = restrictionMsg;
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Read balance
|
||||
const balance = await reg.readBalance();
|
||||
console.log(` 💰 Balance: $${balance !== null ? balance.toFixed(2) : 'unknown'}`);
|
||||
if (balance === 0) {
|
||||
const err = new Error('Balance is $0.00');
|
||||
err.code = 'BALANCE_ZERO';
|
||||
throw err;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.code === 'ACCOUNT_RESTRICTED' || e.code === 'BALANCE_ZERO') {
|
||||
throw e;
|
||||
}
|
||||
console.log(` ! check balance error (lanjut): ${e.message}`);
|
||||
}
|
||||
|
||||
// 8. Create API key (atau ambil existing)
|
||||
console.log('[7/7] Creating API key...');
|
||||
console.log('[8/8] Creating API key...');
|
||||
try {
|
||||
apiKey = await reg.createApiKey();
|
||||
console.log(`✓ API key: ${apiKey || '(none)'}`);
|
||||
@@ -201,6 +333,18 @@ async function runIteration(idx, total) {
|
||||
|
||||
return { ok: true, email, refCode, apiKey };
|
||||
} catch (err) {
|
||||
if (err.code === 'BALANCE_ZERO') {
|
||||
console.log(`\n⚠ Regis Iteration ${idx + 1} skipped: ${err.message}`);
|
||||
logFail(email, err.message);
|
||||
return {
|
||||
ok: false,
|
||||
email,
|
||||
error: err.message,
|
||||
restricted: false,
|
||||
stopReason: err.code,
|
||||
};
|
||||
}
|
||||
|
||||
console.error(`\n❌ Regis Iteration ${idx + 1} failed: ${err.message}`);
|
||||
if (reg.page) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user