feat: auto rotate phone on detected errors
This commit is contained in:
+81
-6
@@ -29,6 +29,14 @@
|
||||
let panel = null;
|
||||
let dragState = null;
|
||||
let codePollToken = 0;
|
||||
let autoRotateObserver = null;
|
||||
let autoRotateTimer = null;
|
||||
let autoRotateInFlight = false;
|
||||
let autoRotateEnabled = true;
|
||||
let lastAutoRotateSignature = '';
|
||||
let lastAutoRotateAt = 0;
|
||||
const AUTO_ROTATE_DEBOUNCE_MS = 800;
|
||||
const AUTO_ROTATE_COOLDOWN_MS = 8000;
|
||||
|
||||
function stopCodePolling() {
|
||||
codePollToken += 1;
|
||||
@@ -153,7 +161,7 @@
|
||||
const btn = $('.sb-fetch');
|
||||
if (btn) btn.disabled = true;
|
||||
try {
|
||||
await saveSettings();
|
||||
if (!options.skipSave) await saveSettings();
|
||||
const reason = options.reason || 'manual_replace';
|
||||
const releaseAction = options.releaseAction || (reason === 'phone_number_used' ? 'ban' : 'cancel');
|
||||
setStatus(releaseAction === 'ban' ? '正在释放被拒号码并获取新号...' : '正在取消上一个激活并获取新号...');
|
||||
@@ -180,14 +188,70 @@
|
||||
return String(clone.innerText || clone.textContent || '').slice(-12000);
|
||||
}
|
||||
|
||||
async function detectAndRotate() {
|
||||
function updateAutoRotateToggle() {
|
||||
const btn = $('.sb-auto-toggle');
|
||||
if (!btn) return;
|
||||
btn.textContent = autoRotateEnabled ? '自动切号:开' : '自动切号:关';
|
||||
btn.classList.toggle('sb-auto-on', autoRotateEnabled);
|
||||
}
|
||||
|
||||
function buildAutoRotateSignature(reason, text) {
|
||||
const compact = String(text || '').replace(/\s+/g, ' ').trim();
|
||||
return `${reason}:${compact.slice(-220)}`;
|
||||
}
|
||||
|
||||
async function rotateFromClassifiedError(classified, source = 'manual') {
|
||||
const text = getPageTextForPhoneError();
|
||||
const signature = buildAutoRotateSignature(classified.reason, text);
|
||||
const now = Date.now();
|
||||
if (autoRotateInFlight) return false;
|
||||
if (source === 'auto' && signature === lastAutoRotateSignature && now - lastAutoRotateAt < AUTO_ROTATE_COOLDOWN_MS) {
|
||||
return false;
|
||||
}
|
||||
autoRotateInFlight = true;
|
||||
lastAutoRotateSignature = signature;
|
||||
lastAutoRotateAt = now;
|
||||
try {
|
||||
setStatus(source === 'auto'
|
||||
? `检测到${classified.reason === 'phone_number_used' ? '号码已使用' : '验证码发送失败'},正在自动切号...`
|
||||
: '检测到手机号错误,正在切号...');
|
||||
await fetchAndFill({ reason: classified.reason, releaseAction: classified.releaseAction, skipSave: true });
|
||||
return true;
|
||||
} finally {
|
||||
autoRotateInFlight = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function detectAndRotate(source = 'manual') {
|
||||
const text = getPageTextForPhoneError();
|
||||
const classified = await send('CLASSIFY_PHONE_ERROR', { text });
|
||||
if (!classified.matched) {
|
||||
setStatus('未检测到明确的手机号错误,可用“手动换号”。', true);
|
||||
return;
|
||||
if (source !== 'auto') setStatus('未检测到明确的手机号错误。', true);
|
||||
return false;
|
||||
}
|
||||
await fetchAndFill({ reason: classified.reason, releaseAction: classified.releaseAction });
|
||||
return rotateFromClassifiedError(classified, source);
|
||||
}
|
||||
|
||||
function scheduleAutoRotateCheck() {
|
||||
if (!autoRotateEnabled || autoRotateInFlight) return;
|
||||
if (autoRotateTimer) clearTimeout(autoRotateTimer);
|
||||
autoRotateTimer = setTimeout(() => {
|
||||
autoRotateTimer = null;
|
||||
detectAndRotate('auto').catch((error) => setStatus(error.message || String(error), true));
|
||||
}, AUTO_ROTATE_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
function startAutoRotateObserver() {
|
||||
if (autoRotateObserver) return;
|
||||
autoRotateObserver = new MutationObserver((mutations) => {
|
||||
if (!autoRotateEnabled) return;
|
||||
if (mutations.some((m) => m.target && panel && panel.contains(m.target))) return;
|
||||
scheduleAutoRotateCheck();
|
||||
});
|
||||
if (document.body) {
|
||||
autoRotateObserver.observe(document.body, { childList: true, subtree: true, characterData: true });
|
||||
}
|
||||
window.addEventListener('focus', scheduleAutoRotateCheck);
|
||||
}
|
||||
|
||||
async function cancelActive() {
|
||||
@@ -328,6 +392,7 @@
|
||||
#${PANEL_ID} code { color: #67e8f9; user-select: all; }
|
||||
#${PANEL_ID} .sb-hint { margin: 7px 0 0; color: #94a3b8; font-size: 12px; }
|
||||
#${PANEL_ID} .sb-status { color: #bbf7d0; }
|
||||
#${PANEL_ID} .sb-auto-on { border-color: #22c55e; color: #bbf7d0; }
|
||||
`;
|
||||
document.documentElement.appendChild(style);
|
||||
}
|
||||
@@ -342,6 +407,7 @@
|
||||
<button class="sb-close" type="button" title="隐藏">×</button>
|
||||
</div>
|
||||
<button class="sb-fetch sb-primary sb-top-fetch" type="button">获取并填入</button>
|
||||
<button class="sb-auto-toggle sb-auto-on" type="button">自动切号:开</button>
|
||||
<label>API Key <input class="sb-api-key" type="password" placeholder="SMSBower API Key" /></label>
|
||||
<label>API 地址 <input class="sb-base-url" type="url" /></label>
|
||||
<div class="sb-row">
|
||||
@@ -376,13 +442,22 @@
|
||||
document.documentElement.appendChild(panel);
|
||||
bindPanelEvents();
|
||||
await loadSettingsIntoPanel();
|
||||
updateAutoRotateToggle();
|
||||
startAutoRotateObserver();
|
||||
scheduleAutoRotateCheck();
|
||||
}
|
||||
|
||||
function bindPanelEvents() {
|
||||
$('.sb-close').addEventListener('click', () => { panel.style.display = 'none'; });
|
||||
$('.sb-save').addEventListener('click', saveSettings);
|
||||
$('.sb-fetch').addEventListener('click', () => fetchAndFill({ reason: 'manual_replace', releaseAction: 'cancel' }));
|
||||
$('.sb-rotate-detect').addEventListener('click', detectAndRotate);
|
||||
$('.sb-auto-toggle').addEventListener('click', () => {
|
||||
autoRotateEnabled = !autoRotateEnabled;
|
||||
updateAutoRotateToggle();
|
||||
setStatus(autoRotateEnabled ? '自动切号已开启' : '自动切号已关闭');
|
||||
if (autoRotateEnabled) scheduleAutoRotateCheck();
|
||||
});
|
||||
$('.sb-rotate-detect').addEventListener('click', () => detectAndRotate('manual'));
|
||||
$('.sb-rotate-used').addEventListener('click', () => fetchAndFill({ reason: 'phone_number_used', releaseAction: 'ban' }));
|
||||
$('.sb-cancel').addEventListener('click', cancelActive);
|
||||
$('.sb-code').addEventListener('click', fetchAndCopyCode);
|
||||
|
||||
Reference in New Issue
Block a user