// ==UserScript==
// @name 自动表单填充工具
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 自动生成并填充注册表单,支持记录和导出数据
// @author You
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_setClipboard
// @grant unsafeWindow
// ==/UserScript==
(function() {
'use strict';
// 存储生成的账户信息
let accountRecords = GM_getValue('accountRecords', []);
// 自动检测和点击的开关
let autoDetectEnabled = GM_getValue('autoDetectEnabled', true);
// 检测间隔(毫秒)
const DETECT_INTERVAL = 1000;
// 检测器ID
let detectorId = null;
// 当前填充的账户信息(临时存储)
let currentAccountInfo = null;
// 随机生成用户名(8-9位大小写字母组合)
function generateUsername() {
const length = Math.floor(Math.random() * 2) + 8; // 8-9位
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let username = '';
for (let i = 0; i < length; i++) {
username += chars.charAt(Math.floor(Math.random() * chars.length));
}
return username;
}
// 随机生成邮箱
function generateEmail() {
const length = Math.floor(Math.random() * 6) + 10; // 10-15位
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let email = '';
for (let i = 0; i < length; i++) {
email += chars.charAt(Math.floor(Math.random() * chars.length));
}
const domains = [
'163.com',
'gmail.com',
'outlook.com',
'protonmail.com',
'tutanota.com',
'zoho.com',
'yandex.com',
'mail.com',
'gmx.com',
'fastmail.com'
];
const domain = domains[Math.floor(Math.random() * domains.length)];
return email + '@' + domain;
}
// 随机生成密码(10-15位大小写字母+数字)
function generatePassword() {
const length = Math.floor(Math.random() * 6) + 10; // 10-15位
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let password = '';
for (let i = 0; i < length; i++) {
password += chars.charAt(Math.floor(Math.random() * chars.length));
}
return password;
}
// 复制文本到剪贴板
function copyToClipboard(text) {
GM_setClipboard(text);
showNotification('已复制到剪贴板');
}
// 自动检测和点击playnow元素
function startAutoDetector() {
// 清除旧的检测器
if (detectorId) {
clearInterval(detectorId);
detectorId = null;
}
if (!autoDetectEnabled) return;
let clickedPlaynow = false;
detectorId = setInterval(() => {
// 首先检测playnow元素
const playnowElement = document.getElementById('playnow');
if (playnowElement && !clickedPlaynow) {
console.log('检测到playnow元素,尝试点击...');
try {
playnowElement.click();
showNotification('已点击展开注册页面');
clickedPlaynow = true;
// 点击后,等待表单出现
checkForFormFields();
} catch (e) {
console.error('点击playnow元素失败:', e);
}
} else if (!clickedPlaynow) {
// 如果没找到playnow元素,继续检查表单字段
// 这种情况适用于页面加载时就已经显示表单的情况
checkForFormFields();
}
}, DETECT_INTERVAL);
}
// 检查表单字段
function checkForFormFields() {
// 检查是否有常见的注册表单字段
if (hasRegistrationFields()) {
console.log('检测到注册表单字段,自动填充...');
fillForm();
// 填充后停止检测,避免重复填充
clearInterval(detectorId);
detectorId = null;
}
}
// 判断页面中是否有注册表单字段
function hasRegistrationFields() {
// 检测常见的注册表单字段
return document.getElementById('username') ||
document.getElementById('email') ||
document.getElementById('password') ||
document.getElementById('passwordCheck') ||
// 查找其他可能的字段ID或名称
document.querySelector('input[name="username"]') ||
document.querySelector('input[name="email"]') ||
document.querySelector('input[name="password"]') ||
document.querySelector('input[type="email"]') ||
document.querySelector('input[type="password"]');
}
// 监听提交按钮
function setupSubmitButtonListener() {
// 寻找可能的提交按钮
const submitButtons = document.querySelectorAll('button[type="submit"], input[type="submit"], .registerbutton, .btn-success');
submitButtons.forEach(button => {
// 避免重复添加事件监听
button.removeEventListener('click', handleSubmitClick);
button.addEventListener('click', handleSubmitClick);
console.log('已监听提交按钮:', button);
});
}
// 处理提交按钮点击事件
function handleSubmitClick(event) {
// 如果有当前填充的账户信息,就记录它
if (currentAccountInfo) {
console.log('提交按钮被点击,记录账户信息');
// 添加到记录列表
accountRecords.push(currentAccountInfo);
GM_setValue('accountRecords', accountRecords);
// 更新计数器
const countElement = document.getElementById('records-count');
if (countElement) {
countElement.textContent = accountRecords.length;
}
// 如果账户列表是展开的,则更新显示
const container = document.getElementById('accounts-container');
if (container && container.style.display !== 'none') {
updateAccountsList();
}
showNotification('账户信息已记录!');
// 清除当前账户信息
currentAccountInfo = null;
}
}
// 创建控制面板UI
function createUI() {
const panel = document.createElement('div');
panel.id = 'auto-fill-panel';
panel.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
background-color: #f8f9fa;
border: 1px solid #ddd;
border-radius: 5px;
padding: 10px;
z-index: 9999;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
font-size: 14px;
width: 300px;
max-height: 80vh;
overflow-y: auto;
`;
panel.innerHTML = `
<div style="font-weight: bold; margin-bottom: 10px; text-align: center;">自动填充工具</div>
<button id="auto-fill-btn" style="width: 100%; margin-bottom: 5px; padding: 5px;">自动填充</button>
<div style="display: flex; margin-bottom: 5px;">
<label style="display: flex; align-items: center; cursor: pointer; width: 100%;">
<input type="checkbox" id="auto-detect-toggle" ${autoDetectEnabled ? 'checked' : ''} style="margin-right: 5px;">
自动检测并填充表单
</label>
</div>
<button id="export-txt-btn" style="width: 100%; margin-bottom: 5px; padding: 5px;">导出记录为TXT</button>
<button id="clear-records-btn" style="width: 100%; margin-bottom: 5px; padding: 5px;">清空记录</button>
<div style="font-size: 12px; margin-top: 5px;">已记录: <span id="records-count">${accountRecords.length}</span>条</div>
<div style="margin-top: 10px;">
<div id="toggle-accounts" style="cursor: pointer; font-weight: bold; user-select: none;">
▶ 查看账户记录 (点击展开)
</div>
<div id="accounts-container" style="display: none; margin-top: 5px; max-height: 300px; overflow-y: auto;">
</div>
</div>
<div style="text-align: right; font-size: 12px; cursor: pointer;" id="hide-panel">隐藏</div>
`;
document.body.appendChild(panel);
// 显示/隐藏面板的按钮
const toggleBtn = document.createElement('div');
toggleBtn.id = 'toggle-panel-btn';
toggleBtn.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
background-color: #00a5e9;
color: white;
border-radius: 3px;
padding: 5px 10px;
z-index: 9998;
cursor: pointer;
display: none;
`;
toggleBtn.textContent = '显示工具';
document.body.appendChild(toggleBtn);
// 绑定事件
document.getElementById('auto-fill-btn').addEventListener('click', fillForm);
document.getElementById('export-txt-btn').addEventListener('click', exportToTxt);
document.getElementById('clear-records-btn').addEventListener('click', clearRecords);
document.getElementById('hide-panel').addEventListener('click', function() {
panel.style.display = 'none';
toggleBtn.style.display = 'block';
});
toggleBtn.addEventListener('click', function() {
panel.style.display = 'block';
toggleBtn.style.display = 'none';
});
// 绑定展开/收起账户记录的事件
document.getElementById('toggle-accounts').addEventListener('click', function() {
const container = document.getElementById('accounts-container');
if (container.style.display === 'none') {
container.style.display = 'block';
this.textContent = '▼ 查看账户记录 (点击收起)';
updateAccountsList(); // 更新账户列表
} else {
container.style.display = 'none';
this.textContent = '▶ 查看账户记录 (点击展开)';
}
});
// 绑定自动检测开关事件
document.getElementById('auto-detect-toggle').addEventListener('change', function() {
autoDetectEnabled = this.checked;
GM_setValue('autoDetectEnabled', autoDetectEnabled);
if (autoDetectEnabled) {
showNotification('已开启自动检测');
startAutoDetector();
} else {
showNotification('已关闭自动检测');
if (detectorId) {
clearInterval(detectorId);
detectorId = null;
}
}
});
}
// 更新账户列表显示
function updateAccountsList() {
const container = document.getElementById('accounts-container');
if (!container) return;
container.innerHTML = '';
if (accountRecords.length === 0) {
container.innerHTML = '<div style="text-align: center; padding: 10px;">暂无记录</div>';
return;
}
// 倒序显示记录,最新的在最前面
for (let i = accountRecords.length - 1; i >= 0; i--) {
const record = accountRecords[i];
const recordElem = document.createElement('div');
recordElem.style.cssText = `
border: 1px solid #eee;
border-radius: 3px;
padding: 8px;
margin-bottom: 8px;
background-color: #fff;
font-size: 13px;
`;
recordElem.innerHTML = `
<div style="color: #666; font-size: 12px;">${record.date}</div>
<div style="margin: 5px 0;">
用户名: <span class="copyable" data-value="${record.username}" style="cursor: pointer; color: #0066cc;">${record.username}</span>
</div>
<div style="margin: 5px 0;">
邮箱: <span class="copyable" data-value="${record.email}" style="cursor: pointer; color: #0066cc;">${record.email}</span>
</div>
<div style="margin: 5px 0;">
密码: <span class="copyable" data-value="${record.password}" style="cursor: pointer; color: #0066cc;">${record.password}</span>
</div>
`;
container.appendChild(recordElem);
}
// 给可复制元素添加点击事件
const copyables = container.querySelectorAll('.copyable');
copyables.forEach(el => {
el.addEventListener('click', function() {
const value = this.getAttribute('data-value');
copyToClipboard(value);
});
});
}
// 填充表单
function fillForm() {
const username = generateUsername();
const email = generateEmail();
const password = generatePassword();
// 填充表单
const usernameFields = document.querySelectorAll('#username, input[name="username"], input[placeholder*="用户名"], input[placeholder*="username"]');
const emailFields = document.querySelectorAll('#email, input[name="email"], input[type="email"], input[placeholder*="邮箱"], input[placeholder*="email"]');
const passwordFields = document.querySelectorAll('#password, input[name="password"], input[type="password"], input[placeholder*="密码"], input[placeholder*="password"]');
const confirmPasswordFields = document.querySelectorAll('#passwordCheck, #confirmPassword, input[name="confirmPassword"], input[placeholder*="确认密码"], input[placeholder*="confirm"]');
// 尝试填充所有可能的字段
usernameFields.forEach(field => field.value = username);
emailFields.forEach(field => field.value = email);
passwordFields.forEach(field => field.value = password);
confirmPasswordFields.forEach(field => field.value = password);
// 准备账户信息但不立即保存
currentAccountInfo = {
username: username,
email: email,
password: password,
date: new Date().toLocaleString()
};
// 设置提交按钮监听
setupSubmitButtonListener();
// 显示提示
showNotification('表单已填充,提交注册后将记录账户信息');
}
// 导出为TXT
function exportToTxt() {
if (accountRecords.length === 0) {
showNotification('没有记录可导出');
return;
}
let txtContent = '';
accountRecords.forEach((record, index) => {
txtContent += `记录 #${index + 1} [${record.date}]\n`;
txtContent += `用户名: ${record.username}\n`;
txtContent += `邮箱: ${record.email}\n`;
txtContent += `密码: ${record.password}\n`;
txtContent += '------------------------\n\n';
});
// 创建下载链接
const blob = new Blob([txtContent], {type: 'text/plain;charset=utf-8'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `账户记录_${new Date().toISOString().slice(0, 10)}.txt`;
a.click();
URL.revokeObjectURL(url);
showNotification('导出成功!');
}
// 清空记录
function clearRecords() {
if (confirm('确定要清空所有记录吗?')) {
accountRecords = [];
GM_setValue('accountRecords', accountRecords);
document.getElementById('records-count').textContent = '0';
// 更新账户列表显示
updateAccountsList();
showNotification('记录已清空');
}
}
// 显示通知
function showNotification(message) {
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border-radius: 5px;
z-index: 10000;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.opacity = '0';
notification.style.transition = 'opacity 0.5s';
setTimeout(() => {
document.body.removeChild(notification);
}, 500);
}, 2000);
}
// 注册油猴菜单命令
GM_registerMenuCommand('自动填充表单', fillForm);
GM_registerMenuCommand('导出记录为TXT', exportToTxt);
GM_registerMenuCommand('清空记录', clearRecords);
// 页面加载完成后创建UI并启动自动检测
window.addEventListener('load', function() {
// 创建UI
createUI();
// 启动自动检测
if (autoDetectEnabled) {
startAutoDetector();
}
});
})();