解混淆

This commit is contained in:
dela
2026-01-13 11:28:37 +08:00
commit 63bfeca740
13 changed files with 4596 additions and 0 deletions

627
popup.js Normal file
View File

@@ -0,0 +1,627 @@
/**
* 界面元素引用 (UI References)
*/
const tabs = document.querySelectorAll(".tab-btn");
const tabContents = document.querySelectorAll(".tab-content");
const binInput = document.getElementById("binInput");
const addBinBtn = document.getElementById("addBinBtn");
const generateCardsBtn = document.getElementById("generateCardsBtn");
const statusMessage = document.getElementById("statusMessage");
const binHistoryList = document.getElementById("binHistoryList");
// 地址管理相关元素
const nameInput = document.getElementById("nameInput");
const address1Input = document.getElementById("address1Input");
const address2Input = document.getElementById("address2Input");
const cityInput = document.getElementById("cityInput");
const stateInput = document.getElementById("stateInput");
const zipInput = document.getElementById("zipInput");
const addAddressBtn = document.getElementById("addAddressBtn");
const addressesList = document.getElementById("addressesList");
// 姓名管理相关元素
const firstNameInput = document.getElementById("firstNameInput");
const lastNameInput = document.getElementById("lastNameInput");
const addNameBtn = document.getElementById("addNameBtn");
const namesList = document.getElementById("namesList");
// 设置相关元素
const useLuhnValidation = document.getElementById("useLuhnValidation");
const DEFAULT_BIN = "552461xxxxxxxxxx";
/**
* 格式化输入BIN 输入框
* 自动转大写,移除非数字/X字符
*/
binInput.addEventListener("input", (e) => {
let val = e.target.value.toUpperCase();
val = val.replace(/[^0-9X]/g, "");
if (val.length > 19) {
val = val.substring(0, 19);
}
e.target.value = val;
});
/**
* 格式化输入:粘贴处理
* 自动补全 X确保格式符合 16 位卡号长度
*/
binInput.addEventListener("blur", (e) => {
let val = e.target.value.trim().replace(/[^0-9X]/g, "");
// 如果长度不足且非空,自动补 X
if (val.length > 0 && val.length < 16) {
const currentLen = val.replace(/X/g, "").length;
const needed = 16 - currentLen;
val = val + "X".repeat(needed);
}
e.target.value = val;
});
// ==========================================
// 设置菜单逻辑
// ==========================================
const settingsToggleBtn = document.getElementById("settingsToggleBtn");
const miniSettings = document.getElementById("miniSettings");
if (settingsToggleBtn && miniSettings) {
settingsToggleBtn.addEventListener("click", (e) => {
e.stopPropagation();
miniSettings.classList.toggle("show");
settingsToggleBtn.classList.toggle("active");
});
// 点击外部关闭菜单
document.addEventListener("click", (e) => {
if (!miniSettings.contains(e.target) && e.target !== settingsToggleBtn && !settingsToggleBtn.contains(e.target)) {
miniSettings.classList.remove("show");
settingsToggleBtn.classList.remove("active");
}
});
}
// Luhn 校验开关
if (useLuhnValidation) {
useLuhnValidation.addEventListener("change", () => {
chrome.storage.local.set({
useLuhnValidation: useLuhnValidation.checked
});
});
// 初始化状态
chrome.storage.local.get(["useLuhnValidation"], (data) => {
if (data.useLuhnValidation !== undefined) {
useLuhnValidation.checked = data.useLuhnValidation;
}
});
}
// 数据源选择器逻辑
const addressSourceSelect = document.getElementById("addressSourceSelect");
const nameSourceSelect = document.getElementById("nameSourceSelect");
if (addressSourceSelect) {
addressSourceSelect.addEventListener("change", () => {
const val = addressSourceSelect.value;
chrome.storage.local.set({ addressSource: val });
console.log("✅ Address source changed to:", val);
});
chrome.storage.local.get(["addressSource"], (data) => {
if (data.addressSource) {
addressSourceSelect.value = data.addressSource;
} else {
// 默认设置为 static
addressSourceSelect.value = "static";
chrome.storage.local.set({ addressSource: "static" });
}
});
}
if (nameSourceSelect) {
nameSourceSelect.addEventListener("change", () => {
const val = nameSourceSelect.value;
chrome.storage.local.set({ nameSource: val });
console.log("✅ Name source changed to:", val);
});
chrome.storage.local.get(["nameSource"], (data) => {
if (data.nameSource) {
nameSourceSelect.value = data.nameSource;
} else {
nameSourceSelect.value = "static";
chrome.storage.local.set({ nameSource: "static" });
}
});
}
// 初始化加载所有数据
loadData();
// ==========================================
// 标签页切换逻辑 (Tabs)
// ==========================================
tabs.forEach(tab => {
tab.addEventListener("click", () => {
const targetId = tab.dataset.tab;
tabs.forEach(t => t.classList.remove("active"));
tabContents.forEach(c => c.classList.remove("active"));
tab.classList.add("active");
document.getElementById(targetId + "-tab").classList.add("active");
});
});
const subTabs = document.querySelectorAll(".sub-tab-btn");
const subTabContents = document.querySelectorAll(".sub-tab-content");
subTabs.forEach(tab => {
tab.addEventListener("click", () => {
const targetId = tab.dataset.subtab;
subTabs.forEach(t => t.classList.remove("active"));
subTabContents.forEach(c => c.classList.remove("active"));
tab.classList.add("active");
document.getElementById(targetId + "-subtab").classList.add("active");
});
});
// ==========================================
// 核心功能:添加 BIN 和 生成卡片
// ==========================================
addBinBtn.addEventListener("click", () => {
const bin = binInput.value.trim();
if (!bin) return;
chrome.storage.local.get(["binHistory"], (data) => {
let history = data.binHistory || [];
// 去重并添加到头部
history = history.filter(b => b !== bin);
history.unshift(bin);
// 限制历史记录数量
if (history.length > 20) history = history.slice(0, 20);
chrome.storage.local.set({
binHistory: history,
currentBin: bin
}, () => {
loadBinHistory();
showToast("BIN added to history");
});
});
});
generateCardsBtn.addEventListener("click", async () => {
const bin = binInput.value.trim();
if (!bin) {
showStatus("Please enter a BIN number", "error");
return;
}
if (bin.length < 6) {
showStatus("BIN must be at least 6 digits", "error");
return;
}
const useLuhn = useLuhnValidation.checked;
// UI 状态更新:处理中
generateCardsBtn.disabled = true;
generateCardsBtn.innerHTML = "<span class=\"btn-icon\">⏳</span><span>Processing...</span>";
if (useLuhn) {
showStatus("🔐 Generating cards with Luhn validation...", "loading");
} else {
showStatus("⚡ Generating cards...", "loading");
}
// 保存 BIN 历史
chrome.storage.local.get(["binHistory"], (data) => {
let history = data.binHistory || [];
history = history.filter(b => b !== bin);
history.unshift(bin);
if (history.length > 20) history = history.slice(0, 20);
chrome.storage.local.set({
binHistory: history,
currentBin: bin
}, () => {
loadBinHistory();
});
});
// 发送消息给后台生成卡片
chrome.runtime.sendMessage({
action: "generateCards",
bin: bin,
useValidation: useLuhn,
stripeTabId: null
}, (response) => {
if (response && response.success) {
const luhnMsg = useLuhn ? " (Luhn validated)" : "";
showStatus("✅ Generated " + response.cards.length + " cards" + luhnMsg + ". Filling form...", "loading");
// 查找 Stripe 标签页并注入填充指令
chrome.tabs.query({
url: ["https://checkout.stripe.com/*", "https://*.stripe.com/*"]
}, (tabs) => {
if (chrome.runtime.lastError) {
resetGenerateButton();
showStatus("❌ Error: " + chrome.runtime.lastError.message, "error");
return;
}
if (tabs.length > 0) {
// 优先选择当前激活的标签页
const targetTab = tabs.find(t => t.active) || tabs[0];
chrome.tabs.sendMessage(targetTab.id, {
action: "fillForm"
}, (fillResponse) => {
resetGenerateButton();
if (chrome.runtime.lastError) {
showStatus("❌ No Stripe checkout page found. Please open one first.", "error");
} else {
showStatus("Form filled!", "success");
showToast("✅ Form filled successfully!");
}
});
} else {
resetGenerateButton();
showStatus("❌ No Stripe checkout page found. Please open one first.", "error");
}
});
} else {
resetGenerateButton();
showStatus("Failed to generate cards", "error");
showToast("❌ Failed to generate cards. Try again.", "error");
}
});
});
function resetGenerateButton() {
generateCardsBtn.disabled = false;
generateCardsBtn.innerHTML = "<span class=\"btn-icon\">🚀</span><span>Fill Everything</span>";
}
// ==========================================
// 历史记录管理
// ==========================================
function loadBinHistory() {
chrome.storage.local.get(["binHistory", "currentBin"], (data) => {
const history = data.binHistory || [];
const current = data.currentBin || DEFAULT_BIN;
binInput.value = current;
binHistoryList.innerHTML = "";
if (history.length === 0) {
binHistoryList.innerHTML = "<div class=\"empty\">No BINs saved yet</div>";
return;
}
history.forEach(bin => {
const item = document.createElement("div");
item.className = "history-item";
const binText = document.createElement("span");
binText.textContent = bin;
binText.className = "history-bin";
binText.addEventListener("click", () => {
binInput.value = bin;
chrome.storage.local.set({ currentBin: bin });
showToast("BIN selected");
});
const delBtn = document.createElement("button");
delBtn.textContent = "×";
delBtn.className = "delete-btn";
delBtn.addEventListener("click", (e) => {
e.stopPropagation();
deleteBin(bin);
});
item.appendChild(binText);
item.appendChild(delBtn);
binHistoryList.appendChild(item);
});
});
}
function deleteBin(bin) {
chrome.storage.local.get(["binHistory"], (data) => {
let history = data.binHistory || [];
history = history.filter(b => b !== bin);
chrome.storage.local.set({ binHistory: history }, () => {
loadBinHistory();
showToast("BIN deleted");
});
});
}
// ==========================================
// 地址管理
// ==========================================
addAddressBtn.addEventListener("click", () => {
const name = nameInput.value.trim();
const addr1 = address1Input.value.trim();
const addr2 = address2Input.value.trim();
const city = cityInput.value.trim();
const state = stateInput.value.trim();
const zip = zipInput.value.trim();
if (!name || !addr1 || !city || !state || !zip) {
showToast("Please fill all required fields", "error");
return;
}
// 简单的姓名拆分逻辑
const nameParts = name.split(" ");
const first = nameParts[0] || name;
const last = nameParts.slice(1).join(" ") || nameParts[0];
const newAddr = {
id: Date.now(),
name: name,
firstName: first,
lastName: last,
address1: addr1,
address2: addr2,
city: city,
state: state,
stateCode: getStateCode(state), // 转换州简写 (如 California -> CA)
postal: zip,
countryText: "United States",
countryValue: "US"
};
chrome.storage.local.get(["customAddresses"], (data) => {
const list = data.customAddresses || [];
list.push(newAddr);
chrome.storage.local.set({ customAddresses: list }, () => {
clearAddressInputs();
loadAddresses();
showToast("Address added");
});
});
});
function clearAddressInputs() {
nameInput.value = "";
address1Input.value = "";
address2Input.value = "";
cityInput.value = "";
stateInput.value = "";
zipInput.value = "";
}
function loadAddresses() {
chrome.storage.local.get(["customAddresses"], (data) => {
const list = data.customAddresses || [];
addressesList.innerHTML = "";
if (list.length === 0) {
addressesList.innerHTML = "<div class=\"empty\">No addresses saved yet</div>";
return;
}
list.forEach(addr => {
const item = document.createElement("div");
item.className = "list-item";
const info = document.createElement("div");
info.className = "item-info";
info.innerHTML = `
<strong>${addr.name}</strong><br>
<small>${addr.address1}${addr.address2 ? ", " + addr.address2 : ""}<br>
${addr.city}, ${addr.state} ${addr.postal}</small>
`;
const delBtn = document.createElement("button");
delBtn.textContent = "×";
delBtn.className = "delete-btn";
delBtn.addEventListener("click", () => deleteAddress(addr.id));
item.appendChild(info);
item.appendChild(delBtn);
addressesList.appendChild(item);
});
});
}
function deleteAddress(id) {
chrome.storage.local.get(["customAddresses"], (data) => {
let list = data.customAddresses || [];
list = list.filter(item => item.id !== id);
chrome.storage.local.set({ customAddresses: list }, () => {
loadAddresses();
showToast("Address deleted");
});
});
}
// ==========================================
// 姓名管理
// ==========================================
addNameBtn.addEventListener("click", () => {
const first = firstNameInput.value.trim();
const last = lastNameInput.value.trim();
if (!first || !last) {
showToast("Please enter both first and last name", "error");
return;
}
const newName = {
id: Date.now(),
firstName: first,
lastName: last,
fullName: first + " " + last
};
chrome.storage.local.get(["customNames"], (data) => {
const list = data.customNames || [];
list.push(newName);
chrome.storage.local.set({ customNames: list }, () => {
firstNameInput.value = "";
lastNameInput.value = "";
loadNames();
showToast("Name added");
});
});
});
function loadNames() {
chrome.storage.local.get(["customNames"], (data) => {
const list = data.customNames || [];
namesList.innerHTML = "";
if (list.length === 0) {
namesList.innerHTML = "<div class=\"empty\">No names saved yet</div>";
return;
}
list.forEach(item => {
const div = document.createElement("div");
div.className = "list-item";
const info = document.createElement("div");
info.className = "item-info";
info.innerHTML = `<strong>${item.fullName}</strong>`;
const delBtn = document.createElement("button");
delBtn.textContent = "×";
delBtn.className = "delete-btn";
delBtn.addEventListener("click", () => deleteName(item.id));
div.appendChild(info);
div.appendChild(delBtn);
namesList.appendChild(div);
});
});
}
function deleteName(id) {
chrome.storage.local.get(["customNames"], (data) => {
let list = data.customNames || [];
list = list.filter(item => item.id !== id);
chrome.storage.local.set({ customNames: list }, () => {
loadNames();
showToast("Name deleted");
});
});
}
// ==========================================
// 辅助工具函数
// ==========================================
/**
* 将州全称转换为两字母缩写 (用于表单匹配)
*/
function getStateCode(stateName) {
const map = {
Alabama: "AL", Alaska: "AK", Arizona: "AZ", Arkansas: "AR", California: "CA",
Colorado: "CO", Connecticut: "CT", Delaware: "DE", Florida: "FL", Georgia: "GA",
Hawaii: "HI", Idaho: "ID", Illinois: "IL", Indiana: "IN", Iowa: "IA",
Kansas: "KS", Kentucky: "KY", Louisiana: "LA", Maine: "ME", Maryland: "MD",
Massachusetts: "MA", Michigan: "MI", Minnesota: "MN", Mississippi: "MS", Missouri: "MO",
Montana: "MT", Nebraska: "NE", Nevada: "NV", "New Hampshire": "NH", "New Jersey": "NJ",
"New Mexico": "NM", "New York": "NY", "North Carolina": "NC", "North Dakota": "ND", Ohio: "OH",
Oklahoma: "OK", Oregon: "OR", Pennsylvania: "PA", "Rhode Island": "RI", "South Carolina": "SC",
"South Dakota": "SD", Tennessee: "TN", Texas: "TX", Utah: "UT", Vermont: "VT",
Virginia: "VA", Washington: "WA", "West Virginia": "WV", Wisconsin: "WI", Wyoming: "WY"
};
return map[stateName] || stateName.substring(0, 2).toUpperCase();
}
function showStatus(msg, type = "") {
statusMessage.textContent = msg;
statusMessage.className = "status-message " + type;
statusMessage.style.display = "block";
if (type === "success" || type === "error") {
setTimeout(() => {
statusMessage.style.display = "none";
}, 5000);
}
}
function showToast(msg, type = "success") {
const toast = document.createElement("div");
toast.className = "toast " + type;
toast.textContent = msg;
document.body.appendChild(toast);
// 动画显示
setTimeout(() => {
toast.classList.add("show");
}, 10);
// 自动消失
setTimeout(() => {
toast.classList.remove("show");
setTimeout(() => toast.remove(), 300);
}, 2000);
}
function loadData() {
loadBinHistory();
loadAddresses();
loadNames();
}
// ==========================================
// Telegram 广告弹窗逻辑
// ==========================================
const telegramModal = document.getElementById("telegramModal");
const modalCloseBtn = document.getElementById("modalCloseBtn");
const modalTimer = document.getElementById("modalTimer");
let countdownInterval = null;
let autoCloseTimeout = null;
function showTelegramModal() {
telegramModal.classList.add("show");
let seconds = 5;
modalTimer.textContent = seconds;
// 倒计时
countdownInterval = setInterval(() => {
seconds--;
if (seconds > 0) {
modalTimer.textContent = seconds;
} else {
modalTimer.textContent = "0";
clearInterval(countdownInterval);
}
}, 1000);
// 5秒后自动关闭
autoCloseTimeout = setTimeout(() => {
closeTelegramModal();
}, 5000);
}
function closeTelegramModal() {
telegramModal.classList.remove("show");
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
if (autoCloseTimeout) {
clearTimeout(autoCloseTimeout);
autoCloseTimeout = null;
}
}
if (modalCloseBtn) {
modalCloseBtn.addEventListener("click", (e) => {
e.preventDefault();
closeTelegramModal();
});
}
// 延迟显示广告,避免一打开就弹
if (telegramModal && modalCloseBtn && modalTimer) {
setTimeout(() => {
showTelegramModal();
}, 300);
}