facebook / modules /migration.js
Althnayi's picture
Upload 27 files
2a196ac verified
Raw
History Blame Contribute Delete
18.1 kB
// ============================================================================
// File: modules/migration.js
// ============================================================================
(global => {
'use strict';
/**
* Sanitizes data strings to protect DOM from XSS
*/
function sanitizeDataString(str) {
if (!str) return '';
return String(str)
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#x27;');
}
// ============================================================================
// Cryptographic Migration Module Initializer
// ============================================================================
function initMigrationModule() {
try {
const selectAllCheck = document.getElementById('chk-ie-all');
const exportBtn = document.getElementById('btn-export-settings');
const importTriggerBtn = document.getElementById('btn-import-settings-trigger');
const fileInput = document.getElementById('file-import-settings');
if (selectAllCheck) {
selectAllCheck.addEventListener('change', (e) => {
const isChecked = e.target.checked;
const ids = ['chk-ie-cl', 'chk-ie-ch', 'chk-ie-sch', 'chk-ie-grp', 'chk-ie-int'];
ids.forEach(id => {
const el = document.getElementById(id);
if (el) el.checked = isChecked;
});
});
}
if (exportBtn) exportBtn.addEventListener('click', exportSystemBackup);
if (importTriggerBtn) {
importTriggerBtn.addEventListener('click', () => {
if (fileInput) fileInput.click();
});
}
if (fileInput) fileInput.addEventListener('change', handleImportSettingsFile);
if (typeof window.addLog === 'function') {
window.addLog('Workspace backup, restore, and cryptographic migration modules successfully initialized.', 'info');
}
} catch (e) {
console.error("[Migration Core] Failed to initialize migration modules:", e);
}
}
// ============================================================================
// Workspace Backup Exporter (Strict AES-256-GCM)
// ============================================================================
async function exportSystemBackup() {
const msgContainer = document.getElementById('ie-status-msg');
if (msgContainer) msgContainer.textContent = "Packaging, compressing, and encrypting active workspace data blocks...";
const passphrase = prompt("Enter a secure backup protection password (minimum 8 characters):");
if (!passphrase || passphrase.length < 8) {
alert("Export aborted: Password must be at least 8 characters to ensure standard encryption strength.");
if (msgContainer) msgContainer.textContent = "Export cancelled by user.";
return;
}
const targetAccountId = prompt("If you wish to restrict restoration to a specific account, enter their 128-character public key (or leave blank for public use):");
if (targetAccountId && targetAccountId.trim().length !== 128) {
alert("Export aborted: The target public key must be exactly 128 alphanumeric characters.");
if (msgContainer) msgContainer.textContent = "Export failed due to invalid destination lock parameters.";
return;
}
try {
const exportPayload = {
timestamp: new Date().toISOString(),
version: "1.2.0-Simultaneous",
algo: "PBKDF2-SHA256-AES-GCM"
};
// 1. Pack Rotation matrix and templates in their current form
if (document.getElementById('chk-ie-cl')?.checked) {
exportPayload.contentLibraryData = await FritreeStorage.get('local_content_library', []);
exportPayload.contentCategoriesData = await FritreeStorage.get('local_content_categories', []);
exportPayload.previousPostsData = await FritreeStorage.get('local_previous_posts', []);
exportPayload.selectedPrevPostIds = await FritreeStorage.get('local_selected_prev_posts', []);
exportPayload.isRotationActive = await FritreeStorage.get('local_is_rotation_active', 'false');
exportPayload.rotationMode = await FritreeStorage.get('local_rotation_mode', 'balanced');
}
// 2. Pack Campaign history ledger
if (document.getElementById('chk-ie-ch')?.checked) {
exportPayload.campaignHistoryData = await FritreeStorage.get('campaignHistoryData', []);
}
// 3. Pack queue and scheduled parameters
if (document.getElementById('chk-ie-sch')?.checked) {
exportPayload.scheduledCampaigns = await FritreeStorage.get('scheduledCampaignsData', []);
}
// 4. Pack Groups registry and segments
if (document.getElementById('chk-ie-grp')?.checked) {
exportPayload.savedTags = await FritreeStorage.get('local_saved_tags', {});
exportPayload.selectedGroupIds = await FritreeStorage.get('local_selected_groups', []);
exportPayload.localGroups = await FritreeStorage.get('local_groups', []);
}
// 5. Pack Cooldowns and active protection configurations
if (document.getElementById('chk-ie-int')?.checked) {
exportPayload.sleepIntervals = await FritreeStorage.get('local_sleep_intervals', {});
exportPayload.protectionSettings = await FritreeStorage.get('local_protection_settings', {});
exportPayload.shieldConfigMatrix = await FritreeStorage.get('local_shield_config_matrix', {});
}
// 6. Pack transaction records and verified keys (EXCLUDING userPoints and fritreeAccountId)
exportPayload.pointsTransactions = await FritreeStorage.get('pointsTransactions', []);
exportPayload.usedSerials = await FritreeStorage.get('usedSerials', []);
exportPayload.usedTokens = await FritreeStorage.get('usedTokens', []);
// 7. Pack XP levels, multipliers, and achievements stats (EXCLUDING acc_fbShares and acc_waShares)
exportPayload.acc_userXP = await FritreeStorage.get('acc_userXP', 0);
exportPayload.acc_userLevel = await FritreeStorage.get('acc_userLevel', 1);
exportPayload.acc_lifetimeFb = await FritreeStorage.get('acc_lifetimeFb', 0);
exportPayload.acc_lifetimeWa = await FritreeStorage.get('acc_lifetimeWa', 0);
exportPayload.acc_lifetimeTasks = await FritreeStorage.get('acc_lifetimeTasks', 0);
exportPayload.acc_activeSub = await FritreeStorage.get('acc_activeSub', 'Lifetime Unlimited');
exportPayload.acc_subExpiry = await FritreeStorage.get('acc_subExpiry', null);
exportPayload.acc_tasks = await FritreeStorage.get('acc_tasks', []);
// 8. Pack WhatsApp broadcast environment variables
exportPayload.wa_connected = await FritreeStorage.get('wa_connected', false);
exportPayload.wa_phone_number = await FritreeStorage.get('wa_phone_number', 'Online');
exportPayload.wa_profile_name = await FritreeStorage.get('wa_profile_name', 'Active Account');
exportPayload.wa_sent_today = await FritreeStorage.get('wa_sent_today', 0);
const plainText = JSON.stringify(exportPayload);
const targetId = targetAccountId ? targetAccountId.trim() : null;
// Trigger AES-256-GCM encryption with destination account lock logic
const encryptedBase64 = await FritreeCrypto.encryptBackupString(plainText, passphrase, targetId);
if (encryptedBase64) {
const blob = new Blob([encryptedBase64], { type: 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
// Formulate target-specific seconds-level filename
const now = new Date();
const pad = num => String(num).padStart(2, '0');
const timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}-${pad(now.getMinutes())}-${pad(now.getSeconds())}`;
const fileSuffix = targetId ? "_RESTRICTED" : "_GENERAL";
a.download = `Fritree_Backup_${fileSuffix}_${timestamp}.txt`;
a.click();
URL.revokeObjectURL(url);
if (msgContainer) msgContainer.textContent = "Workspace backup package (.txt) generated and downloaded successfully.";
if (typeof window.addLog === 'function') {
window.addLog(`Encrypted backup of complete workspace state compiled successfully (${targetId ? "restricted destination lock applied" : "general public unlock allowed"}).`, 'success');
}
}
} catch (e) {
console.error("[Migration Core] Failed to compile backup package:", e);
if (msgContainer) msgContainer.textContent = "An error occurred during encryption packaging processing.";
}
}
// ============================================================================
// Workspace Backup Importer & Environment Restorer
// ============================================================================
async function handleImportSettingsFile(event) {
const file = event.target.files[0];
if (!file) return;
const msgContainer = document.getElementById('ie-status-msg');
if (msgContainer) msgContainer.textContent = "Reading backup file and verifying cryptographic signatures...";
const passphrase = prompt("Enter the protection password associated with this backup file to restore workspace state:");
if (!passphrase) {
if (msgContainer) msgContainer.textContent = "Import cancelled by user.";
event.target.value = '';
return;
}
const reader = new FileReader();
reader.onload = async (ev) => {
try {
const encryptedText = ev.target.result;
const currentId = await FritreeCrypto.getOrGenerateAccountId();
// Supply active local account ID to verify restriction boundaries on decryption
const decryptedText = await FritreeCrypto.decryptBackupString(encryptedText, passphrase, currentId);
if (!decryptedText) {
alert('Import failed: Decryption error. The password is incorrect, or the backup file has been corrupted or modified.');
if (msgContainer) msgContainer.textContent = "Decryption failure during restore process.";
event.target.value = '';
return;
}
const data = JSON.parse(decryptedText);
// Write decrypted database records securely using indexedDB
if (data.contentLibraryData) await FritreeStorage.set('local_content_library', data.contentLibraryData);
if (data.contentCategoriesData) await FritreeStorage.set('local_content_categories', data.contentCategoriesData);
if (data.campaignHistoryData) await FritreeStorage.set('campaignHistoryData', data.campaignHistoryData);
if (data.scheduledCampaigns) await FritreeStorage.set('scheduledCampaignsData', data.scheduledCampaigns);
if (data.savedTags) await FritreeStorage.set('local_saved_tags', data.savedTags);
if (data.selectedGroupIds) await FritreeStorage.set('local_selected_groups', data.selectedGroupIds);
if (data.localGroups) await FritreeStorage.set('local_groups', data.localGroups);
if (data.sleepIntervals) await FritreeStorage.set('local_sleep_intervals', data.sleepIntervals);
if (data.protectionSettings) await FritreeStorage.set('local_protection_settings', data.protectionSettings);
if (data.shieldConfigMatrix) await FritreeStorage.set('local_shield_config_matrix', data.shieldConfigMatrix);
// Restore Rotation templates and state in its current form
if (data.previousPostsData) {
await FritreeStorage.set('local_previous_posts', data.previousPostsData);
// Recalculate local rotation matrix integrity signature
const STATE_INTEGRITY_SALT = "FritreeRotationMatrixDynamicIntegrityVerificationSalt_2026";
const structuralConcat = data.previousPostsData.map(p => `${p.id}:${p.status}`).sort().join('||');
let computedSignature = "lite_hash_" + structuralConcat.length;
if (typeof FritreeCrypto !== 'undefined' && typeof FritreeCrypto.signReceipt === 'function') {
computedSignature = await FritreeCrypto.signReceipt("ROT_MATRIX", structuralConcat.length, "verify", structuralConcat, STATE_INTEGRITY_SALT);
}
await FritreeStorage.set('local_rotation_matrix_integrity_sig', computedSignature);
}
if (data.selectedPrevPostIds) await FritreeStorage.set('local_selected_prev_posts', data.selectedPrevPostIds);
if (data.isRotationActive) await FritreeStorage.set('local_is_rotation_active', data.isRotationActive);
if (data.rotationMode) await FritreeStorage.set('local_rotation_mode', data.rotationMode);
// Restore points transaction matrices (ignoring userPoints and fritree_account_id to prevent browser modifications)
if (data.pointsTransactions) await FritreeStorage.set('pointsTransactions', data.pointsTransactions);
if (data.usedSerials) await FritreeStorage.set('usedSerials', data.usedSerials);
if (data.usedTokens) await FritreeStorage.set('usedTokens', data.usedTokens);
// Restore level statistics & XP progress indicators (ignoring acc_fbShares and acc_waShares)
if (data.acc_userXP !== undefined) await FritreeStorage.set('acc_userXP', data.acc_userXP);
if (data.acc_userLevel !== undefined) await FritreeStorage.set('acc_userLevel', data.acc_userLevel);
if (data.acc_lifetimeFb !== undefined) await FritreeStorage.set('acc_lifetimeFb', data.acc_lifetimeFb);
if (data.acc_lifetimeWa !== undefined) await FritreeStorage.set('acc_lifetimeWa', data.acc_lifetimeWa);
if (data.acc_lifetimeTasks !== undefined) await FritreeStorage.set('acc_lifetimeTasks', data.acc_lifetimeTasks);
if (data.acc_activeSub !== undefined) await FritreeStorage.set('acc_activeSub', data.acc_activeSub);
if (data.acc_subExpiry !== undefined) await FritreeStorage.set('acc_subExpiry', data.acc_subExpiry);
if (data.acc_tasks !== undefined) await FritreeStorage.set('acc_tasks', data.acc_tasks);
// Restore WhatsApp broadcast environment variables
if (data.wa_connected !== undefined) await FritreeStorage.set('wa_connected', data.wa_connected);
if (data.wa_phone_number !== undefined) await FritreeStorage.set('wa_phone_number', data.wa_phone_number);
if (data.wa_profile_name !== undefined) await FritreeStorage.set('wa_profile_name', data.wa_profile_name);
if (data.wa_sent_today !== undefined) await FritreeStorage.set('wa_sent_today', data.wa_sent_today);
if (msgContainer) msgContainer.textContent = "Workspace state imported and restored successfully! Reloading environment to apply changes...";
if (typeof window.addLog === 'function') {
window.addLog('Verified backup imported successfully. Reloading active session environment.', 'success');
}
setTimeout(() => {
window.location.reload();
}, 1500);
} catch (err) {
console.error("[Migration Core] Error occurred during backup package importing:", err);
let fallbackErrorMsg = 'Restore failed: Please ensure you select a valid .fritree backup file and enter the correct decryption password.';
if (err.message === "RESTRICTED_ACCESS_DENIED") {
fallbackErrorMsg = "Decryption failure: This backup package was restricted for a different workspace ID.";
}
alert(fallbackErrorMsg);
if (msgContainer) msgContainer.textContent = "Restore failed.";
}
event.target.value = '';
};
reader.readAsText(file);
}
// Exports
global.FritreeMigration = {
init: initMigrationModule,
export: exportSystemBackup,
import: handleImportSettingsFile
};
if (document.readyState === 'complete' || document.readyState === 'interactive') {
initMigrationModule();
} else {
document.addEventListener('DOMContentLoaded', () => initMigrationModule());
}
})(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this);