Skip to content

Commit 4d0420f

Browse files
Merge pull request #193 from Patricklumowa/main
MASSIVE UPDATE
2 parents 7a1c44b + 41bb431 commit 4d0420f

File tree

11 files changed

+6563
-5517
lines changed

11 files changed

+6563
-5517
lines changed

Extension/background.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async function executeLocalScript(scriptName, tabId) {
110110
const overlayManagerCode = await overlayManagerResponse.text();
111111
console.log('🎨 Overlay manager loaded, injecting third...');
112112

113-
// Execute overlay manager third
113+
// Execute overlay manager thirds
114114
await chrome.scripting.executeScript({
115115
target: { tabId: tabId },
116116
world: "MAIN",

Extension/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "WPlace AutoBOT Script Launcher",
4-
"version": "2.0.2",
4+
"version": "2.0.4",
55
"description": "Launch and manage automation scripts for WPlace",
66
"icons": {
77
"16": "icons/icon16.png",

Extension/popup/popup.css

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ main {
335335
display: flex;
336336
justify-content: space-between;
337337
align-items: center;
338-
margin-bottom: 12px;
338+
margin-bottom: 8px;
339339
}
340340

341341
.section-header h4 {
@@ -351,6 +351,9 @@ main {
351351
.header-actions {
352352
display: flex;
353353
gap: 6px;
354+
margin-bottom: 12px;
355+
justify-content: flex-start;
356+
flex-wrap: wrap;
354357
}
355358

356359
.btn-small {

Extension/popup/popup.html

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,24 @@ <h3>Available Scripts</h3>
3030
<div class="account-section">
3131
<div class="section-header">
3232
<h4>Account Manager</h4>
33-
<div class="header-actions">
34-
<button class="btn btn-primary btn-small" id="refreshAccountBtn" title="Add Current Account">
35-
<span class="icon">🔄</span>
36-
Refresh
37-
</button>
38-
<button class="btn btn-primary btn-small" id="addAccountBtn" title="Add Account Manually">
39-
<span class="icon"></span>
40-
Add
41-
</button>
42-
</div>
33+
</div>
34+
<div class="header-actions">
35+
<button class="btn btn-primary btn-small" id="refreshAccountBtn" title="Add Current Account">
36+
<span class="icon">🔄</span>
37+
Refresh
38+
</button>
39+
<button class="btn btn-primary btn-small" id="addAccountBtn" title="Add Account Manually">
40+
<span class="icon"></span>
41+
Add
42+
</button>
43+
<button class="btn btn-secondary btn-small" id="exportAccountsBtn" title="Export All Accounts">
44+
<span class="icon">📤</span>
45+
Export
46+
</button>
47+
<button class="btn btn-secondary btn-small" id="importAccountsBtn" title="Import Accounts">
48+
<span class="icon">📥</span>
49+
Import
50+
</button>
4351
</div>
4452

4553
<div class="accounts-container" id="accountsContainer">
@@ -105,7 +113,7 @@ <h3>Startup Script</h3>
105113

106114
<footer>
107115
<div class="footer-info">
108-
<span>v2.0.2</span>
116+
<span>v2.0.4</span>
109117
<a href="#" id="settingsBtn">Settings</a>
110118
</div>
111119
</footer>

Extension/popup/popup.js

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const AVAILABLE_SCRIPTS = [
3939
let statusDot, statusText, scriptsList, accountsContainer, accountPlaceholder;
4040
let addAccountModal, accountNameInput, accountTokenInput;
4141
let refreshAccountBtn, addAccountBtn, saveAccountBtn, cancelAccountBtn, closeModalBtn;
42+
let exportAccountsBtn, importAccountsBtn;
4243

4344
// Global state
4445
let accounts = [];
@@ -75,6 +76,8 @@ function initializeElements() {
7576
saveAccountBtn = document.getElementById('saveAccountBtn');
7677
cancelAccountBtn = document.getElementById('cancelAccountBtn');
7778
closeModalBtn = document.getElementById('closeModalBtn');
79+
exportAccountsBtn = document.getElementById('exportAccountsBtn');
80+
importAccountsBtn = document.getElementById('importAccountsBtn');
7881
}
7982

8083
async function loadScripts() {
@@ -126,6 +129,8 @@ function setupEventListeners() {
126129
saveAccountBtn.addEventListener('click', handleSaveAccount);
127130
cancelAccountBtn.addEventListener('click', closeAddAccountModal);
128131
closeModalBtn.addEventListener('click', closeAddAccountModal);
132+
exportAccountsBtn.addEventListener('click', handleExportAccounts);
133+
importAccountsBtn.addEventListener('click', handleImportAccounts);
129134

130135
// Modal close on overlay click
131136
addAccountModal.addEventListener('click', (e) => {
@@ -663,6 +668,194 @@ async function loadStartupScript() {
663668
}
664669
}
665670

671+
async function handleExportAccounts() {
672+
try {
673+
if (isLoading) return;
674+
675+
setLoading(true);
676+
showNotification('Exporting accounts...', 'info');
677+
678+
console.log('📤 Starting account export process');
679+
680+
// Get accounts from storage
681+
const result = await chrome.storage.local.get('infoAccounts');
682+
const accounts = result.infoAccounts || [];
683+
684+
if (accounts.length === 0) {
685+
showNotification('No accounts to export', 'warning');
686+
return;
687+
}
688+
689+
// Create export data structure
690+
const exportData = {
691+
version: '1.0',
692+
exportDate: new Date().toISOString(),
693+
accountCount: accounts.length,
694+
accounts: accounts.map(account => ({
695+
name: account.name,
696+
token: account.token,
697+
ID: account.ID,
698+
// Include static metadata only (exclude dynamic status like Charges, Max, Droplets)
699+
...(account.lastActive && { lastActive: account.lastActive }),
700+
...(account.level && { level: account.level }),
701+
...(account.totalPixelsPainted && { totalPixelsPainted: account.totalPixelsPainted }),
702+
...(account.allianceName && { allianceName: account.allianceName }),
703+
...(account.allianceRole && { allianceRole: account.allianceRole })
704+
}))
705+
};
706+
707+
// Create filename with timestamp
708+
const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
709+
const filename = `wplace-accounts-${timestamp}.json`;
710+
711+
// Create and download file
712+
const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
713+
const url = URL.createObjectURL(blob);
714+
const a = document.createElement('a');
715+
a.href = url;
716+
a.download = filename;
717+
document.body.appendChild(a);
718+
a.click();
719+
document.body.removeChild(a);
720+
URL.revokeObjectURL(url);
721+
722+
console.log(`✅ Exported ${accounts.length} accounts to ${filename}`);
723+
showNotification(`Exported ${accounts.length} accounts successfully`, 'success');
724+
725+
} catch (error) {
726+
console.error('❌ Error exporting accounts:', error);
727+
showNotification('Failed to export accounts', 'error');
728+
} finally {
729+
setLoading(false);
730+
}
731+
}
732+
733+
async function handleImportAccounts() {
734+
try {
735+
if (isLoading) return;
736+
737+
setLoading(true);
738+
showNotification('Importing accounts...', 'info');
739+
740+
console.log('📥 Starting account import process');
741+
742+
// Create file input
743+
const input = document.createElement('input');
744+
input.type = 'file';
745+
input.accept = '.json';
746+
747+
input.onchange = async (e) => {
748+
const file = e.target.files[0];
749+
if (!file) {
750+
setLoading(false);
751+
return;
752+
}
753+
754+
try {
755+
const text = await file.text();
756+
const importData = JSON.parse(text);
757+
758+
// Validate import data structure
759+
if (!importData.accounts || !Array.isArray(importData.accounts)) {
760+
throw new Error('Invalid file format: missing accounts array');
761+
}
762+
763+
// Validate each account has required fields
764+
for (const account of importData.accounts) {
765+
if (!account.name || !account.token) {
766+
throw new Error('Invalid account data: missing name or token');
767+
}
768+
}
769+
770+
// Get existing accounts
771+
const result = await chrome.storage.local.get('infoAccounts');
772+
let existingAccounts = result.infoAccounts || [];
773+
774+
let addedCount = 0;
775+
let updatedCount = 0;
776+
let skippedCount = 0;
777+
778+
// Process each imported account
779+
for (const importAccount of importData.accounts) {
780+
// Check if account already exists (by token or ID)
781+
const existingIndex = existingAccounts.findIndex(existing =>
782+
existing.token === importAccount.token ||
783+
(existing.ID && importAccount.ID && existing.ID === importAccount.ID)
784+
);
785+
786+
if (existingIndex > -1) {
787+
// Account exists - ask user what to do
788+
const shouldUpdate = confirm(
789+
`Account "${importAccount.name}" already exists. Update it?\n\n` +
790+
`Click OK to update, Cancel to skip.`
791+
);
792+
793+
if (shouldUpdate) {
794+
// Update existing account
795+
existingAccounts[existingIndex] = {
796+
...existingAccounts[existingIndex],
797+
...importAccount,
798+
lastImported: new Date().toISOString()
799+
};
800+
updatedCount++;
801+
console.log(`🔄 Updated account: ${importAccount.name}`);
802+
} else {
803+
skippedCount++;
804+
console.log(`⏭️ Skipped account: ${importAccount.name}`);
805+
}
806+
} else {
807+
// New account - add it
808+
existingAccounts.push({
809+
...importAccount,
810+
lastImported: new Date().toISOString(),
811+
// Set default values for missing fields
812+
Charges: importAccount.Charges || 0,
813+
Max: importAccount.Max || 100,
814+
Droplets: importAccount.Droplets || 0
815+
});
816+
addedCount++;
817+
console.log(`➕ Added new account: ${importAccount.name}`);
818+
}
819+
}
820+
821+
// Save updated accounts
822+
await chrome.storage.local.set({ infoAccounts: existingAccounts });
823+
824+
// Update the accounts array for compatibility
825+
const accountTokens = existingAccounts.map(account => account.token);
826+
await chrome.storage.local.set({ accounts: accountTokens });
827+
828+
// Reload the accounts display
829+
await loadAccounts();
830+
831+
// Show summary
832+
const summary = [
833+
`Import completed:`,
834+
addedCount > 0 ? `${addedCount} added` : '',
835+
updatedCount > 0 ? `${updatedCount} updated` : '',
836+
skippedCount > 0 ? `${skippedCount} skipped` : ''
837+
].filter(Boolean).join(', ');
838+
839+
console.log(`✅ Import summary: ${summary}`);
840+
showNotification(summary, 'success');
841+
842+
} catch (error) {
843+
console.error('❌ Error importing accounts:', error);
844+
showNotification(`Import failed: ${error.message}`, 'error');
845+
} finally {
846+
setLoading(false);
847+
}
848+
};
849+
850+
input.click();
851+
852+
} catch (error) {
853+
console.error('❌ Error starting import:', error);
854+
showNotification('Failed to start import', 'error');
855+
setLoading(false);
856+
}
857+
}
858+
666859
// Enhanced account validation
667860
async function validateAccountToken(token) {
668861
try {

0 commit comments

Comments
 (0)