Download migration.js from fritreefw/facebook: direct link, hf CLI and curl.
- Browser
- Download file 20.5 kB
-
https://huggingface.co/spaces/fritreefw/facebook/resolve/main/migration.js
- Command line
-
hf download hf://spaces/fritreefw/facebook/migration.js
-
curl -L -o migration.js https://huggingface.co/spaces/fritreefw/facebook/resolve/main/migration.js
20.5 kB
| // ============================================================================ | |
| // File: migration.js | |
| // ============================================================================ | |
| (global => { | |
| 'use strict'; | |
| /** | |
| * Injects HTML structures dynamically | |
| */ | |
| function renderStructuralHTMLTemplates() { | |
| const paneMigration = document.getElementById('pane-migration'); | |
| if (paneMigration) { | |
| paneMigration.innerHTML = ` | |
| <div class="card"> | |
| <div class="card-title"> | |
| <span><i class="fa-solid fa-database"></i><span>Workspace System Backup & State Migration</span></span> | |
| </div> | |
| <div class="export-grid" style="margin-top: 0;"> | |
| <div class="export-section"> | |
| <h3><i class="fa-solid fa-filter"></i><span>Choose data blocks to include in your package:</span></h3> | |
| <div class="export-checkboxes"> | |
| <div class="checkbox-group"><input type="checkbox" id="chk-ie-cl" checked> <label><i class="fa-solid fa-arrows-spin"></i><span>Rotation Matrix & Broadcast Templates</span></label></div> | |
| <div class="checkbox-group"><input type="checkbox" id="chk-ie-ch" checked> <label><i class="fa-solid fa-box-archive"></i><span>Campaign History & Delivery Ledgers</span></label></div> | |
| <div class="checkbox-group"><input type="checkbox" id="chk-ie-sch" checked> <label><i class="fa-solid fa-calendar-day"></i><span>Scheduled Tasks & Dispatch Queue</span></label></div> | |
| <div class="checkbox-group"><input type="checkbox" id="chk-ie-grp" checked> <label><i class="fa-solid fa-users"></i><span>Groups Registry & Saved Target Segments</span></label></div> | |
| <div class="checkbox-group"><input type="checkbox" id="chk-ie-int" checked> <label><i class="fa-solid fa-user-secret"></i><span>Cooldown Parameters & Stealth Profiles</span></label></div> | |
| </div> | |
| <div class="checkbox-group" style="margin-top:10px; border-top: 1px solid #e2e8f0; padding-top: 10px;"> | |
| <input type="checkbox" id="chk-ie-all" checked> | |
| <label style="font-weight:bold; color:var(--primary);"><i class="fa-solid fa-folder-open"></i><span>Package All Local Database Store Blocks</span></label> | |
| </div> | |
| </div> | |
| <!-- Import/Export Tools --> | |
| <div class="export-section"> | |
| <h3><i class="fa-solid fa-shield-halved"></i><span>Secure Export / Import Console</span></h3> | |
| <p style="font-size: 12px; color: var(--text-muted); margin-bottom: 15px;"> | |
| <i class="fa-solid fa-circle-info"></i><span>Export your workspace settings, targets, templates, and logs into a single encrypted backups file (.txt) to safely migrate your setup.</span> | |
| </p> | |
| <!-- Target Account restrictions --> | |
| <div class="form-group" style="margin-bottom: 12px;"> | |
| <label style="font-size: 11px; font-weight: bold;"><i class="fa-solid fa-lock"></i><span>Restrict Backup file to a specific Account ID (Optional):</span></label> | |
| <input type="text" id="export-restricted-target-id" class="search-box" style="font-family: monospace; font-size: 11px;" placeholder="Paste the target public key to restrict restoring on other systems..."> | |
| </div> | |
| <div style="display: flex; gap: 10px; margin-bottom: 10px;"> | |
| <button id="btn-export-settings" class="btn-primary" style="flex: 1;"><i class="fa-solid fa-file-export"></i><span>Export Backup Package</span></button> | |
| <button id="btn-import-settings-trigger" class="btn-secondary" style="flex: 1; background: #f59e0b; color: white;"><i class="fa-solid fa-file-import"></i><span>Import Backup Package</span></button> | |
| <input type="file" id="file-import-settings" accept=".txt" style="display: none;"> | |
| </div> | |
| <div id="ie-status-msg" style="font-size: 11px; color: var(--success); font-weight: bold; text-align: center;"></div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| } | |
| function sanitizeDataString(str) { | |
| if (!str) return ''; | |
| return String(str) | |
| .replace(/&/g, '&') | |
| .replace(/</g, '<') | |
| .replace(/>/g, '>') | |
| .replace(/"/g, '"') | |
| .replace(/'/g, '''); | |
| } | |
| function initMigrationModule() { | |
| try { | |
| renderStructuralHTMLTemplates(); | |
| 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); | |
| } | |
| } | |
| 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" | |
| }; | |
| 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'); | |
| } | |
| if (document.getElementById('chk-ie-ch')?.checked) { | |
| exportPayload.campaignHistoryData = await FritreeStorage.get('campaignHistoryData', []); | |
| } | |
| if (document.getElementById('chk-ie-sch')?.checked) { | |
| exportPayload.scheduledCampaigns = await FritreeStorage.get('scheduledCampaignsData', []); | |
| } | |
| 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', []); | |
| } | |
| 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', {}); | |
| } | |
| exportPayload.pointsTransactions = await FritreeStorage.get('pointsTransactions', []); | |
| exportPayload.usedSerials = await FritreeStorage.get('usedSerials', []); | |
| exportPayload.usedTokens = await FritreeStorage.get('usedTokens', []); | |
| 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', []); | |
| 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; | |
| 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; | |
| 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."; | |
| } | |
| } | |
| 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(); | |
| 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); | |
| 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); | |
| if (data.previousPostsData) { | |
| await FritreeStorage.set('local_previous_posts', data.previousPostsData); | |
| 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); | |
| 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); | |
| 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); | |
| 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 .txt 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); | |
| } | |
| 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); |