Files
Dotbypasser/extension/ui/options/options.js
2026-01-10 16:53:02 +08:00

299 lines
9.1 KiB
JavaScript

/**
* Options Page Logic
*/
// Tab switching
const tabBtns = document.querySelectorAll('.tab-btn');
const tabContents = document.querySelectorAll('.tab-content');
tabBtns.forEach(btn => {
btn.addEventListener('click', () => {
const targetTab = btn.dataset.tab;
// Remove active class from all
tabBtns.forEach(b => b.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
// Add active class to clicked
btn.classList.add('active');
document.getElementById(`tab-${targetTab}`).classList.add('active');
});
});
// Initialize on load
document.addEventListener('DOMContentLoaded', async () => {
await loadAllSettings();
await loadStats();
await loadDataPreview();
// Set up event listeners
document.getElementById('save-api-keys').addEventListener('click', saveAPIKeys);
document.getElementById('save-module-config').addEventListener('click', saveModuleConfig);
document.getElementById('export-json').addEventListener('click', exportJSON);
document.getElementById('export-csv').addEventListener('click', exportCSV);
document.getElementById('clear-data').addEventListener('click', clearData);
});
/**
* Load all settings from storage
*/
async function loadAllSettings() {
try {
const config = await chrome.storage.sync.get(['apiKeys', 'modules']);
// Load API keys
if (config.apiKeys) {
document.getElementById('api-capsolver').value = config.apiKeys.capsolver || '';
document.getElementById('api-2captcha').value = config.apiKeys.twocaptcha || '';
document.getElementById('api-nopecha').value = config.apiKeys.nopecha || '';
document.getElementById('api-nocaptchaai').value = config.apiKeys.nocaptchaai || '';
}
// Load module configs
if (config.modules) {
// Captcha Solver
const cs = config.modules.captchaSolver?.config;
if (cs) {
document.getElementById('cs-debug').checked = cs.debug || false;
document.getElementById('cs-service').value = cs.apiService || 'capsolver';
document.getElementById('cs-delay').value = cs.solveDelay || 800;
}
// GOG Payment
const gog = config.modules.gogPayment?.config;
if (gog) {
document.getElementById('gog-bins').value = gog.bins?.join(',') || '';
document.getElementById('gog-rotate').checked = gog.autoRotateBIN || false;
}
// AutoFill
const af = config.modules.autoFill?.config;
if (af) {
document.getElementById('af-country').value = af.defaultCountry || 'US';
document.getElementById('af-delay').value = af.fillDelay || 300;
}
}
} catch (error) {
console.error('[Options] Failed to load settings:', error);
}
}
/**
* Save API Keys
*/
async function saveAPIKeys() {
const apiKeys = {
capsolver: document.getElementById('api-capsolver').value.trim(),
twocaptcha: document.getElementById('api-2captcha').value.trim(),
nopecha: document.getElementById('api-nopecha').value.trim(),
nocaptchaai: document.getElementById('api-nocaptchaai').value.trim()
};
try {
await chrome.storage.sync.set({ apiKeys });
showNotification('API keys saved successfully', 'success');
} catch (error) {
console.error('[Options] Failed to save API keys:', error);
showNotification('Failed to save API keys', 'error');
}
}
/**
* Save Module Configuration
*/
async function saveModuleConfig() {
try {
const config = await chrome.storage.sync.get(['modules']);
// Update Captcha Solver config
config.modules.captchaSolver.config.debug = document.getElementById('cs-debug').checked;
config.modules.captchaSolver.config.apiService = document.getElementById('cs-service').value;
config.modules.captchaSolver.config.solveDelay = parseInt(document.getElementById('cs-delay').value);
// Update GOG Payment config
const bins = document.getElementById('gog-bins').value.split(',').map(b => b.trim()).filter(b => b);
config.modules.gogPayment.config.bins = bins;
config.modules.gogPayment.config.autoRotateBIN = document.getElementById('gog-rotate').checked;
// Update AutoFill config
config.modules.autoFill.config.defaultCountry = document.getElementById('af-country').value;
config.modules.autoFill.config.fillDelay = parseInt(document.getElementById('af-delay').value);
await chrome.storage.sync.set(config);
showNotification('Module configuration saved successfully', 'success');
} catch (error) {
console.error('[Options] Failed to save module config:', error);
showNotification('Failed to save configuration', 'error');
}
}
/**
* Load statistics
*/
async function loadStats() {
try {
const response = await chrome.runtime.sendMessage({ type: 'GET_STATS' });
if (response && response.success) {
const stats = response.stats;
document.getElementById('total-captchas').textContent = stats.captchasSolved || 0;
document.getElementById('total-forms').textContent = stats.formsFilled || 0;
document.getElementById('total-cards').textContent = stats.cardsGenerated || 0;
document.getElementById('total-payments').textContent = stats.paymentsCaptured || 0;
}
} catch (error) {
console.error('[Options] Failed to load stats:', error);
}
}
/**
* Load data preview
*/
async function loadDataPreview() {
try {
const response = await chrome.runtime.sendMessage({ type: 'EXPORT_DATA' });
if (response && response.success) {
const data = response.data;
const preview = document.getElementById('data-preview-content');
if (data && data.length > 0) {
preview.textContent = JSON.stringify(data, null, 2);
} else {
preview.textContent = 'No data captured yet';
}
}
} catch (error) {
console.error('[Options] Failed to load data preview:', error);
}
}
/**
* Export data as JSON
*/
async function exportJSON() {
try {
const response = await chrome.runtime.sendMessage({ type: 'EXPORT_DATA' });
if (response && response.success) {
const data = response.data;
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
downloadBlob(blob, `payment-automation-data-${Date.now()}.json`);
showNotification('Data exported as JSON', 'success');
}
} catch (error) {
console.error('[Options] Failed to export JSON:', error);
showNotification('Export failed', 'error');
}
}
/**
* Export data as CSV
*/
async function exportCSV() {
try {
const response = await chrome.runtime.sendMessage({ type: 'EXPORT_DATA' });
if (response && response.success) {
const data = response.data;
if (!data || data.length === 0) {
showNotification('No data to export', 'error');
return;
}
// Convert to CSV
const headers = Object.keys(data[0]);
const csv = [
headers.join(','),
...data.map(row => headers.map(h => JSON.stringify(row[h] || '')).join(','))
].join('\n');
const blob = new Blob([csv], { type: 'text/csv' });
downloadBlob(blob, `payment-automation-data-${Date.now()}.csv`);
showNotification('Data exported as CSV', 'success');
}
} catch (error) {
console.error('[Options] Failed to export CSV:', error);
showNotification('Export failed', 'error');
}
}
/**
* Clear all captured data
*/
async function clearData() {
if (!confirm('Are you sure you want to clear all captured data? This cannot be undone.')) {
return;
}
try {
await chrome.runtime.sendMessage({ type: 'CLEAR_DATA' });
await loadDataPreview();
await loadStats();
showNotification('All data cleared', 'success');
} catch (error) {
console.error('[Options] Failed to clear data:', error);
showNotification('Failed to clear data', 'error');
}
}
/**
* Download blob as file
*/
function downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
/**
* Show notification
*/
function showNotification(message, type) {
// Create notification element
const notification = document.createElement('div');
notification.textContent = message;
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
padding: 16px 24px;
background: ${type === 'success' ? '#4CAF50' : '#f44336'};
color: white;
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
z-index: 10000;
animation: slideIn 0.3s ease-out;
`;
document.body.appendChild(notification);
// Remove after 3 seconds
setTimeout(() => {
notification.style.animation = 'slideOut 0.3s ease-out';
setTimeout(() => {
document.body.removeChild(notification);
}, 300);
}, 3000);
}
// Add CSS animations
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from { transform: translateX(400px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes slideOut {
from { transform: translateX(0); opacity: 1; }
to { transform: translateX(400px); opacity: 0; }
}
`;
document.head.appendChild(style);