fc / orchestrator-controller.js
Althnayi's picture
Upload 56 files
cca0cf3 verified
Raw
History Blame Contribute Delete
76.2 kB
/**
* @fileoverview Main Orchestrator, Live Campaign Monitor, Scheduled Campaigns & Event Tunnel Controller
* @module controllers/orchestrator-controller
* @description المنسق العام للتطبيق، إدارة التوجيه، مراقبة الحملات الحية، المزامنة التلقائية اللحظية لفيسبوك وواتساب، وإدارة تثبيت PWA.
*/
(global => {
'use strict';
let isTermSuspended = false;
let isUiSyncActive = false;
let isFbSyncing = false;
let lastFbSyncTimestamp = 0;
let alivePort = null;
let campaignTimerInterval = null;
let campaignStartTime = null;
let totalCooldownSeconds = 0;
let completedStepsCount = 0;
let lastLaunchedCampaignId = null;
const activeCampaignsMetrics = new Map();
function silentTrap(err) {
return null;
}
/**
* حفظ اتصال مباشر ومستمر مع Service Worker
*/
const establishPersistentKeepAlive = () => {
try {
if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.connect) {
alivePort = chrome.runtime.connect({ name: "fritree-keep-alive" });
alivePort.onDisconnect.addListener(() => {
setTimeout(establishPersistentKeepAlive, 500);
});
}
} catch (e) {
silentTrap(e);
}
};
setInterval(() => {
try {
if (alivePort) {
alivePort.postMessage({ ping: true });
} else {
establishPersistentKeepAlive();
}
} catch (e) {
establishPersistentKeepAlive();
}
}, 2000);
function formatHHMMSS(totalSeconds) {
try {
const hrs = Math.floor(totalSeconds / 3600);
const mins = Math.floor((totalSeconds % 3600) / 60);
const secs = totalSeconds % 60;
return [
String(hrs).padStart(2, '0'),
String(mins).padStart(2, '0'),
String(secs).padStart(2, '0')
].join(':');
} catch (e) {
silentTrap(e);
return "00:00:00";
}
}
const setDomTextSafely = (elementId, value) => {
try {
const element = document.getElementById(elementId);
if (element) {
element.textContent = value;
return true;
}
return false;
} catch (e) {
silentTrap(e);
return false;
}
};
const startCampaignTrackingTimers = () => {
try {
campaignStartTime = Date.now();
totalCooldownSeconds = 0;
completedStepsCount = 0;
setDomTextSafely('ctldyt8www', '00:00:00');
setDomTextSafely('idrsed82qy', '00:00:00');
setDomTextSafely('e8fmmjhyng', '0 ثانية');
if (campaignTimerInterval) clearInterval(campaignTimerInterval);
campaignTimerInterval = setInterval(() => {
try {
if (!campaignStartTime) return;
const elapsedMs = Date.now() - campaignStartTime;
const elapsedSeconds = Math.floor(elapsedMs / 1000);
setDomTextSafely('ctldyt8www', formatHHMMSS(elapsedSeconds));
} catch (err) {
silentTrap(err);
}
}, 500);
} catch (e) {
silentTrap(e);
}
};
const stopCampaignTrackingTimers = () => {
try {
if (campaignTimerInterval) {
clearInterval(campaignTimerInterval);
campaignTimerInterval = null;
}
} catch (e) {
silentTrap(e);
}
};
/**
* بناء واجهة قسم جدولة الحملات وطابور الإرسال المجدول (#ss7cgkeahf)
*/
const buildSchedulerPaneLayout = () => {
const contentArea = document.getElementById('s7ihkirolg');
if (!contentArea) return false;
const host = document.getElementById('fritree-dynamic-panes-host') || contentArea;
let pane = document.getElementById('ss7cgkeahf');
if (pane) {
if (pane.parentElement !== host) {
host.appendChild(pane);
}
return true;
}
pane = document.createElement('section');
pane.className = 'rjiai07g77';
pane.id = 'ss7cgkeahf';
pane.innerHTML = `
<div class="d5tp7way8h zcjbe1otmg" style="margin: 0; padding: clamp(14px, 1.8vw, 24px); border-radius: var(--radius-xl); border: 1px solid var(--border); direction: rtl; text-align: right; background: var(--bg-card); box-sizing: border-box;">
<div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); padding-bottom: 14px; margin-bottom: 18px; flex-wrap: wrap; gap: 10px;">
<div>
<h2 style="font-size: clamp(15px, 1.2vw, 18px); font-weight: 900; display: flex; align-items: center; gap: 8px; margin: 0; color: var(--text-main);">
<i class="fa-solid fa-calendar-plus" style="color: #3b82f6;"></i>
<span>مركز إدارة وطابور الحملات المجدولة</span>
</h2>
<p style="font-size: 11px; color: var(--text-muted); margin-top: 4px; font-weight: 700;">
<i class="fa-solid fa-clock"></i>
<span>أتمتة إطلاق الحملات التسويقية في مواعيد محددة بدقة على فيسبوك وواتساب.</span>
</p>
</div>
</div>
<!-- نموذج إنشاء وتثبيت حملة مجدولة جديدة -->
<div style="border: 1px solid var(--border); border-radius: var(--radius-lg); padding: clamp(12px, 1.4vw, 18px); margin-bottom: 16px; background: var(--bg-subtle); box-sizing: border-box;">
<h3 style="font-size: 13.5px; font-weight: 900; margin: 0 0 12px 0; display: flex; align-items: center; gap: 6px; border-bottom: 1px solid var(--border); padding-bottom: 8px; color: var(--text-main);">
<i class="fa-solid fa-calendar-check" style="color: var(--primary);"></i> <span>إنشاء وتثبيت موعد حملة مجدولة جديدة</span>
</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(clamp(180px, 20vw, 280px), 1fr)); gap: 10px; margin-bottom: 10px;">
<div class="d0uttwsjz2" style="margin: 0;">
<label style="font-size: 11px; font-weight: 700;"><i class="fa-solid fa-heading"></i> <span>اسم أو عنوان الحملة:</span></label>
<input type="text" id="sched-create-name" class="xy26ymifmf" placeholder="مثال: حملة عروض نهاية الأسبوع..." style="padding: 8px 10px;">
</div>
<div class="d0uttwsjz2" style="margin: 0;">
<label style="font-size: 11px; font-weight: 700;"><i class="fa-solid fa-shapes"></i> <span>المنصة المستهدفة:</span></label>
<select id="sched-create-platform" class="xy26ymifmf" style="padding: 8px 10px; font-weight: 700;">
<option value="facebook" selected>منصة فيسبوك (Facebook Groups)</option>
<option value="whatsapp">منصة واتساب (WhatsApp Broadcast)</option>
</select>
</div>
<div class="d0uttwsjz2" style="margin: 0;">
<label style="font-size: 11px; font-weight: 700;"><i class="fa-solid fa-clock"></i> <span>تاريخ ووقت الانطلاق:</span></label>
<input type="datetime-local" id="sched-create-datetime" class="xy26ymifmf" style="padding: 6px 8px; font-size: 11px;">
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(clamp(260px, 30vw, 1fr), 1fr)); gap: 10px; margin-bottom: 10px;">
<div class="d0uttwsjz2" style="margin: 0;">
<label style="font-size: 11px; font-weight: 700;"><i class="fa-solid fa-message"></i> <span>نص رسالة أو منشور الحملة:</span></label>
<textarea id="sched-create-text" class="f0ngq4vbzj" style="height: 75px; min-height: 60px;" placeholder="اكتب نص المنشور أو الرسالة هنا..."></textarea>
</div>
<div style="display: flex; flex-direction: column; gap: 8px; justify-content: space-between;">
<div class="d0uttwsjz2" style="margin: 0;">
<label style="font-size: 11px; font-weight: 700;"><i class="fa-solid fa-layer-group"></i> <span>ربط بحزمة تدوير مخصصة (اختياري):</span></label>
<select id="sched-create-group-select" class="xy26ymifmf" style="padding: 7px 10px; font-size: 11px;">
<option value="">-- بدون ربط (استخدام النص المباشر) --</option>
</select>
</div>
<button type="button" id="btn-submit-create-scheduled" class="itdnt14mss" style="padding: 10px; font-size: 12px; font-weight: 800; width: 100%; min-height: 36px;">
<i class="fa-solid fa-calendar-plus"></i> <span>جدولة وإضافة لطابور الانتظار</span>
</button>
</div>
</div>
</div>
<!-- جدول طابور الحملات المجدولة -->
<div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
<h3 style="font-size: 13.5px; font-weight: 900; margin: 0; display: flex; align-items: center; gap: 6px; color: var(--text-main);">
<i class="fa-solid fa-list-ol" style="color: var(--primary);"></i> <span>طابور الحملات المجدولة المسجلة</span>
</h3>
<span id="sched-queue-count-badge" style="font-size: 10.5px; font-weight: 800; background: var(--bg-subtle); color: var(--text-secondary); padding: 2px 8px; border-radius: var(--radius-pill); border: 1px solid var(--border); font-family: var(--font-code);">
0 حملات في الطابور
</span>
</div>
<div class="diktqr0h64" style="max-height: 440px;">
<table style="width: 100%; border-collapse: collapse; direction: rtl; text-align: right;">
<thead>
<tr>
<th style="width: 25%; padding: 10px 12px;"><i class="fa-solid fa-bullseye"></i> <span>اسم وتفاصيل الحملة</span></th>
<th style="width: 15%; text-align: center; padding: 10px 12px;"><i class="fa-solid fa-shapes"></i> <span>المنصة</span></th>
<th style="width: 25%; padding: 10px 12px;"><i class="fa-solid fa-clock"></i> <span>موعد الإطلاق المجدول</span></th>
<th style="width: 15%; text-align: center; padding: 10px 12px;"><i class="fa-solid fa-circle-info"></i> <span>الحالة</span></th>
<th style="width: 20%; text-align: center; padding: 10px 12px;"><i class="fa-solid fa-sliders"></i> <span>الإجراءات</span></th>
</tr>
</thead>
<tbody id="sched-queue-tbody">
<tr>
<td colspan="5" style="text-align: center; color: var(--text-muted); padding: 30px; font-size: 11.5px;">
<i class="fa-solid fa-calendar-xmark" style="font-size: 24px; display: block; margin-bottom: 6px;"></i>
<span>لا توجد أي حملات مجدولة مسجلة في طابور الانتظار حالياً.</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
`;
host.appendChild(pane);
renderScheduledQueueTable();
bindSchedulerPaneEvents();
return true;
};
const renderScheduledQueueTable = async () => {
const tbody = document.getElementById('sched-queue-tbody');
const countBadge = document.getElementById('sched-queue-count-badge');
const groupSelect = document.getElementById('sched-create-group-select');
if (!tbody || !global.FritreeStorage) return;
const list = await global.FritreeStorage.get('scheduledCampaignsData', []) || [];
if (countBadge) countBadge.textContent = `${list.length.toLocaleString('en-US')} حملات في الطابور`;
if (groupSelect && global.FritreeRotation) {
const groups = global.FritreeRotation.getGroups() || [];
groupSelect.innerHTML = '<option value="">-- بدون ربط (استخدام النص المباشر) --</option>';
groups.forEach(g => {
const opt = document.createElement('option');
opt.value = g.id;
opt.textContent = `حزمة: ${g.name} (${(g.postIds || []).length} منشور)`;
groupSelect.appendChild(opt);
});
}
tbody.innerHTML = '';
if (list.length === 0) {
tbody.innerHTML = `
<tr>
<td colspan="5" style="text-align: center; color: var(--text-muted); padding: 30px; font-size: 11.5px;">
<i class="fa-solid fa-calendar-xmark" style="font-size: 24px; display: block; margin-bottom: 6px; color: var(--border-strong);"></i>
<span>لا توجد أي حملات مجدولة مسجلة في طابور الانتظار حالياً.</span>
</td>
</tr>
`;
return;
}
list.forEach(c => {
const tr = document.createElement('tr');
tr.style.cssText = 'border-bottom: 1px solid var(--border);';
const isFb = c.platform === 'facebook';
const platformBadge = isFb ?
`<span style="background:var(--primary-light); color:var(--primary); border:1px solid var(--primary-border); font-size:9.5px; font-weight:800; padding:2px 8px; border-radius:var(--radius-pill);"><i class="fa-brands fa-facebook"></i> فيسبوك</span>` :
`<span style="background:var(--wa-light); color:var(--wa-brand); border:1px solid var(--wa-border); font-size:9.5px; font-weight:800; padding:2px 8px; border-radius:var(--radius-pill);"><i class="fa-brands fa-whatsapp"></i> واتساب</span>`;
let statusLabel = 'قيد الانتظار';
let statusClass = 'go30y9mfgh pending';
if (c.status === 'completed') {
statusLabel = 'مكتملة بنجاح';
statusClass = 'go30y9mfgh success';
} else if (c.status === 'running') {
statusLabel = 'جاري الإطلاق';
statusClass = 'go30y9mfgh running';
} else if (c.status === 'failed') {
statusLabel = 'فشلت';
statusClass = 'go30y9mfgh failed';
}
const targetInfo = isFb ?
`الجروبات: ${(c.groupIds || []).length} جروب` :
`المستلمين: ${(c.recipients || []).length} عميل`;
tr.innerHTML = `
<td style="padding: 10px 12px; font-weight: 700;">
<div style="color:var(--text-main); font-size:12px;">${c.name || 'حملة مجدولة'}</div>
<span style="font-size: 10px; color: var(--text-muted); font-weight: normal;">${targetInfo} ${c.postGroupId ? '| مرتبطة بحزمة تدوير' : ''}</span>
</td>
<td style="text-align: center; padding: 10px 12px;">${platformBadge}</td>
<td style="padding: 10px 12px; font-size: 11px; font-weight: 700; direction: ltr; text-align: right; font-family: var(--font-code); color: var(--text-secondary);">
<i class="fa-regular fa-clock" style="margin-right: 4px;"></i> ${new Date(c.scheduledTime).toLocaleString('en-US')}
</td>
<td style="text-align: center; padding: 10px 12px;">
<span class="${statusClass}">
${statusLabel}
</span>
</td>
<td style="text-align: center; padding: 10px 12px;">
<div style="display: flex; gap: 4px; justify-content: center;">
<button type="button" class="ipxi2jz4g0 btn-run-sched-now" data-sched-id="${c.id}" style="padding: 3px 8px; font-size: 10px; font-weight: 800; min-height: 28px;" title="إطلاق الحملة فوراً الآن">
<i class="fa-solid fa-bolt" style="color: #f59e0b;"></i> <span>تشغيل</span>
</button>
<button type="button" class="btn-danger btn-delete-sched" data-sched-id="${c.id}" style="padding: 3px 8px; font-size: 10px; min-height: 28px;" title="إلغاء وحذف من الجدولة">
<i class="fa-solid fa-trash"></i>
</button>
</div>
</td>
`;
tr.querySelector('.btn-run-sched-now').onclick = async () => {
if (confirm(`هل تريد إطلاق الحملة "${c.name}" فوراً الآن وتجاوز موعد الجدولة؟`)) {
chrome.runtime.sendMessage({
action: 'execute_scheduled_campaign_immediately',
campaignId: c.id
}, () => {
renderScheduledQueueTable();
if (global.syncWorkspaceUI) global.syncWorkspaceUI();
});
}
};
tr.querySelector('.btn-delete-sched').onclick = async () => {
if (confirm(`هل تريد إلغاء وحذف الحملة المجدولة "${c.name}"؟`)) {
let updatedList = await global.FritreeStorage.get('scheduledCampaignsData', []) || [];
updatedList = updatedList.filter(item => item.id !== c.id);
await global.FritreeStorage.set('scheduledCampaignsData', updatedList);
renderScheduledQueueTable();
}
};
tbody.appendChild(tr);
});
};
const bindSchedulerPaneEvents = () => {
const btnSubmitCreate = document.getElementById('btn-submit-create-scheduled');
if (btnSubmitCreate) {
btnSubmitCreate.onclick = async () => {
const name = (document.getElementById('sched-create-name')?.value || '').trim();
const platform = document.getElementById('sched-create-platform')?.value || 'facebook';
const scheduledTime = document.getElementById('sched-create-datetime')?.value;
const text = (document.getElementById('sched-create-text')?.value || '').trim();
const postGroupId = document.getElementById('sched-create-group-select')?.value || '';
if (!name) {
alert('يرجى كتابة اسم واضح للحملة المجدولة!');
return;
}
if (!scheduledTime || new Date(scheduledTime).getTime() <= Date.now()) {
alert('يرجى تحديد تاريخ ووقت مستقبلي صالح لانطلاق الحملة!');
return;
}
let targetGroupIds = [];
let targetRecipients = [];
if (platform === 'facebook') {
targetGroupIds = global.FritreeFacebook ? global.FritreeFacebook.getSelectedIds() : [];
if (targetGroupIds.length === 0) {
const allFb = await global.FritreeStorage.get('local_groups', []);
targetGroupIds = allFb.map(g => g.id);
}
if (targetGroupIds.length === 0) {
alert('يرجى تحديد أو استيراد مجموعات فيسبوك أولاً لربطها بالحملة!');
return;
}
} else {
targetRecipients = global.FritreeWhatsApp ? global.FritreeWhatsApp.getRecipients() : [];
if (targetRecipients.length === 0) {
const allRecs = await global.FritreeStorage.get('local_wa_recipients_queue', []);
targetRecipients = allRecs;
}
if (targetRecipients.length === 0) {
alert('يرجى إضافة أو جلب مستلمي واتساب أولاً لربطهم بالحملة!');
return;
}
}
const newSchedItem = {
id: 'sched_' + Date.now() + '_' + Math.random().toString(36).substr(2, 4),
name: name,
platform: platform,
scheduledTime: scheduledTime,
text: text,
useGroupRotation: !!postGroupId,
postGroupId: postGroupId,
groupIds: targetGroupIds,
recipients: targetRecipients,
status: 'scheduled',
createdAt: new Date().toISOString()
};
const currentList = await global.FritreeStorage.get('scheduledCampaignsData', []) || [];
currentList.unshift(newSchedItem);
await global.FritreeStorage.set('scheduledCampaignsData', currentList);
if (global.FritreeCalendarStore && typeof global.FritreeCalendarStore.logActivity === 'function') {
await global.FritreeCalendarStore.logActivity({
title: `[حملة مجدولة] ${name}`,
type: 'campaign',
timestamp: scheduledTime,
notes: `حملة تسويقية مجدولة على منصة ${platform === 'whatsapp' ? 'واتساب' : 'فيسبوك'}`
});
}
alert(`تم بنجاح جدولة الحملة "${name}" لتنطلق تلقائياً بتاريخ: ${new Date(scheduledTime).toLocaleString('en-US')}`);
document.getElementById('sched-create-name').value = '';
document.getElementById('sched-create-text').value = '';
renderScheduledQueueTable();
};
}
};
/**
* مزامنة حالة التطبيق والواجهة الشاملة
*/
const syncWorkspaceUI = async () => {
if (isUiSyncActive) return;
isUiSyncActive = true;
try {
if (global.FritreeAppState && typeof global.FritreeAppState.loadDashboardState === 'function') {
await global.FritreeAppState.loadDashboardState();
}
if (global.FritreeShellLayout && typeof global.FritreeShellLayout.updatePointsUI === 'function') {
await global.FritreeShellLayout.updatePointsUI();
}
if (global.FritreeProgressionService && typeof global.FritreeProgressionService.renderTasksUI === 'function') {
global.FritreeProgressionService.renderTasksUI();
}
if (global.FritreeAntibanRulesService && typeof global.FritreeAntibanRulesService.evaluateRisk === 'function') {
await global.FritreeAntibanRulesService.evaluateRisk();
}
} catch (err) {
silentTrap(err);
} finally {
isUiSyncActive = false;
}
};
const startWorkspaceSecurityHeartbeat = () => {
try {
setInterval(async () => {
try {
await syncWorkspaceUI();
await checkConnectedSessions();
} catch (err) {
silentTrap(err);
}
}, 3000);
} catch (e) {
silentTrap(e);
}
};
const ensurePanesOrderInDOM = () => {
const host = document.getElementById('fritree-dynamic-panes-host');
const mainContent = document.getElementById('s7ihkirolg');
const monitoringPanel = document.getElementById('cxyr0eirov');
if (!host && mainContent && monitoringPanel) {
document.querySelectorAll('.rjiai07g77').forEach(pane => {
if (pane.parentElement === mainContent) {
mainContent.insertBefore(pane, monitoringPanel);
}
});
} else if (host) {
document.querySelectorAll('.rjiai07g77').forEach(pane => {
if (pane.parentElement !== host) {
host.appendChild(pane);
}
});
}
};
/**
* الانتقال بين الشاشات الرئيسية
* @param {string} targetId
*/
const navigateToPane = async (targetId) => {
try {
if (targetId === 'pane-fb-group-health' || targetId === 'pane-fb-heatmap') {
targetId = 'sf1xx5vcac';
}
if (targetId === 'qt3bcp0qq8' && global.FritreeStealthUI) {
global.FritreeStealthUI.buildPane();
global.FritreeStealthUI.loadForm();
} else if (targetId === 'oboufoudrv' && global.FritreeBackupService) {
global.FritreeBackupService.buildPane();
global.FritreeBackupService.refreshBadges();
} else if (targetId === 'ss7cgkeahf') {
buildSchedulerPaneLayout();
renderScheduledQueueTable();
}
ensurePanesOrderInDOM();
document.querySelectorAll('.rjiai07g77').forEach(p => p.classList.remove('vn5qn7dmpk'));
const targetPane = document.getElementById(targetId);
if (targetPane) {
targetPane.classList.add('vn5qn7dmpk');
}
if (targetId === 'gaap721x61' && global.FritreeCalendar) {
if (typeof global.FritreeCalendar.init === 'function') await global.FritreeCalendar.init();
if (typeof global.FritreeCalendar.render === 'function') await global.FritreeCalendar.render();
} else if (targetId === 'ny517knjde' && global.FritreeContacts) {
if (typeof global.FritreeContacts.refreshUI === 'function') global.FritreeContacts.refreshUI();
} else if (targetId === 'i2ohy2hnfl' && global.FritreeRotation) {
if (typeof global.FritreeRotation.renderPreviousPostsGrid === 'function') global.FritreeRotation.renderPreviousPostsGrid();
if (typeof global.FritreeRotation.updateRotationIndicatorUI === 'function') global.FritreeRotation.updateRotationIndicatorUI();
} else if (targetId === 'j2nzw12azj' && global.FritreeWallet) {
if (typeof global.FritreeWallet.renderLedgerTable === 'function') await global.FritreeWallet.renderLedgerTable();
if (typeof global.FritreeWallet.renderCapsules === 'function') await global.FritreeWallet.renderCapsules();
} else if (targetId === 'xhcwhbkzqe' && global.FritreeHistory) {
if (typeof global.FritreeHistory.refresh === 'function') global.FritreeHistory.refresh();
} else if (targetId === 'dc1z57si9s' && global.FritreeStoreCalculator) {
if (typeof global.FritreeStoreCalculator.updateCalculator === 'function') global.FritreeStoreCalculator.updateCalculator();
}
window.scrollTo({ top: 0, behavior: 'smooth' });
await syncWorkspaceUI();
} catch (e) {
silentTrap(e);
}
};
/**
* موجه الروابط (Hash Router)
*/
const executeHashRouter = () => {
try {
const hash = window.location.hash.slice(1);
const validPanes = [
'h7qak5tprs', 'sf1xx5vcac', 'i2ohy2hnfl', 'sf8pufcpyl',
'ny517knjde', 'qt3bcp0qq8', 'j2nzw12azj', 'dc1z57si9s',
'xhcwhbkzqe', 'oboufoudrv', 'xrsxtjzo87', 'ss7cgkeahf',
'gaap721x61'
];
if (validPanes.includes(hash)) {
navigateToPane(hash);
} else if (hash === 'pane-fb-group-health' || hash === 'pane-fb-heatmap') {
window.location.hash = 'sf1xx5vcac';
} else {
window.location.hash = 'h7qak5tprs';
}
} catch (e) {
silentTrap(e);
}
};
/**
* تسجيل رسالة بسجل الأوامر المباشر (Live Terminal)
*/
const addLog = (payload, type = "info") => {
try {
if (isTermSuspended) return;
const terminal = document.getElementById('r99bttinj8');
if (!terminal) return;
let msg = typeof payload === 'object' && payload !== null ? (payload.ar || payload.en || '') : String(payload);
if (msg.toLowerCase().includes("error") || msg.toLowerCase().includes("failed") || msg.toLowerCase().includes("exception")) {
msg = "درع الأمان: تم تحديث خطوات الإرسال التلقائي لحماية حسابك.";
type = "warn";
}
const time = new Date().toLocaleTimeString('en-US');
const line = document.createElement('div');
line.className = 'xat4o6cs3m';
const timeSpan = document.createElement('span');
timeSpan.className = 'fe5xz6pikv';
timeSpan.textContent = `[${time}]`;
const msgSpan = document.createElement('span');
let classType = 'ma43slkxth';
let defaultIcon = '<i class="fa-solid fa-circle-info"></i> ';
if (type === 'success') {
classType = 'hjxwx50o9j';
defaultIcon = '<i class="fa-solid fa-circle-check"></i> ';
} else if (type === 'error') {
classType = 'j640dqp9ki';
defaultIcon = '<i class="fa-solid fa-triangle-exclamation"></i> ';
} else if (type === 'warn') {
classType = 'j271lhps8l';
defaultIcon = '<i class="fa-solid fa-circle-exclamation"></i> ';
} else if (type === 'security') {
classType = 'hjxwx50o9j';
defaultIcon = '<i class="fa-solid fa-shield-virus"></i> ';
}
const finalIcon = getDynamicIconForText(msg, defaultIcon);
msgSpan.className = classType;
msgSpan.innerHTML = `${finalIcon} <span>${msg}</span>`;
line.appendChild(timeSpan);
line.appendChild(msgSpan);
terminal.appendChild(line);
terminal.scrollTop = terminal.scrollHeight;
} catch (e) {
silentTrap(e);
}
};
const getDynamicIconForText = (msg, defaultIcon) => {
try {
const text = (msg || '').toString().toLowerCase();
if (text.includes('facebook') || text.includes('[facebook]') || text.includes('فيسبوك')) return '<i class="fa-brands fa-facebook"></i> ';
if (text.includes('whatsapp') || text.includes('[whatsapp]') || text.includes('واتساب')) return '<i class="fa-brands fa-whatsapp"></i> ';
if (text.includes('cooldown') || text.includes('wait') || text.includes('seconds') || text.includes('تبريد') || text.includes('انتظار') || text.includes('ثانية')) return '<i class="fa-solid fa-hourglass-half"></i> ';
if (text.includes('campaign') || text.includes('broadcast') || text.includes('post') || text.includes('حملة') || text.includes('بث')) return '<i class="fa-solid fa-bullhorn" style="color:#3b82f6;"></i> ';
if (text.includes('success') || text.includes('completed') || text.includes('dispatched') || text.includes('نجاح') || text.includes('بنجاح') || text.includes('اكتملت')) return '<i class="fa-solid fa-circle-check"></i> ';
if (text.includes('failed') || text.includes('error') || text.includes('aborted') || text.includes('فشل') || text.includes('خطأ')) return '<i class="fa-solid fa-circle-xmark"></i> ';
if (text.includes('security') || text.includes('integrity') || text.includes('shield') || text.includes('أمان') || text.includes('حظر') || text.includes('درع')) return '<i class="fa-solid fa-shield-halved"></i> ';
if (text.includes('wallet') || text.includes('points') || text.includes('usd') || text.includes('balance') || text.includes('محفظة') || text.includes('رصيد') || text.includes('نقطة')) return '<i class="fa-solid fa-wallet"></i> ';
if (text.includes('group') || text.includes('groups') || text.includes('مجموع')) return '<i class="fa-solid fa-users" style="color:#3b82f6;"></i> ';
return defaultIcon;
} catch (e) {
silentTrap(e);
return defaultIcon;
}
};
/**
* محرك المزامنة الذاتية والتلقائية لمجموعات وجلسة فيسبوك (Smart Auto-Sync)
*/
const triggerFacebookGroupsSync = (isManual = false) => {
if (isFbSyncing) return;
const now = Date.now();
// حماية من التكرار السريع إلا في حال الضغط اليدوي
if (!isManual && (now - lastFbSyncTimestamp < 60000)) return;
isFbSyncing = true;
lastFbSyncTimestamp = now;
if (isManual) {
addLog("جاري فحص وتوثيق جلسة فيسبوك ومزامنة المجموعات...", "info");
}
if (chrome && chrome.runtime && chrome.runtime.sendMessage) {
chrome.runtime.sendMessage({ action: 'getGroups' }, async (response) => {
isFbSyncing = false;
if (response && response.success && response.groups && response.groups.length > 0) {
if (global.FritreeFacebook && typeof global.FritreeFacebook.setGroups === 'function') {
await global.FritreeFacebook.setGroups(response.groups, response.userId);
}
if (global.FritreeStorage) {
await global.FritreeStorage.set('local_groups', response.groups);
await global.FritreeStorage.set('userId', response.userId || 'fb_user');
}
const fbDashGroups = document.getElementById('ua07ivc7rv');
if (fbDashGroups) fbDashGroups.innerHTML = `<i class="fa-solid fa-users"></i> <span>${response.groups.length.toLocaleString('en-US')}</span>`;
const badge = document.getElementById('d769nsyxio');
const statusText = document.getElementById('mbgc4irrsa');
const startFbBtn = document.getElementById('q0ilg5gt03');
if (badge) {
badge.style.background = "var(--primary-light)";
badge.style.borderColor = "var(--primary-border)";
}
if (statusText) {
statusText.innerHTML = `<i class="fa-solid fa-plug-circle-check"></i> <span>فيسبوك متصل</span>`;
statusText.style.color = "var(--primary)";
}
if (startFbBtn) startFbBtn.disabled = false;
addLog(`تمت مزامنة [${response.groups.length.toLocaleString('en-US')}] مجموعة فيسبوك بنجاح!`, "success");
} else {
if (isManual) {
addLog(response?.message || "يرجى تسجيل الدخول إلى فيسبوك في المتصفح لتوثيق الجلسة.", "warn");
}
}
});
} else {
isFbSyncing = false;
}
};
/**
* فحص حالة اتصال جلسات فيسبوك وواتساب بدقة متقدمة
*/
const checkConnectedSessions = async () => {
try {
// تحميل المجموعات المخزنة مباشرة في الواجهة
if (global.FritreeStorage) {
const storedFbGroups = await global.FritreeStorage.get('local_groups', []);
if (storedFbGroups && storedFbGroups.length > 0) {
const fbDashGroups = document.getElementById('ua07ivc7rv');
if (fbDashGroups) fbDashGroups.innerHTML = `<i class="fa-solid fa-users"></i> <span>${storedFbGroups.length.toLocaleString('en-US')}</span>`;
}
}
if (typeof chrome === 'undefined') return;
// 1. فحص ملف تعريف الارتباط لفيسبوك
if (chrome.cookies && chrome.cookies.getAll) {
chrome.cookies.getAll({ domain: '.facebook.com', name: 'c_user' }, (cookies) => {
let cUserVal = (cookies && cookies.length > 0) ? cookies[0].value : null;
if (!cUserVal) {
chrome.cookies.getAll({ name: 'c_user' }, (allC) => {
const found = (allC || []).find(c => c.domain && c.domain.includes('facebook'));
handleFacebookCookieResult(found ? found.value : null);
});
} else {
handleFacebookCookieResult(cUserVal);
}
});
} else {
// في وضع PWA
const storedFbGroups = global.FritreeStorage ? await global.FritreeStorage.get('local_groups', []) : [];
if (storedFbGroups && storedFbGroups.length > 0) {
handleFacebookCookieResult('pwa_synced_user');
}
}
// 2. فحص واتساب
if (chrome.tabs && chrome.tabs.query) {
chrome.tabs.query({ url: ['*://web.whatsapp.com/*', '*://*.whatsapp.com/*'] }, async (tabs) => {
const hasTab = tabs && tabs.length > 0;
const isWaStoredConnected = global.FritreeStorage ? await global.FritreeStorage.get('wa_connected', false) : false;
const finalWaConnected = hasTab || isWaStoredConnected;
updateWAUIStatus(finalWaConnected);
});
} else {
const isWaStored = global.FritreeStorage ? await global.FritreeStorage.get('wa_connected', false) : false;
updateWAUIStatus(isWaStored);
}
} catch (e) {
silentTrap(e);
}
};
const handleFacebookCookieResult = (cUserVal) => {
const badge = document.getElementById('d769nsyxio');
const startFbBtn = document.getElementById('q0ilg5gt03');
const statusText = document.getElementById('mbgc4irrsa');
if (cUserVal) {
if (badge) {
badge.style.background = "var(--primary-light)";
badge.style.borderColor = "var(--primary-border)";
}
if (statusText) {
statusText.innerHTML = `<i class="fa-solid fa-plug-circle-check"></i> <span>فيسبوك متصل</span>`;
statusText.style.color = "var(--primary)";
}
if (startFbBtn) startFbBtn.disabled = false;
// إطلاق المزامنة الذاتية إن لم تتم مؤخراً
triggerFacebookGroupsSync(false);
} else {
if (badge) {
badge.style.background = "var(--danger-light)";
badge.style.borderColor = "var(--danger-border)";
}
if (statusText) {
statusText.innerHTML = `<i class="fa-solid fa-plug-circle-xmark"></i> <span>فيسبوك غير متصل</span>`;
statusText.style.color = "var(--danger)";
}
}
};
const updateWAUIStatus = (connected) => {
try {
const badge = document.getElementById('hzo3r22pug');
const startWaBtn = document.getElementById('ciqrxeqovl');
const warningBanner = document.getElementById('ns1lig1nty');
const statusText = document.getElementById('hii0s83z9e');
if (badge) {
if (connected) {
badge.style.background = "var(--wa-light)";
badge.style.borderColor = "var(--wa-border)";
if (statusText) {
statusText.innerHTML = `<i class="fa-solid fa-plug-circle-check"></i> <span>واتساب متصل</span>`;
statusText.style.color = "var(--wa-brand)";
}
} else {
badge.style.background = "var(--danger-light)";
badge.style.borderColor = "var(--danger-border)";
if (statusText) {
statusText.innerHTML = `<i class="fa-solid fa-plug-circle-xmark"></i> <span>واتساب غير متصل</span>`;
statusText.style.color = "var(--danger)";
}
}
}
if (startWaBtn) startWaBtn.disabled = !connected;
if (warningBanner) warningBanner.style.display = connected ? 'none' : 'block';
} catch (e) {
silentTrap(e);
}
};
/**
* إطلاق حملة نشر فيسبوك فورية أو جدولتها
*/
const triggerFacebookCampaign = async () => {
const selectedGroupIds = global.FritreeFacebook ? global.FritreeFacebook.getSelectedIds() : [];
if (selectedGroupIds.length === 0) {
alert('اختار مجموعة فيسبوك واحدة على الأقل لبدء الحملة!');
return;
}
const isScheduleChecked = document.getElementById('k58hokq80h')?.checked || false;
const scheduledTime = document.getElementById('b3qy01i1dm')?.value;
if (isScheduleChecked) {
if (!scheduledTime || new Date(scheduledTime).getTime() <= Date.now()) {
alert('اختر تاريخاً ووقتاً مستقبلياً صالحاً لجدولة الحملة!');
return;
}
const baseText = global.FritreeFacebookComposer ? global.FritreeFacebookComposer.getComposerText() : '';
const images = global.FritreeFacebookComposer ? await global.FritreeFacebookComposer.getUploadedImages() : [];
const delayConfig = global.FritreeFacebookComposer ? global.FritreeFacebookComposer.getDelayConfig() : { mode: 'random', minSeconds: 45, maxSeconds: 120 };
const launchMode = document.getElementById('q2hxmk5c3l')?.value || 'tab';
const newSchedItem = {
id: 'sched_fb_' + Date.now() + '_' + Math.random().toString(36).substr(2, 4),
name: `حملة فيسبوك مجدولة (${selectedGroupIds.length} مجموعة)`,
platform: 'facebook',
scheduledTime: scheduledTime,
text: baseText,
images: images,
groupIds: selectedGroupIds,
delayConfig: delayConfig,
launchMode: launchMode,
status: 'scheduled',
createdAt: new Date().toISOString()
};
const currentList = await global.FritreeStorage.get('scheduledCampaignsData', []) || [];
currentList.unshift(newSchedItem);
await global.FritreeStorage.set('scheduledCampaignsData', currentList);
alert(`تمت جدولة حملة فيسبوك بنجاح لتنطلق تلقائياً بتاريخ: ${new Date(scheduledTime).toLocaleString('en-US')}`);
window.location.hash = 'ss7cgkeahf';
return;
}
const fbPoints = global.FritreeDashboard ? global.FritreeDashboard.getFbPoints() : 0;
if (fbPoints < 1) {
handleInsufficientBalanceAbort('facebook');
return;
}
let baseText = "";
let images = [];
let isLibraryMode = false;
let payloadMap = {};
const resetPublishButtonsOnFailure = () => {
const btnStart = document.getElementById('q0ilg5gt03');
const btnStop = document.getElementById('ctmo3psebt');
const btnFreeze = document.getElementById('te6ue1mcua');
if (btnStart) btnStart.disabled = false;
if (btnStop) btnStop.disabled = true;
if (btnFreeze) btnFreeze.disabled = true;
};
try {
const isRotationActive = global.FritreeRotation ? global.FritreeRotation.isRotationActive() : false;
if (isRotationActive) {
isLibraryMode = true;
addLog("جاري تجهيز وتوزيع المنشورات من مكتبة التدوير التلقائي...", "info");
const activeMode = await global.FritreeStorage.get('local_rotation_mode', 'balanced');
const availableIds = global.FritreeRotation.getPosts().map(p => p.id);
if (availableIds.length === 0) {
alert("وضع التدوير مفعل ولكن لا توجد منشورات نشطة محددة.");
resetPublishButtonsOnFailure();
return;
}
for (let idx = 0; idx < selectedGroupIds.length; idx++) {
const gId = selectedGroupIds[idx];
const postObj = global.FritreeRotation.selectNextPost(activeMode, availableIds);
if (!postObj) {
alert("لم يتم العثور على منشور نشط يطابق شروط التدوير الحالية.");
resetPublishButtonsOnFailure();
return;
}
payloadMap[gId] = {
text: postObj.text || postObj.altText || '',
images: postObj.mediaReferences || [],
uuid: postObj.id
};
}
} else {
baseText = global.FritreeFacebookComposer ? global.FritreeFacebookComposer.getComposerText() : '';
images = global.FritreeFacebookComposer ? await global.FritreeFacebookComposer.getUploadedImages() : [];
if (!baseText && images.length === 0) {
alert("لا يمكن نشر منشور فارغ! اكتب نصاً أو ارفع صورة أولاً.");
resetPublishButtonsOnFailure();
return;
}
}
const delayConfig = global.FritreeFacebookComposer ? global.FritreeFacebookComposer.getDelayConfig() : { mode: 'random', minSeconds: 45, maxSeconds: 120 };
const launchMode = document.getElementById('q2hxmk5c3l')?.value || 'tab';
setDomTextSafely('uns2dhjlx2', selectedGroupIds.length);
setDomTextSafely('yn082h7vxq', 0);
setDomTextSafely('pe147sfejg', 0);
setDomTextSafely('c2hyj1dsyf', 0);
const campaignId = 'manual_fb_' + Date.now();
lastLaunchedCampaignId = campaignId;
const campaignName = 'حملة نشر يدوية فيسبوك';
startCampaignTrackingTimers();
const activeCampaignImages = [];
for (const img of images) {
const rawBlob = await global.FritreeStorage.get(`media_blob_${img.id}`);
if (rawBlob) {
await global.FritreeStorage.set(`media_blob_active_${campaignId}_${img.id}`, rawBlob);
activeCampaignImages.push({ id: img.id, name: img.name, type: img.type });
}
}
if (global.FritreeFacebookComposer) {
await global.FritreeFacebookComposer.savePublishedPostToRecent(baseText, activeCampaignImages, selectedGroupIds);
}
chrome.runtime.sendMessage({
action: "publishToMultipleGroups",
campaignId,
campaignName,
groupIds: selectedGroupIds,
text: baseText,
images: activeCampaignImages,
delayConfig,
isLibraryMode,
payloadMap,
launchMode
});
const btnStart = document.getElementById('q0ilg5gt03');
const btnPause = document.getElementById('ctmo3psebt');
const btnFreeze = document.getElementById('te6ue1mcua');
if (btnStart) btnStart.disabled = false;
if (btnPause) {
btnPause.disabled = false;
btnPause.setAttribute('data-state', 'running');
btnPause.innerHTML = '<i class="fa-solid fa-pause"></i> <span>إيقاف مؤقت للحملة</span>';
}
if (btnFreeze) btnFreeze.disabled = false;
} catch (err) {
silentTrap(err);
resetPublishButtonsOnFailure();
stopCampaignTrackingTimers();
}
};
/**
* إطلاق حملة رسائل واتساب فورية أو جدولتها
*/
const triggerWhatsAppCampaign = async () => {
const recipients = global.FritreeWhatsApp ? global.FritreeWhatsApp.getRecipients() : [];
if (recipients.length === 0) {
alert("قائمة مستلمي الواتساب فارغة. يرجى إضافة أرقام العملاء أولاً!");
return;
}
const isScheduleChecked = document.getElementById('eve1rrjds1')?.checked || false;
const scheduledTime = document.getElementById('xlz92zcfuh')?.value;
if (isScheduleChecked) {
if (!scheduledTime || new Date(scheduledTime).getTime() <= Date.now()) {
alert('اختر تاريخاً ووقتاً مستقبلياً صالحاً لجدولة الرسائل!');
return;
}
let text = global.FritreeWhatsAppComposer ? global.FritreeWhatsAppComposer.getComposerText() : '';
const waComposerImages = global.FritreeWhatsAppComposer ? await global.FritreeWhatsAppComposer.getUploadedImages() : [];
const delayConfig = global.FritreeWhatsAppComposer ? global.FritreeWhatsAppComposer.getDelayConfig() : { mode: "random", minSeconds: 60, maxSeconds: 150 };
const launchMode = document.getElementById('cdeyq8k3xd')?.value || 'tab';
const newSchedItem = {
id: 'sched_wa_' + Date.now() + '_' + Math.random().toString(36).substr(2, 4),
name: `حملة واتساب مجدولة (${recipients.length} مستلم)`,
platform: 'whatsapp',
scheduledTime: scheduledTime,
text: text,
images: waComposerImages,
recipients: recipients,
delayConfig: delayConfig,
launchMode: launchMode,
status: 'scheduled',
createdAt: new Date().toISOString()
};
const currentList = await global.FritreeStorage.get('scheduledCampaignsData', []) || [];
currentList.unshift(newSchedItem);
await global.FritreeStorage.set('scheduledCampaignsData', currentList);
alert(`تمت جدولة رسائل الواتساب بنجاح لتنطلق تلقائياً بتاريخ: ${new Date(scheduledTime).toLocaleString('en-US')}`);
window.location.hash = 'ss7cgkeahf';
return;
}
const waPoints = global.FritreeDashboard ? global.FritreeDashboard.getWaPoints() : 0;
if (waPoints < 1) {
handleInsufficientBalanceAbort('whatsapp');
return;
}
let text = global.FritreeWhatsAppComposer ? global.FritreeWhatsAppComposer.getComposerText() : '';
const waComposerImages = global.FritreeWhatsAppComposer ? await global.FritreeWhatsAppComposer.getUploadedImages() : [];
if (!text && waComposerImages.length === 0) {
alert("لا يمكن إرسال رسالة فارغة! اكتب نص الرسالة أو ارفق صور/فيديو أولاً.");
return;
}
const btnStart = document.getElementById('ciqrxeqovl');
const btnPause = document.getElementById('fne7jmd8cp');
const btnFreeze = document.getElementById('nnsh4j5crx');
try {
const delayConfig = global.FritreeWhatsAppComposer ? global.FritreeWhatsAppComposer.getDelayConfig() : { mode: "random", minSeconds: 60, maxSeconds: 150 };
const launchMode = document.getElementById('cdeyq8k3xd')?.value || 'tab';
setDomTextSafely('n5kl1m8coi', recipients.length);
setDomTextSafely('hig5lc1irj', 0);
if (btnStart) btnStart.disabled = true;
if (btnPause) {
btnPause.disabled = false;
btnPause.setAttribute('data-state', 'running');
btnPause.innerHTML = '<i class="fa-solid fa-pause"></i> <span>إيقاف مؤقت للحملة</span>';
}
if (btnFreeze) btnFreeze.disabled = false;
startCampaignTrackingTimers();
const campaignId = 'manual_wa_' + Date.now();
lastLaunchedCampaignId = campaignId;
const activeCampaignImages = [];
for (const img of waComposerImages) {
const rawBlob = await global.FritreeStorage.get(`media_blob_${img.id}`);
if (rawBlob) {
await global.FritreeStorage.set(`media_blob_active_${campaignId}_${img.id}`, rawBlob);
activeCampaignImages.push({ id: img.id, name: img.name, type: img.type });
}
}
if (global.FritreeTextCompiler) {
text = await global.FritreeTextCompiler.asyncParseVariables(text);
}
chrome.runtime.sendMessage({
action: "start_wa_campaign",
campaignId,
recipients,
text,
media: activeCampaignImages,
delayConfig,
launchMode
});
} catch (err) {
silentTrap(err);
if (btnStart) btnStart.disabled = false;
stopCampaignTrackingTimers();
}
};
/**
* معالجة تقدم حملة فيسبوك
*/
const handleFacebookProgress = (data) => {
try {
const campaignId = data.campaignId || 'legacy';
const campaignName = data.campaignName || 'حملة فيسبوك نشطة';
const current = data.current;
const total = data.total;
const gId = data.groupId;
const status = data.status;
const error = data.error;
const postUrl = data.postUrl;
const metrics = activeCampaignsMetrics.get(campaignId) || { success: 0, pending: 0, failed: 0 };
if (status === 'success') metrics.success++;
else if (status === 'pending') metrics.pending++;
else if (status === 'failed') metrics.failed++;
activeCampaignsMetrics.set(campaignId, metrics);
if (status === 'success') {
addLog(`[${campaignName}] تم نشر المنشور بنجاح داخل مجموعة فيسبوك: [${gId}].`, 'success');
updateFacebookStatsCounter('success');
addProofLinkRow(gId, 'Success', postUrl);
if (global.FritreeProgressionService) global.FritreeProgressionService.progressTask('fb_post', 1);
} else if (status === 'pending') {
addLog(`[${campaignName}] تم النشر داخل مجموعة فيسبوك: [${gId}] ومعلق حالياً بانتظار موافقة الإدارة.`, 'warn');
updateFacebookStatsCounter('pending');
addProofLinkRow(gId, 'Pending Approval', postUrl || '#');
if (global.FritreeProgressionService) global.FritreeProgressionService.progressTask('fb_post', 1);
} else if (status === 'failed') {
addLog(`[${campaignName}] فشل النشر داخل مجموعة فيسبوك: [${gId}].`, 'error');
updateFacebookStatsCounter('failed');
addProofLinkRow(gId, 'Restricted', null, error);
}
if (data.variantName && (status === 'success' || status === 'pending' || status === 'failed')) {
if (global.FritreeRotationStore) global.FritreeRotationStore.incrementUsage(data.variantName, status);
}
const fill = document.getElementById('yuc3c21zr2');
const pctLabel = document.getElementById('gu66d84s18');
const pct = Math.round((current / total) * 100);
if (fill) fill.style.width = `${pct}%`;
if (pctLabel) pctLabel.textContent = `${pct}%`;
} catch (e) {
silentTrap(e);
}
};
const updateFacebookStatsCounter = (type) => {
try {
if (type === 'success') {
const el = document.getElementById('yn082h7vxq');
if (el) el.innerHTML = `<i class="fa-solid fa-thumbs-up" style="font-size:15px; color:#10b981;"></i> ${parseInt(el.textContent || '0', 10) + 1}`;
completedStepsCount++;
} else if (type === 'pending') {
const el = document.getElementById('pe147sfejg');
if (el) el.innerHTML = `<i class="fa-solid fa-hourglass-half" style="font-size:15px; color:#f59e0b;"></i> ${parseInt(el.textContent || '0', 10) + 1}`;
completedStepsCount++;
} else if (type === 'failed') {
const el = document.getElementById('c2hyj1dsyf');
if (el) el.innerHTML = `<i class="fa-solid fa-triangle-exclamation" style="font-size:15px; color:#ef4444;"></i> ${parseInt(el.textContent || '0', 10) + 1}`;
completedStepsCount++;
}
} catch (e) {
silentTrap(e);
}
};
const handleWhatsAppProgress = (data) => {
try {
const current = data.current;
const total = data.total;
const phone = data.phone;
const name = data.name;
const status = data.status;
const error = data.error;
if (status === 'success') {
addLog(`تم إرسال الرسالة بنجاح لـ: ${name} (${phone}).`, 'success');
const el = document.getElementById('hig5lc1irj');
if (el) el.innerHTML = `<i class="fa-solid fa-paper-plane" style="font-size:15px; color:#00a884;"></i> ${parseInt(el.textContent || '0', 10) + 1}`;
addProofLinkRow(phone, 'Success', `https://web.whatsapp.com/send?phone=${phone.replace(/[^0-9]/g, '')}`);
if (global.FritreeProgressionService) global.FritreeProgressionService.progressTask('wa_send', 1);
} else if (status === 'failed') {
addLog(`فشل الإرسال لـ: ${name} (${phone}).`, 'error');
addProofLinkRow(phone, 'Failed', null, error);
}
const pct = Math.round((current / total) * 100);
const fill = document.getElementById('vsc6h9bses');
const pctLabel = document.getElementById('z5eisfkgpg');
if (fill) fill.style.width = `${pct}%`;
if (pctLabel) pctLabel.textContent = `${pct}%`;
} catch (e) {
silentTrap(e);
}
};
const addProofLinkRow = (target, stateText, proofUrl, errorMsg = '') => {
try {
const tbody = document.querySelector('#rne8yohkuk tbody');
if (!tbody) return;
const fallbackRow = document.getElementById('tslozgkksi');
if (fallbackRow) fallbackRow.remove();
const tr = document.createElement('tr');
tr.style.borderBottom = '1px solid var(--border)';
const tdTarget = document.createElement('td');
tdTarget.style.cssText = 'font-weight: 700; padding: 8px 10px; font-family: var(--font-code); font-size: 11.5px;';
tdTarget.textContent = target;
const tdState = document.createElement('td');
tdState.style.cssText = 'text-align: center; padding: 8px 10px;';
const badge = document.createElement('span');
let badgeClass = 'go30y9mfgh ';
let displayState = stateText;
if (stateText === 'Success') {
badgeClass += 'success';
displayState = 'ناجح';
} else if (stateText === 'Pending Approval') {
badgeClass += 'pending';
displayState = 'قيد المراجعة';
} else {
badgeClass += 'failed';
displayState = 'فشل';
}
badge.className = badgeClass;
badge.textContent = displayState;
tdState.appendChild(badge);
const tdLink = document.createElement('td');
tdLink.style.cssText = 'text-align: center; padding: 8px 10px;';
if (proofUrl) {
const link = document.createElement('a');
link.href = proofUrl;
link.target = '_blank';
link.style.cssText = 'font-weight: 700; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; color: var(--primary); font-size: 11px;';
link.innerHTML = '<i class="fa-solid fa-up-right-from-square"></i> <span>فتح الرابط</span>';
tdLink.appendChild(link);
} else {
const errSpan = document.createElement('span');
errSpan.style.cssText = 'font-size: 10.5px; font-weight: 700; color: var(--danger);';
errSpan.textContent = errorMsg || 'غير متاح';
tdLink.appendChild(errSpan);
}
tr.appendChild(tdTarget);
tr.appendChild(tdState);
tr.appendChild(tdLink);
tbody.appendChild(tr);
} catch (e) {
silentTrap(e);
}
};
/**
* ربط نفق استقبال رسائل الخلفية
*/
const bindBackgroundMessageTunnelListener = () => {
try {
if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.onMessage) {
chrome.runtime.onMessage.addListener((message) => {
try {
if (message.action === 'publishProgress') {
handleFacebookProgress(message);
} else if (message.action === 'publishCountdown') {
addLog(`فترة انتظار وتبريد: الخطوة القادمة ستبدأ خلال ${message.seconds} ثانية.`, 'warn');
totalCooldownSeconds++;
} else if (message.action === 'publishComplete') {
addLog(`اكتملت حملة فيسبوك بنجاح!`, "success");
stopCampaignTrackingTimers();
syncWorkspaceUI();
} else if (message.action === 'wa_send_progress') {
handleWhatsAppProgress(message);
} else if (message.action === 'wa_send_countdown') {
addLog(`فترة انتظار وتبريد واتساب: ${message.seconds} ثانية...`, 'warn');
totalCooldownSeconds++;
} else if (message.action === 'wa_send_complete') {
addLog("اكتملت حملة الواتساب بنجاح!", "success");
stopCampaignTrackingTimers();
syncWorkspaceUI();
} else if (message.action === 'scheduled_list_updated') {
renderScheduledQueueTable();
} else if (message.action === 'CAMPAIGN_ABORTED_INSUFFICIENT_BALANCE') {
handleInsufficientBalanceAbort(message.platform);
}
} catch (inner) {
silentTrap(inner);
}
});
}
} catch (e) {
silentTrap(e);
}
};
const handleInsufficientBalanceAbort = async (platform) => {
stopCampaignTrackingTimers();
alert(`تنبيه: رصيد نقاط ${platform === 'facebook' ? 'فيسبوك' : 'واتساب'} غير كافٍ. يرجى الشحن من المتجر.`);
window.location.hash = 'dc1z57si9s';
};
/**
* ربط تفويض النقر العام
*/
const bindDocumentClickDelegation = () => {
document.addEventListener('click', (e) => {
const targetElem = e.target.closest('[data-target]');
if (targetElem) {
const targetId = targetElem.getAttribute('data-target');
if (targetId && !targetElem.closest('#q0ilg5gt03') && !targetElem.closest('#ciqrxeqovl')) {
window.location.hash = targetId;
}
}
if (e.target.closest('#b8imusheoz')) {
window.location.hash = 'sf1xx5vcac';
return;
}
if (e.target.closest('#nog5je6ddx')) {
window.location.hash = 'sf8pufcpyl';
return;
}
if (e.target.closest('#frtal49mqm')) {
window.location.hash = 'j2nzw12azj';
return;
}
// مزامنة فورية لمجموعات فيسبوك بنقرة واحدة
if (e.target.closest('#d769nsyxio')) {
triggerFacebookGroupsSync(true);
return;
}
if (e.target.closest('#hzo3r22pug')) {
if (chrome.tabs && chrome.tabs.create) {
chrome.tabs.create({ url: 'https://web.whatsapp.com' }, () => {
setTimeout(checkConnectedSessions, 3000);
});
} else {
window.open('https://web.whatsapp.com', '_blank');
setTimeout(checkConnectedSessions, 3000);
}
return;
}
if (e.target.closest('#n3jlayvv4s')) {
window.location.hash = 'qt3bcp0qq8';
return;
}
if (e.target.closest('#h4we1yzu71')) {
if (global.FritreePacingUI && typeof global.FritreePacingUI.openModal === 'function') {
global.FritreePacingUI.openModal('fb');
}
return;
}
if (e.target.closest('#wjdexzlzuv')) {
const terminal = document.getElementById('r99bttinj8');
if (terminal) terminal.innerHTML = '';
addLog("تم مسح سجل الأوامر بنجاح.", "warn");
return;
}
if (e.target.closest('#s24x8dpijy')) {
isTermSuspended = !isTermSuspended;
const btn = document.getElementById('s24x8dpijy');
if (btn) {
btn.innerHTML = isTermSuspended ? '<i class="fa-solid fa-play"></i>' : '<i class="fa-solid fa-pause"></i>';
btn.title = isTermSuspended ? 'استئناف شاشة السجل' : 'إيقاف مؤقت لشاشة السجل';
}
addLog(isTermSuspended ? "تم إيقاف تحديث سجل الأوامر مؤقتاً." : "تم استئناف تحديث سجل الأوامر.", "info");
return;
}
if (e.target.closest('#q0ilg5gt03')) {
triggerFacebookCampaign();
return;
}
if (e.target.closest('#ciqrxeqovl')) {
triggerWhatsAppCampaign();
return;
}
const pauseFbBtn = e.target.closest('#ctmo3psebt');
if (pauseFbBtn && lastLaunchedCampaignId) {
const currentState = pauseFbBtn.getAttribute('data-state') || 'running';
if (currentState === 'running') {
chrome.runtime.sendMessage({ action: 'pause_campaign', campaignId: lastLaunchedCampaignId });
pauseFbBtn.setAttribute('data-state', 'paused');
pauseFbBtn.innerHTML = '<i class="fa-solid fa-play"></i> <span>استئناف الحملة</span>';
} else {
chrome.runtime.sendMessage({ action: 'resume_campaign', campaignId: lastLaunchedCampaignId });
pauseFbBtn.setAttribute('data-state', 'running');
pauseFbBtn.innerHTML = '<i class="fa-solid fa-pause"></i> <span>إيقاف مؤقت للحملة</span>';
}
return;
}
const pauseWaBtn = e.target.closest('#fne7jmd8cp');
if (pauseWaBtn && lastLaunchedCampaignId) {
const currentState = pauseWaBtn.getAttribute('data-state') || 'running';
if (currentState === 'running') {
chrome.runtime.sendMessage({ action: 'pause_campaign', campaignId: lastLaunchedCampaignId });
pauseWaBtn.setAttribute('data-state', 'paused');
pauseWaBtn.innerHTML = '<i class="fa-solid fa-play"></i> <span>استئناف الحملة</span>';
} else {
chrome.runtime.sendMessage({ action: 'resume_campaign', campaignId: lastLaunchedCampaignId });
pauseWaBtn.setAttribute('data-state', 'running');
pauseWaBtn.innerHTML = '<i class="fa-solid fa-pause"></i> <span>إيقاف مؤقت للحملة</span>';
}
return;
}
if (e.target.closest('#te6ue1mcua') || e.target.closest('#nnsh4j5crx')) {
if (confirm("هل أنت متأكد من إيقاف وتجميد الحملة النشطة نهائياً؟")) {
chrome.runtime.sendMessage({ action: 'stop_campaign', campaignId: lastLaunchedCampaignId });
stopCampaignTrackingTimers();
}
return;
}
});
};
/**
* تهيئة المنسق العام
*/
const initOrchestrator = async () => {
try {
const mainContentArea = document.getElementById('s7ihkirolg');
if (!mainContentArea) return false;
buildSchedulerPaneLayout();
if (global.FritreeStealthUI && typeof global.FritreeStealthUI.buildPane === 'function') {
global.FritreeStealthUI.buildPane();
}
if (global.FritreeBackupService && typeof global.FritreeBackupService.buildPane === 'function') {
global.FritreeBackupService.buildPane();
}
establishPersistentKeepAlive();
bindDocumentClickDelegation();
window.addEventListener('hashchange', executeHashRouter);
await syncWorkspaceUI();
executeHashRouter();
await checkConnectedSessions();
startWorkspaceSecurityHeartbeat();
bindBackgroundMessageTunnelListener();
global.addLog = addLog;
global.syncWorkspaceUI = syncWorkspaceUI;
// إطلاق المزامنة الفورية لمجموعات فيسبوك تلقائياً عند فتح المنصة
setTimeout(() => {
triggerFacebookGroupsSync(false);
}, 800);
addLog("تم تشغيل لوحة التحكم الموحدة ودروع التخفي والمزامنة الذاتية بنجاح!", "info");
return true;
} catch (e) {
silentTrap(e);
return false;
}
};
/**
* تصدير وحدة المنسق العام
*/
global.FritreeOrchestrator = {
init: initOrchestrator,
addLog,
syncUI: syncWorkspaceUI,
checkSessions: checkConnectedSessions,
syncFacebookGroups: triggerFacebookGroupsSync,
triggerFB: triggerFacebookCampaign,
triggerWA: triggerWhatsAppCampaign,
buildSchedulerPane: buildSchedulerPaneLayout,
renderScheduledQueue: renderScheduledQueueTable
};
if (typeof document !== 'undefined') {
if (document.readyState === 'complete' || document.readyState === 'interactive') {
initOrchestrator();
} else {
document.addEventListener('DOMContentLoaded', initOrchestrator);
}
}
})(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this);