feat: auto submit after filling phone

This commit is contained in:
chick
2026-05-31 17:23:30 +08:00
parent 6424862cc9
commit 2b127d070b
2 changed files with 58 additions and 6 deletions
+3 -3
View File
@@ -1,13 +1,13 @@
SMSBower Phone Fill Tool SMSBower Phone Fill Tool
用途:点击扩展图标后,在当前网页右上角打开一个常驻悬浮窗。点一次“获取并填入”就获取一个 SMSBower 手机号,自动填入当前页面最像手机号的输入框,并复制到剪贴板。再次获取会先释放上一个激活,再拿新号替换页面输入框。 用途:点击扩展图标后,在当前网页右上角打开一个常驻悬浮窗。点一次“获取并填入”就获取一个 SMSBower 手机号,自动填入当前页面最像手机号的输入框复制到剪贴板,并自动点击页面上的下一步/发送验证码按钮。再次获取会先释放上一个激活,再拿新号替换页面输入框并自动提交
本版已集成 FlowPilot 同款自动切号机制: 本版已集成 FlowPilot 同款自动切号机制:
- 悬浮窗打开后默认开启“自动切号:开”。 - 悬浮窗打开后默认开启“自动切号:开”。
- 页面提示“该电话/手机号已被使用、已绑定、已注册”时,只要确认是当前新号码触发的错误,插件会自动切换下一个号码;旧号按被拒原因释放,新号自动填入并复制。 - 页面提示“该电话/手机号已被使用、已绑定、已注册”时,只要确认是当前新号码触发的错误,插件会自动切换下一个号码;旧号按被拒原因释放,新号自动填入并复制。
- 页面提示“无法向此电话号码发送验证码”等发送失败时,插件会自动按可恢复失败换号。 - 页面提示“无法向此电话号码发送验证码”等发送失败时,插件会自动按可恢复失败换号。
- “检测报错换号”和“已使用换号”仍保留为手动兜底按钮。 - “检测报错换号”和“已使用换号”仍保留为手动兜底按钮。
- 仍然只负责填号/查码/复制,不自动点击目标页面继续按钮 - 填号后会自动寻找并点击目标页面上的“下一步/继续/发送验证码/提交”等按钮;如果找不到按钮,会尝试提交表单或发送 Enter
安装/更新: 安装/更新:
1. 打开 Chrome/Edge 扩展管理页。 1. 打开 Chrome/Edge 扩展管理页。
@@ -20,7 +20,7 @@ SMSBower Phone Fill Tool
2. 点浏览器工具栏里的“SMSBower 悬浮填号”扩展图标。 2. 点浏览器工具栏里的“SMSBower 悬浮填号”扩展图标。
3. 页面右上角会出现悬浮窗,可拖动。 3. 页面右上角会出现悬浮窗,可拖动。
4. 填 SMSBower API Key、项目代码、价格上下限、国家顺序。 4. 填 SMSBower API Key、项目代码、价格上下限、国家顺序。
5. 顶部“获取并填入”会立即拿号填入。 5. 顶部“获取并填入”会立即拿号填入、复制,并自动提交/点击发送验证码
6. 再点一次“获取并填入”会释放上一个激活,替换输入框为新手机号。 6. 再点一次“获取并填入”会释放上一个激活,替换输入框为新手机号。
7. 如果目标页面拒绝号码,保持悬浮窗打开即可:插件会自动扫描页面错误文本并切换下一个号码。 7. 如果目标页面拒绝号码,保持悬浮窗打开即可:插件会自动扫描页面错误文本并切换下一个号码。
- “自动切号:开/关”可以临时启停自动扫描; - “自动切号:开/关”可以临时启停自动扫描;
+55 -3
View File
@@ -79,7 +79,58 @@
const input = findBestInput(); const input = findBestInput();
if (!input) throw new Error('当前页面没有找到可填写的输入框。请先点一下目标输入框再获取。'); if (!input) throw new Error('当前页面没有找到可填写的输入框。请先点一下目标输入框再获取。');
setValue(input, phoneNumber); setValue(input, phoneNumber);
return { phoneNumber, tag: input.tagName, name: input.name || '', id: input.id || '' }; return { phoneNumber, input, tag: input.tagName, name: input.name || '', id: input.id || '' };
}
function scoreSubmitButton(button, input) {
if (!button || panel?.contains(button)) return -1000;
const style = window.getComputedStyle(button);
const rect = button.getBoundingClientRect();
if (button.disabled || style.visibility === 'hidden' || style.display === 'none' || rect.width <= 0 || rect.height <= 0) return -1000;
const text = [
button.innerText, button.textContent, button.value, button.name, button.id,
button.getAttribute('aria-label'), button.getAttribute('title')
].join(' ').toLowerCase();
let score = 0;
if (/下一步|继续|发送验证码|获取验证码|发送代码|发送短信|验证|提交|next|continue|send\s*(code|sms)?|verify|submit/.test(text)) score += 100;
if (/取消|返回|back|cancel|关闭|close|skip|跳过|resend|重发/.test(text)) score -= 140;
if (button.type === 'submit') score += 35;
if (input) {
const inputRect = input.getBoundingClientRect();
const dy = rect.top - inputRect.bottom;
const dx = Math.abs((rect.left + rect.right) / 2 - (inputRect.left + inputRect.right) / 2);
if (dy >= -20 && dy < 260) score += Math.max(0, 60 - dy / 5);
if (dx < 360) score += Math.max(0, 30 - dx / 20);
}
return score;
}
function findSubmitButton(input) {
const formButton = input?.form?.querySelector('button[type="submit"], input[type="submit"]');
const candidates = Array.from(document.querySelectorAll('button, input[type="button"], input[type="submit"], [role="button"]'))
.filter((el) => !panel || !panel.contains(el));
if (formButton && !candidates.includes(formButton)) candidates.unshift(formButton);
const ranked = candidates.map((el) => ({ el, score: scoreSubmitButton(el, input) })).sort((a, b) => b.score - a.score);
return ranked[0]?.score > 30 ? ranked[0].el : null;
}
async function autoSubmitPhone(input) {
await sleep(250);
const button = findSubmitButton(input);
if (button) {
button.scrollIntoView?.({ block: 'center', inline: 'center' });
button.click();
return { method: 'button', text: String(button.innerText || button.textContent || button.value || button.getAttribute('aria-label') || '').trim().slice(0, 40) };
}
const form = input?.form;
if (form) {
if (typeof form.requestSubmit === 'function') form.requestSubmit();
else form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
return { method: 'form' };
}
input?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', bubbles: true }));
input?.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter', code: 'Enter', bubbles: true }));
return { method: 'enter' };
} }
function send(type, payload = {}) { function send(type, payload = {}) {
@@ -166,13 +217,14 @@
const res = await send('FETCH_NEXT_PHONE', { reason, releaseAction }); const res = await send('FETCH_NEXT_PHONE', { reason, releaseAction });
const phone = res.activation.phoneNumber; const phone = res.activation.phoneNumber;
await copyText(phone); await copyText(phone);
fillPhone(phone); const filled = fillPhone(phone);
$('.sb-current-phone').textContent = phone; $('.sb-current-phone').textContent = phone;
lastErroredPhoneNumber = ''; lastErroredPhoneNumber = '';
$('.sb-current-id').textContent = res.activation.activationId; $('.sb-current-id').textContent = res.activation.activationId;
const codeNode = $('.sb-current-code'); const codeNode = $('.sb-current-code');
if (codeNode) codeNode.textContent = '无'; if (codeNode) codeNode.textContent = '无';
setStatus(`已切换、填入并复制:${phone}`); const submit = await autoSubmitPhone(filled.input);
setStatus(`已切换、填入、复制并自动提交:${phone}${submit.text ? `${submit.text}` : ''}`);
} catch (error) { } catch (error) {
setStatus(error.message || String(error), true); setStatus(error.message || String(error), true);
} finally { } finally {