// ==UserScript== // @name Nc.me表单自动填充生成器 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 生成随机数据并一键填充表单,支持数据保存和恢复,导出功能 // @author cursor 0.46.11 // @match *://*.namecheap.com/* // @match *://*.nc.me/* // @grant GM_setValue // @grant GM_getValue // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 数据生成工具 - 内联数据避免外部依赖 const DataGenerator = { // 美国常用名 firstNames: ["John", "Jane", "Alex", "Emily", "Chris", "Katie", "Mike", "Laura", "David", "Sarah", "Robert", "Amanda", "James", "Jennifer", "Michael", "Elizabeth", "William", "Jessica", "Thomas", "Melissa", "Kevin", "Rachel", "Brian", "Nicole", "Steven", "Michelle"], // 美国常用姓 lastNames: ["Smith", "Johnson", "Brown", "Williams", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Wilson", "Anderson", "Taylor", "Thomas", "Moore", "Jackson", "Martin", "Lee", "Thompson", "White", "Harris", "Clark", "Lewis", "Young", "Walker", "Hall"], // 美国常用街道名 streetNames: ["Main", "Oak", "Park", "Pine", "Maple", "Cedar", "Elm", "Washington", "Lake", "Hill", "Walnut", "Spring", "North", "South", "East", "West", "Center", "River", "Church"], // 美国常用街道类型 streetTypes: ["St", "Ave", "Blvd", "Dr", "Rd", "Ln", "Way", "Pl", "Ct", "Terrace", "Circle", "Drive"], // 美国常用城市 cities: ["New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "Philadelphia", "San Antonio", "San Diego", "Dallas", "San Jose", "Austin", "Jacksonville", "Fort Worth", "Columbus", "Charlotte", "San Francisco", "Indianapolis", "Seattle", "Denver", "Boston"], // 美国州 states: [ { full: "Alabama", abbr: "AL" }, { full: "Alaska", abbr: "AK" }, { full: "Arizona", abbr: "AZ" }, { full: "Arkansas", abbr: "AR" }, { full: "California", abbr: "CA" }, { full: "Colorado", abbr: "CO" }, { full: "Connecticut", abbr: "CT" }, { full: "Delaware", abbr: "DE" }, { full: "Florida", abbr: "FL" }, { full: "Georgia", abbr: "GA" }, { full: "Hawaii", abbr: "HI" }, { full: "Idaho", abbr: "ID" }, { full: "Illinois", abbr: "IL" }, { full: "Indiana", abbr: "IN" }, { full: "Iowa", abbr: "IA" }, { full: "Kansas", abbr: "KS" }, { full: "Kentucky", abbr: "KY" }, { full: "Louisiana", abbr: "LA" }, { full: "Maine", abbr: "ME" }, { full: "Maryland", abbr: "MD" }, { full: "Massachusetts", abbr: "MA" }, { full: "Michigan", abbr: "MI" }, { full: "Minnesota", abbr: "MN" }, { full: "Mississippi", abbr: "MS" }, { full: "Missouri", abbr: "MO" }, { full: "Montana", abbr: "MT" }, { full: "Nebraska", abbr: "NE" }, { full: "Nevada", abbr: "NV" }, { full: "New Hampshire", abbr: "NH" }, { full: "New Jersey", abbr: "NJ" }, { full: "New Mexico", abbr: "NM" }, { full: "New York", abbr: "NY" }, { full: "North Carolina", abbr: "NC" }, { full: "North Dakota", abbr: "ND" }, { full: "Ohio", abbr: "OH" }, { full: "Oklahoma", abbr: "OK" }, { full: "Oregon", abbr: "OR" }, { full: "Pennsylvania", abbr: "PA" }, { full: "Rhode Island", abbr: "RI" }, { full: "South Carolina", abbr: "SC" }, { full: "South Dakota", abbr: "SD" }, { full: "Tennessee", abbr: "TN" }, { full: "Texas", abbr: "TX" }, { full: "Utah", abbr: "UT" }, { full: "Vermont", abbr: "VT" }, { full: "Virginia", abbr: "VA" }, { full: "Washington", abbr: "WA" }, { full: "West Virginia", abbr: "WV" }, { full: "Wisconsin", abbr: "WI" }, { full: "Wyoming", abbr: "WY" } ], // 随机数生成 randomInt: function(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }, // 随机选择数组元素 randomElement: function(array) { return array[this.randomInt(0, array.length - 1)]; }, // 生成随机字符串 randomString: function(length, chars) { chars = chars || 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; }, // 生成随机用户名 - 只包含字母和数字 getUserName: function(firstName, lastName) { if (!firstName || !lastName) { firstName = this.randomElement(this.firstNames); lastName = this.randomElement(this.lastNames); } // 生成几种可能的用户名格式 - 仅使用字母和数字 const formats = [ firstName.toLowerCase() + lastName.toLowerCase(), firstName.toLowerCase() + this.randomInt(1, 999), firstName.toLowerCase() + lastName.toLowerCase() + this.randomInt(1, 99), firstName.toLowerCase().substring(0, 1) + lastName.toLowerCase() + this.randomInt(100, 999), firstName.toLowerCase() + this.randomInt(1000, 9999) ]; // 获取一个随机格式的用户名 let username = this.randomElement(formats); // 确保只包含字母和数字 username = username.replace(/[^a-z0-9]/g, ''); return username; }, // 生成随机密码 getPassword: function(length, includeSpecial) { length = length || 10; let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; if (includeSpecial) { chars += "!@#$%^&*()_+~`|}{[]\\:;?><,./-="; } return this.randomString(length, chars); }, // 生成随机街道地址 getStreetAddress: function() { const number = this.randomInt(100, 9999); const street = this.randomElement(this.streetNames); const type = this.randomElement(this.streetTypes); return number + " " + street + " " + type; }, // 生成随机公寓/单元号 getSecondaryAddress: function() { const formats = [ "Apt " + this.randomInt(1, 999), "Suite " + this.randomInt(1, 999), "Unit " + this.randomInt(1, 999), "#" + this.randomInt(1, 999) ]; return this.randomElement(formats); }, // 生成随机邮编 getZipCode: function() { return "" + this.randomInt(10000, 99999); }, // 生成随机电话号码 - 使用(xxx) xxx-xxxx格式 getPhoneNumber: function() { const areaCode = this.randomInt(200, 999); const prefix = this.randomInt(200, 999); const lineNumber = this.randomInt(1000, 9999); return `(${areaCode}) ${prefix}-${lineNumber}`; }, // 生成完整个人信息数据集 generatePersonData: function() { const firstName = this.randomElement(this.firstNames); const lastName = this.randomElement(this.lastNames); const state = this.randomElement(this.states); return { username: this.getUserName(firstName, lastName), password: this.getPassword(12, true), email: "请自行填写用于验证的邮箱", // 固定值 firstName: firstName, lastName: lastName, addressLine1: this.getStreetAddress(), addressLine2: this.getSecondaryAddress(), city: this.randomElement(this.cities), state: state.full, stateAbbr: state.abbr, postalCode: this.getZipCode(), phone: this.getPhoneNumber(), timestamp: new Date().toLocaleString(), filled: false // 添加填充状态标记 }; } }; // 数据存储工具 - 使用GM API const DataStorage = { storageKey: 'formFiller_NamecheapData', // 检查用户名是否已存在 isUsernameDuplicate: function(username) { const allData = this.getAllData(); return allData.some(item => item.username === username); }, // 保存数据 saveData: function(data) { try { // 首先检查用户名是否已经存在 if (this.isUsernameDuplicate(data.username)) { return { success: false, message: '该用户名已存在于保存的数据中' }; } // 获取现有数据 let savedData = this.getAllData(); // 生成唯一ID data.id = Date.now().toString(36) + Math.random().toString(36).substr(2, 5); savedData.push(data); // 使用GM_setValue保存数据 GM_setValue(this.storageKey, savedData); console.log("数据已保存", data); return { success: true, id: data.id }; } catch(e) { console.error("保存数据失败:", e); return { success: false, message: "保存数据失败: " + e.message }; } }, // 获取所有保存的数据 getAllData: function() { try { // 使用GM_getValue获取数据 const data = GM_getValue(this.storageKey, []); console.log("读取的数据:", data); return data; } catch(e) { console.error("读取数据失败:", e); return []; } }, // 获取指定ID的数据 getData: function(id) { const allData = this.getAllData(); return allData.find(item => item.id === id); }, // 删除数据 deleteData: function(id) { let allData = this.getAllData(); allData = allData.filter(item => item.id !== id); GM_setValue(this.storageKey, allData); }, // 清空所有数据 clearAllData: function() { GM_setValue(this.storageKey, []); }, // 导出所有数据为文本 exportDataAsText: function() { const allData = this.getAllData(); if (allData.length === 0) { return "没有保存的数据"; } let text = "表单填充数据导出 - " + new Date().toLocaleString() + "\n\n"; allData.forEach((data, index) => { text += `--- 记录 ${index + 1} ---\n`; text += `姓名: ${data.firstName} ${data.lastName}\n`; text += `用户名: ${data.username}\n`; text += `密码: ${data.password}\n`; text += `邮箱: ${data.email || '未填写'}\n`; text += `地址: ${data.addressLine1}\n`; text += `地址2: ${data.addressLine2 || '无'}\n`; text += `城市: ${data.city}\n`; text += `州/省: ${data.state}\n`; text += `邮编: ${data.postalCode}\n`; text += `电话: ${data.phone}\n`; text += `保存时间: ${data.timestamp || '未知'}\n\n`; }); return text; } }; // 存储生成的数据、表单填充状态和邮箱填写状态 let generatedData = {}; let hasFilledForm = false; let emailFilled = false; let userFilledEmail = ""; // 创建UI const UI = { panel: null, dataContainer: null, savedDataContainer: null, saveButton: null, showSavedData: false, buttonContainer: null, secondRowContainer: null, notificationArea: null, // 初始化UI init: function() { // 检测当前页面类型 const isSignInPage = window.location.href.includes('/login') || window.location.href.includes('/signin'); // 创建控制面板 - 统一上边界高度 this.panel = document.createElement('div'); this.panel.style.cssText = ` position: fixed; top: 200px; left: 20px; width: 350px; background: #f8f9fa; border: 1px solid #ddd; border-radius: 5px; padding: 10px; z-index: 10000; box-shadow: 0 0 10px rgba(0,0,0,0.1); max-height: ${isSignInPage ? '90vh' : '75vh'}; overflow-y: auto; `; // 创建标题 - 缩小边距 const title = document.createElement('h3'); title.textContent = 'Nc.me表单填写助手'; title.style.cssText = ` margin: 0 0 8px 0; color: #333; font-size: 16px; text-align: center; padding: 6px 0; background-color: #f1f8e9; border-radius: 4px; border-bottom: 2px solid #4CAF50; font-weight: bold; box-shadow: 0 1px 3px rgba(0,0,0,0.1); `; this.panel.appendChild(title); // 创建通知区域 - 在标题下方 this.notificationArea = document.createElement('div'); this.notificationArea.style.cssText = ` margin: -10px 0 10px 0; padding: 0; min-height: 30px; text-align: center; `; this.panel.appendChild(this.notificationArea); // 如果是登录页面,只显示保存的数据 if (isSignInPage) { this.savedDataContainer = document.createElement('div'); this.savedDataContainer.id = 'saved-data'; this.panel.appendChild(this.savedDataContainer); // 显示保存的数据 this.displaySavedData(); } else { // 注册页面的完整UI this.dataContainer = document.createElement('div'); this.dataContainer.id = 'faker-data'; this.panel.appendChild(this.dataContainer); // 创建保存数据容器 this.savedDataContainer = document.createElement('div'); this.savedDataContainer.id = 'saved-data'; this.savedDataContainer.style.display = 'none'; this.panel.appendChild(this.savedDataContainer); // 创建按钮容器 this.buttonContainer = document.createElement('div'); this.buttonContainer.style.cssText = 'display: flex; margin-top: 10px; gap: 6px; flex-wrap: wrap;'; this.panel.appendChild(this.buttonContainer); // 创建生成按钮 const generateButton = document.createElement('button'); generateButton.textContent = '重新生成'; generateButton.style.cssText = ` background: #4CAF50; color: white; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; flex: 1; min-width: 100px; font-size: 13px; `; generateButton.onclick = () => { generatedData = DataGenerator.generatePersonData(); hasFilledForm = false; emailFilled = false; userFilledEmail = ""; // 重置邮箱表单字段 const emailField = findFormField('email'); if (emailField) { emailField.value = ''; emailField.dispatchEvent(new Event('input', { bubbles: true })); emailField.dispatchEvent(new Event('change', { bubbles: true })); } this.updateSaveButtonState(); this.displayCurrentData(); }; this.buttonContainer.appendChild(generateButton); // 创建填充按钮 const fillButton = document.createElement('button'); fillButton.textContent = '一键填充'; fillButton.style.cssText = ` background: #2196F3; color: white; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; flex: 1; min-width: 100px; font-size: 13px; `; fillButton.onclick = () => { fillForm(); hasFilledForm = true; this.updateSaveButtonState(); }; this.buttonContainer.appendChild(fillButton); // 创建保存按钮 this.saveButton = document.createElement('button'); this.saveButton.textContent = '保存数据'; this.saveButton.style.cssText = ` background: #FF9800; color: white; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; flex: 1; min-width: 100px; font-size: 13px; opacity: 0.5; `; this.saveButton.disabled = true; this.saveButton.onclick = () => { if (hasFilledForm && emailFilled) { // 从表单中读取当前值 const formData = readFormData(); // 显示邮箱确认对话框 if (confirm(`请确认填写的邮箱地址是否正确:\n${formData.email}\n\n点击"确定"继续保存,点击"取消"返回修改`)) { const result = DataStorage.saveData(formData); if (result.success) { this.showStatusMessage('数据已保存', 'success'); hasFilledForm = false; this.updateSaveButtonState(); } else { this.showStatusMessage(result.message, 'warning'); } } } }; this.buttonContainer.appendChild(this.saveButton); // 第二行按钮 this.secondRowContainer = document.createElement('div'); this.secondRowContainer.style.cssText = 'display: flex; margin-top: 10px; gap: 10px;'; this.panel.appendChild(this.secondRowContainer); // 创建数据切换按钮 const toggleButton = document.createElement('button'); toggleButton.textContent = '查看保存的数据'; toggleButton.id = 'toggle-data-view-btn'; toggleButton.style.cssText = ` background: #757575; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: pointer; flex: 1; `; toggleButton.onclick = () => this.toggleDataView(); this.secondRowContainer.appendChild(toggleButton); // 创建导出按钮 const exportButton = document.createElement('button'); exportButton.textContent = '导出数据'; exportButton.style.cssText = ` background: #9C27B0; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: pointer; flex: 1; `; exportButton.onclick = () => this.exportData(); this.secondRowContainer.appendChild(exportButton); // 显示当前数据 this.displayCurrentData(); // 添加对表单中邮箱字段的监听 this.setupEmailListener(); } // 添加面板到文档 document.body.appendChild(this.panel); }, // 邮箱字段的监听器 setupEmailListener: function() { // 使用MutationObserver监听DOM变化 const observer = new MutationObserver(() => { // 尝试查找邮箱字段 const emailField = findFormField('email'); if (emailField) { // 获取当前值(如果有的话) if (emailField.value && emailField.value.trim() !== '') { userFilledEmail = emailField.value; emailFilled = true; this.updateSaveButtonState(); } // 为邮箱字段添加事件监听器 emailField.addEventListener('input', (e) => { userFilledEmail = e.target.value; emailFilled = userFilledEmail.trim() !== ''; this.updateSaveButtonState(); }); // 监听到邮箱字段后可以停止观察 observer.disconnect(); } }); // 开始观察文档变化 observer.observe(document.body, { childList: true, subtree: true }); // 立即尝试查找一次 const emailField = findFormField('email'); if (emailField) { // 获取当前值(如果有的话) if (emailField.value && emailField.value.trim() !== '') { userFilledEmail = emailField.value; emailFilled = true; this.updateSaveButtonState(); } emailField.addEventListener('input', (e) => { userFilledEmail = e.target.value; emailFilled = userFilledEmail.trim() !== ''; this.updateSaveButtonState(); }); } }, // 更新保存按钮状态 updateSaveButtonState: function() { if (hasFilledForm && emailFilled) { this.saveButton.disabled = false; this.saveButton.style.opacity = '1'; this.saveButton.style.cursor = 'pointer'; } else { this.saveButton.disabled = true; this.saveButton.style.opacity = '0.5'; this.saveButton.style.cursor = 'not-allowed'; } }, // 导出数据为文本文件 exportData: function() { const text = DataStorage.exportDataAsText(); const blob = new Blob([text], {type: 'text/plain;charset=utf-8'}); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `Nc.me账户数据_${new Date().toISOString().slice(0,10)}.txt`; document.body.appendChild(a); a.click(); // 清理 setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 100); this.showStatusMessage('数据已导出', 'success'); }, // 显示当前生成的数据 displayCurrentData: function() { // 创建表格显示数据 let html = '
${formatKey(key)}: | ${displayValue} |
没有保存的数据
'; return; } let html = ''; // 调整登录页面按钮布局 if (!isSignInPage) { // 注册页面的清空按钮 html += `