feat: auto submit after filling phone
This commit is contained in:
@@ -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
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user