| |
| |
| |
| |
|
|
|
|
| 'use strict';
|
|
|
| (global => {
|
| const FB_CONFIG = {
|
| doc_id_groups_shortcuts: '3884641628300421',
|
| doc_id_joined_groups_full: '5007421822699884',
|
| doc_id_post_text: '3559434960802556',
|
| doc_id_post_photo: '4669579913112843',
|
| jazoest: '25450',
|
| upload_id: 'jsc_c_9',
|
| captured: {
|
| userId: null,
|
| fb_dtsg: null,
|
| lsd: null,
|
| dyn: null
|
| }
|
| };
|
|
|
| |
| |
|
|
| function getFacebookUserId() {
|
| return new Promise(resolve => {
|
| if (typeof chrome === 'undefined' || !chrome.cookies) {
|
| const storedId = global.FritreeStorage ? global.FritreeStorage.get('userId', null) : null;
|
| resolve(storedId);
|
| return;
|
| }
|
|
|
| const domains = ['.facebook.com', 'facebook.com', 'web.facebook.com', 'm.facebook.com'];
|
| let resolved = false;
|
|
|
| const checkNextDomain = (index) => {
|
| if (index >= domains.length) {
|
| if (!resolved) {
|
| chrome.cookies.getAll({ name: 'c_user' }, allCookies => {
|
| const found = (allCookies || []).find(c => c.domain && c.domain.includes('facebook'));
|
| resolve(found ? found.value : null);
|
| });
|
| }
|
| return;
|
| }
|
|
|
| chrome.cookies.getAll({ domain: domains[index], name: 'c_user' }, cookies => {
|
| if (cookies && cookies.length > 0 && cookies[0].value) {
|
| resolved = true;
|
| resolve(cookies[0].value);
|
| } else {
|
| checkNextDomain(index + 1);
|
| }
|
| });
|
| };
|
|
|
| checkNextDomain(0);
|
| });
|
| }
|
|
|
| function getFacebookPageId() {
|
| return new Promise(resolve => {
|
| if (typeof chrome === 'undefined' || !chrome.cookies) {
|
| resolve(null);
|
| return;
|
| }
|
|
|
| chrome.cookies.getAll({ domain: '.facebook.com', name: 'i_user' }, cookies => {
|
| if (cookies && cookies.length > 0 && cookies[0].value) {
|
| resolve(cookies[0].value);
|
| } else {
|
| chrome.cookies.get({ url: 'https://www.facebook.com', name: 'i_user' }, cookie => {
|
| resolve(cookie && cookie.value ? cookie.value : null);
|
| });
|
| }
|
| });
|
| });
|
| }
|
|
|
| async function resolveActiveUserId() {
|
| const pageId = await getFacebookPageId();
|
| if (pageId) return pageId;
|
| return await getFacebookUserId();
|
| }
|
|
|
| async function extractFbDtsg(tabId) {
|
| return new Promise(resolve => {
|
| if (typeof chrome === 'undefined' || !chrome.scripting) {
|
| resolve({ fb_dtsg: null, lsd: null });
|
| return;
|
| }
|
|
|
| chrome.scripting.executeScript({
|
| target: { tabId: tabId },
|
| func: () => {
|
| let dtsg = null, lsd = null;
|
|
|
| try {
|
| if (window.DTSGInitialData && window.DTSGInitialData.token) dtsg = window.DTSGInitialData.token;
|
| if (window.DTSGInitData && window.DTSGInitData.token) dtsg = window.DTSGInitData.token;
|
| if (window.LSD && window.LSD.token) lsd = window.LSD.token;
|
| } catch (e) {}
|
|
|
| if (!dtsg) {
|
| const inputDtsg = document.querySelector('input[name="fb_dtsg"]') || document.querySelector('[data-dtsg]');
|
| if (inputDtsg) dtsg = inputDtsg.value || inputDtsg.getAttribute('data-dtsg');
|
| }
|
| if (!lsd) {
|
| const inputLsd = document.querySelector('input[name="lsd"]');
|
| if (inputLsd && inputLsd.value) lsd = inputLsd.value;
|
| }
|
|
|
| const html = document.documentElement.innerHTML;
|
| if (!dtsg) {
|
| const m = html.match(/["']DTSGInitialData["']\s*,\s*\[\s*\]\s*,\s*\{\s*["']token["']\s*:\s*["']([^"']+)["']/) ||
|
| html.match(/["']token["']\s*:\s*["'](AQ[^"']+)["']/) ||
|
| html.match(/["']token["']\s*:\s*["'](NA[^"']+)["']/) ||
|
| html.match(/async_get_token:"([^"]+)"/) ||
|
| html.match(/"dtsg"\s*:\s*\{\s*"token"\s*:\s*"([^"]+)"/);
|
| if (m) dtsg = m[1];
|
| }
|
|
|
| if (!lsd) {
|
| const lm = html.match(/["']LSD["']\s*,\s*\[\s*\]\s*,\s*\{\s*["']token["']\s*:\s*["']([^"']+)["']/) ||
|
| html.match(/"lsd"\s*:\s*"([^"]+)"/);
|
| if (lm) lsd = lm[1];
|
| }
|
|
|
| return { fb_dtsg: dtsg, lsd: lsd };
|
| }
|
| }, results => {
|
| if (chrome.runtime.lastError || !results || !results[0]) {
|
| resolve({ fb_dtsg: null, lsd: null });
|
| } else {
|
| resolve(results[0].result || { fb_dtsg: null, lsd: null });
|
| }
|
| });
|
| });
|
| }
|
|
|
| async function extractD_Dyn(tabId) {
|
| return new Promise(resolve => {
|
| if (typeof chrome === 'undefined' || !chrome.scripting) {
|
| resolve(null);
|
| return;
|
| }
|
|
|
| chrome.scripting.executeScript({
|
| target: { tabId: tabId },
|
| func: () => {
|
| const dyn = document.querySelector('input[name="__dyn"]')?.value;
|
| if (dyn && dyn.length > 20) return dyn;
|
| const html = document.documentElement.innerHTML;
|
| const m = html.match(/__dyn\s*:\s*"([^"]+)"/);
|
| return m ? m[1] : null;
|
| }
|
| }, results => {
|
| if (chrome.runtime.lastError || !results || !results[0]) {
|
| resolve(null);
|
| } else {
|
| resolve(results[0].result);
|
| }
|
| });
|
| });
|
| }
|
|
|
| async function refreshFacebookSession(tabId) {
|
| try {
|
| await chrome.scripting.executeScript({
|
| target: { tabId: tabId },
|
| func: () => fetch('https://www.facebook.com/groups/joins/', { credentials: 'include', headers: { Accept: 'text/html' } })
|
| });
|
| await new Promise(r => setTimeout(r, 600));
|
| } catch (e) {
|
| console.warn('[Fritree Facebook Bg] Session ping note:', e.message);
|
| }
|
| }
|
|
|
| async function ensureFacebookAndCaptureKeys() {
|
| const activeId = await resolveActiveUserId();
|
| if (!activeId) {
|
| return {
|
| success: false,
|
| error: 'not_logged_in',
|
| message: 'لم يتم العثور على جلسة فيسبوك نشطة. سجل دخول لحسابك على فيسبوك في المتصفح أولاً.'
|
| };
|
| }
|
|
|
| FB_CONFIG.captured.userId = activeId;
|
| const tabs = await chrome.tabs.query({ url: ['*://*.facebook.com/*', '*://web.facebook.com/*'] });
|
| let targetTabId = null;
|
|
|
|
|
| if (tabs.length === 0) {
|
| const newTab = await chrome.tabs.create({ url: 'https://www.facebook.com/groups/joins/', active: false });
|
| targetTabId = newTab.id;
|
| await new Promise(r => setTimeout(r, 3500));
|
| } else {
|
| targetTabId = tabs[0].id;
|
| const currentTabUrl = tabs[0].url || '';
|
| if (!currentTabUrl.includes('/groups/joins')) {
|
| await chrome.tabs.update(targetTabId, { url: 'https://www.facebook.com/groups/joins/' });
|
| await new Promise(r => setTimeout(r, 2500));
|
| }
|
| }
|
|
|
| await refreshFacebookSession(targetTabId);
|
| let keys = await extractFbDtsg(targetTabId);
|
|
|
| if (!keys || !keys.fb_dtsg) {
|
| await chrome.tabs.reload(targetTabId);
|
| await new Promise(r => setTimeout(r, 3000));
|
| keys = await extractFbDtsg(targetTabId);
|
| }
|
|
|
| if (keys && keys.fb_dtsg) {
|
| FB_CONFIG.captured.fb_dtsg = keys.fb_dtsg;
|
| FB_CONFIG.captured.lsd = keys.lsd;
|
| FB_CONFIG.captured.dyn = await extractD_Dyn(targetTabId);
|
|
|
| if (global.FritreeStorage) {
|
| await global.FritreeStorage.set('fb_dtsg', keys.fb_dtsg);
|
| await global.FritreeStorage.set('lsd', keys.lsd);
|
| await global.FritreeStorage.set('dyn', FB_CONFIG.captured.dyn);
|
| await global.FritreeStorage.set('userId', activeId);
|
| }
|
| }
|
|
|
| return { success: true, userId: activeId, tabId: targetTabId };
|
| }
|
|
|
| |
| |
|
|
| async function fetchAllFacebookGroups(tabId) {
|
| return new Promise(resolve => {
|
| if (typeof chrome === 'undefined' || !chrome.scripting) {
|
| resolve({ success: false, groups: [] });
|
| return;
|
| }
|
|
|
| chrome.scripting.executeScript({
|
| target: { tabId: tabId },
|
| func: (config) => {
|
| return new Promise(async (innerResolve) => {
|
| const groupsMap = new Map();
|
|
|
| function parseFacebookGroupMembersText(text) {
|
| if (!text || typeof text !== 'string') return 0;
|
| let cleaned = text.replace(/[٠-٩]/g, d => '٠١٢٣٤٥٦٧٨٩'.indexOf(d));
|
| cleaned = cleaned.replace(/٫/g, '.');
|
| let millionMatch = cleaned.match(/([\d.]+)\s*(مليون|m|مليار)/i);
|
| if (millionMatch) return Math.round(parseFloat(millionMatch[1]) * 1000000);
|
| let thousandMatch = cleaned.match(/([\d.]+)\s*(ألف|الف|آلاف|الاف|k)/i);
|
| if (thousandMatch) return Math.round(parseFloat(thousandMatch[1]) * 1000);
|
| let plainMatch = cleaned.match(/([\d,.]+)\s*(عضو|اعضاء|أعضاء|من الأعضاء|members|member)/i);
|
| if (plainMatch) {
|
| const val = parseFloat(plainMatch[1].replace(/,/g, ''));
|
| return isNaN(val) ? 0 : Math.round(val);
|
| }
|
| return 0;
|
| }
|
|
|
| const getImg = node => node?.image?.uri || node?.profile_picture?.uri || node?.group_icon?.uri || node?.custom_icon?.uri || '';
|
|
|
| const addGroupToMap = (id, name, img, isAdmin, memberCount) => {
|
| if (!id) return;
|
| const cleanId = String(id).replace(/[^0-9a-zA-Z._-]/g, '');
|
| const blacklistedTerms = ['feed', 'discover', 'joins', 'create', 'search', 'notifications', 'categories', 'chats', 'saved', 'events', 'members', 'about'];
|
| if (blacklistedTerms.includes(cleanId) || cleanId.length < 2) return;
|
|
|
| const cleanName = (name || '').split('\n')[0].trim();
|
| if (!cleanName || cleanName.startsWith('مجموعة (') || cleanName === cleanId) return;
|
|
|
| if (!groupsMap.has(cleanId)) {
|
| groupsMap.set(cleanId, {
|
| id: cleanId,
|
| name: cleanName,
|
| image: img || '',
|
| url: `https://www.facebook.com/groups/${cleanId}`,
|
| isAdmin: Boolean(isAdmin),
|
| memberCount: parseInt(memberCount, 10) || 0
|
| });
|
| } else {
|
| const existing = groupsMap.get(cleanId);
|
| if (isAdmin) existing.isAdmin = true;
|
| if (!existing.image && img) existing.image = img;
|
| if ((!existing.name || existing.name.includes('(')) && cleanName) existing.name = cleanName;
|
| if (!existing.memberCount && memberCount) existing.memberCount = parseInt(memberCount, 10);
|
| }
|
| };
|
|
|
| const processEdges = (edges, isAdmin) => {
|
| if (!edges || !Array.isArray(edges)) return;
|
| edges.forEach(e => {
|
| const n = e.node || e;
|
| if (n && (n.id || n.group_id)) {
|
| const gId = n.id || n.group_id;
|
| const gName = n.name || n.title;
|
| const mCount = n.group_members?.count || n.members?.count || n.member_count || 0;
|
| if (gName) {
|
| addGroupToMap(gId, gName, getImg(n), isAdmin, mCount);
|
| }
|
| }
|
| });
|
| };
|
|
|
|
|
| try {
|
| const scripts = document.querySelectorAll('script[type="application/json"]');
|
| scripts.forEach(s => {
|
| const content = s.textContent || '';
|
| if (content.includes('"Group"') || content.includes('"tab_groups_list"') || content.includes('"all_joined_groups"')) {
|
| try {
|
| const parsed = JSON.parse(content);
|
| const scanObject = (obj) => {
|
| if (!obj || typeof obj !== 'object') return;
|
| if ((obj.__typename === 'Group' || obj.__typename === 'CometGroup') && obj.id && (obj.name || obj.title)) {
|
| const mCount = obj.group_members?.count || obj.members?.count || obj.member_count || 0;
|
| addGroupToMap(obj.id, obj.name || obj.title, getImg(obj), false, mCount);
|
| }
|
| if (obj.tab_groups_list?.edges) processEdges(obj.tab_groups_list.edges, false);
|
| if (obj.all_joined_groups?.edges) processEdges(obj.all_joined_groups.edges, false);
|
| if (obj.viewer?.groups?.edges) processEdges(obj.viewer.groups.edges, false);
|
| if (obj.admin_groups?.edges) processEdges(obj.admin_groups.edges, true);
|
| Object.values(obj).forEach(val => { if (typeof val === 'object') scanObject(val); });
|
| };
|
| scanObject(parsed);
|
| } catch (e) {}
|
| }
|
| });
|
| } catch (rErr) {}
|
|
|
|
|
| try {
|
| const harvestDOM = () => {
|
| const anchors = document.querySelectorAll('a[href*="/groups/"]');
|
| anchors.forEach(a => {
|
| const href = a.getAttribute('href') || '';
|
| const match = href.match(/\/groups\/([0-9a-zA-Z._-]+)/);
|
| if (match && match[1]) {
|
| const gId = match[1].replace(/[^0-9a-zA-Z._-]/g, '');
|
| let groupName = a.innerText?.trim() || a.getAttribute('aria-label') || '';
|
| if (groupName && groupName.length > 1 && !groupName.includes('http') && !groupName.includes('إنشاء')) {
|
| const imgEl = a.querySelector('img') || a.closest('div')?.querySelector('img');
|
| const cardText = a.closest('[role="listitem"], [role="article"], div')?.innerText || '';
|
| const mCount = parseFacebookGroupMembersText(cardText);
|
| addGroupToMap(gId, groupName, imgEl ? imgEl.src : '', false, mCount);
|
| }
|
| }
|
| });
|
| };
|
|
|
| harvestDOM();
|
|
|
|
|
| let lastHeight = 0;
|
| let noChangeCounter = 0;
|
|
|
| for (let i = 0; i < 40; i++) {
|
| window.scrollTo(0, document.body.scrollHeight);
|
| await new Promise(r => setTimeout(r, 180));
|
| harvestDOM();
|
|
|
| const currentHeight = document.body.scrollHeight;
|
| if (currentHeight === lastHeight) {
|
| noChangeCounter++;
|
| if (noChangeCounter >= 4) break;
|
| } else {
|
| noChangeCounter = 0;
|
| lastHeight = currentHeight;
|
| }
|
| }
|
| } catch (domErr) {}
|
|
|
|
|
| if (config.captured.fb_dtsg) {
|
| const executeGraphQLQueryLoop = async (docId, queryVariables) => {
|
| let hasNextPage = true;
|
| let currentCursor = null;
|
| let pageCounter = 0;
|
| const maxPages = 150;
|
|
|
| while (hasNextPage && pageCounter < maxPages) {
|
| pageCounter++;
|
| try {
|
| const vars = { ...queryVariables, cursor: currentCursor };
|
| const params = new URLSearchParams();
|
| params.append('av', config.captured.userId);
|
| params.append('__user', config.captured.userId);
|
| params.append('__a', '1');
|
| params.append('fb_dtsg', config.captured.fb_dtsg);
|
| params.append('variables', JSON.stringify(vars));
|
| params.append('doc_id', docId);
|
|
|
| const r = await fetch('https://www.facebook.com/api/graphql/', {
|
| method: 'POST',
|
| credentials: 'include',
|
| body: params,
|
| headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
| });
|
|
|
| if (r.ok) {
|
| const resp = await r.text();
|
| const parsed = JSON.parse(resp);
|
|
|
| const adminEdges = parsed.data?.adminGroups?.groups_tab?.tab_groups_list?.edges || parsed.data?.viewer?.admin_groups?.edges;
|
| const viewerEdges = parsed.data?.viewer?.groups?.edges || parsed.data?.viewer?.all_joined_groups?.edges || parsed.data?.viewer?.joined_groups?.edges;
|
| const nonAdminEdges = parsed.data?.nonAdminGroups?.groups_tab?.tab_groups_list?.edges || parsed.data?.viewer?.member_groups?.edges;
|
|
|
| processEdges(adminEdges, true);
|
| processEdges(viewerEdges, false);
|
| processEdges(nonAdminEdges, false);
|
|
|
| const pageInfo = parsed.data?.viewer?.all_joined_groups?.page_info ||
|
| parsed.data?.viewer?.groups?.page_info ||
|
| parsed.data?.adminGroups?.groups_tab?.tab_groups_list?.page_info;
|
|
|
| if (pageInfo && pageInfo.has_next_page && pageInfo.end_cursor && pageInfo.end_cursor !== currentCursor) {
|
| currentCursor = pageInfo.end_cursor;
|
| } else {
|
| hasNextPage = false;
|
| }
|
| } else {
|
| hasNextPage = false;
|
| }
|
| } catch (err) {
|
| hasNextPage = false;
|
| }
|
| }
|
| };
|
|
|
| await executeGraphQLQueryLoop(config.doc_id_groups_shortcuts, {
|
| adminGroupsCount: 500, memberGroupsCount: 500, scale: 1.5, count: 500
|
| });
|
| }
|
|
|
| const resultList = Array.from(groupsMap.values());
|
| resultList.sort((a, b) => (a.isAdmin === b.isAdmin ? 0 : (a.isAdmin ? -1 : 1)));
|
| console.log(`[Fritree Deep Harvester] Total 100% Real Groups Harvested: ${resultList.length}`);
|
| innerResolve({ success: resultList.length > 0, groups: resultList });
|
| });
|
| },
|
| args: [FB_CONFIG]
|
| }, results => {
|
| if (chrome.runtime.lastError || !results || !results[0]) {
|
| resolve({ success: false, groups: [] });
|
| } else {
|
| const res = results[0].result;
|
| resolve(res || { success: false, groups: [] });
|
| }
|
| });
|
| });
|
| }
|
|
|
| async function uploadFacebookImage(dataUrl, fileName) {
|
| return new Promise(resolve => {
|
| try {
|
| const parts = dataUrl.split(',');
|
| if (parts.length < 2) {
|
| resolve({ success: false, error: 'صيغة الصورة غير صالحة للرفع.' });
|
| return;
|
| }
|
|
|
| const binary = atob(parts[1]);
|
| const mimeType = parts[0].split(':')[1].split(';')[0];
|
| const arrayBuffer = new ArrayBuffer(binary.length);
|
| const uint8Array = new Uint8Array(arrayBuffer);
|
| for (let i = 0; i < binary.length; i++) {
|
| uint8Array[i] = binary.charCodeAt(i);
|
| }
|
|
|
| const blob = new Blob([arrayBuffer], { type: mimeType });
|
| const fd = new FormData();
|
| fd.append('fb_dtsg', FB_CONFIG.captured.fb_dtsg);
|
| fd.append('profile_id', FB_CONFIG.captured.userId);
|
| fd.append('source', '8');
|
| fd.append('waterfallxapp', 'comet');
|
| fd.append('farr', blob, fileName || 'upload.jpg');
|
|
|
| const dynamicUploadId = Math.floor(Math.random() * 1000000000000000).toString();
|
| fd.append('upload_id', dynamicUploadId);
|
| fd.append('jazoest', (25000 + Math.floor(Math.random() * 100)).toString());
|
|
|
| const uploadUrl = `https://upload.facebook.com/ajax/react_composer/attachments/photo/upload?av=${FB_CONFIG.captured.userId}&__user=${FB_CONFIG.captured.userId}&__a=1&fb_dtsg=${FB_CONFIG.captured.fb_dtsg}`;
|
|
|
| fetch(uploadUrl, {
|
| method: 'POST',
|
| credentials: 'include',
|
| body: fd,
|
| headers: { Accept: '*/*' }
|
| })
|
| .then(async r => {
|
| const responseText = await r.text();
|
| let photoId = null;
|
| try {
|
| const cleanText = responseText.replace("for (;;);", "").trim();
|
| const parsedData = JSON.parse(cleanText);
|
| if (parsedData?.payload?.photoID) photoId = parsedData.payload.photoID;
|
| } catch (jsonErr) {
|
| const m1 = responseText.match(/"photoID"\s*:\s*"?(\d+)"?/) || responseText.match(/"fbid"\s*:\s*"?(\d+)"?/);
|
| if (m1) photoId = m1[1];
|
| }
|
|
|
| if (photoId) {
|
| resolve({ success: true, photoId: photoId });
|
| } else {
|
| resolve({ success: false, error: 'لم تتمكن خوادم فيسبوك من إكمال رفع الصورة.' });
|
| }
|
| })
|
| .catch(err => resolve({ success: false, error: 'خطأ شبكة أثناء رفع الصورة: ' + err.message }));
|
| } catch (err) {
|
| resolve({ success: false, error: 'خطأ في معالجة الصورة: ' + err.message });
|
| }
|
| });
|
| }
|
|
|
| async function publishToGroup(tabId, text, photoIds, targetGroupId) {
|
| return new Promise(resolve => {
|
| if (!targetGroupId) {
|
| resolve({ success: false, error: 'كود المجموعة المستهدفة غير محدد.' });
|
| return;
|
| }
|
|
|
| const hasPhotos = photoIds && photoIds.length > 0;
|
| const docId = hasPhotos ? FB_CONFIG.doc_id_post_photo : FB_CONFIG.doc_id_post_text;
|
| let hasResolved = false;
|
|
|
| const timeout = setTimeout(() => {
|
| if (!hasResolved) {
|
| hasResolved = true;
|
| resolve({ success: false, error: 'مهلة الاتصال انتهت: خوادم فيسبوك لم تستجب.', post_url: null });
|
| }
|
| }, 30000);
|
|
|
| chrome.scripting.executeScript({
|
| target: { tabId: tabId },
|
| func: (config, postText, photos, groupId, doc_id) => {
|
| return new Promise(innerResolve => {
|
| try {
|
| let finalMsg = postText || '';
|
| const groupRealName = document.title ? document.title.replace(/\s*[-|\|].*$/, '').trim() : 'المجموعة';
|
| finalMsg = finalMsg.replace(/\{\{\s*GROUP_NAME\s*\}\}/gi, groupRealName);
|
| const randomSuffix = '\n\u200B\n\u200B\n\u200B\n\u200B\n\u200B\n' + config.jazoest;
|
|
|
| const variables = {
|
| input: {
|
| client_mutation_id: "1",
|
| actor_id: config.captured.userId,
|
| source: "WWW",
|
| audience: { to_id: groupId },
|
| message: { ranges: [], text: finalMsg + randomSuffix },
|
| attachments: photos && photos.length > 0 ? photos.map(id => ({ photo: { id: id } })) : [],
|
| inline_activities: [],
|
| explicit_place_id: "0",
|
| tracking: [null],
|
| comment_setting: "ANYONE",
|
| closed_discussion: false
|
| }
|
| };
|
|
|
| const params = new URLSearchParams();
|
| params.append('av', config.captured.userId);
|
| params.append('__user', config.captured.userId);
|
| params.append('__a', '1');
|
| params.append('fb_dtsg', config.captured.fb_dtsg);
|
| params.append('variables', JSON.stringify(variables));
|
| params.append('doc_id', doc_id);
|
| params.append('jazoest', config.jazoest);
|
|
|
| fetch('https://www.facebook.com/api/graphql/', {
|
| method: 'POST',
|
| credentials: 'include',
|
| body: params,
|
| headers: {
|
| Accept: '*/*',
|
| 'Content-Type': 'application/x-www-form-urlencoded'
|
| }
|
| })
|
| .then(r => r.text())
|
| .then(resp => {
|
| let storyId = null, permalink = null, postUrl = null;
|
| const m1 = resp.match(/["']legacy_story_hideable_id["']\s*:\s*["'](\d+)["']/);
|
| if (m1) { storyId = m1[1]; postUrl = `https://www.facebook.com/groups/${groupId}/posts/${storyId}/`; }
|
| if (!storyId) {
|
| const m2 = resp.match(/["']story_id["']\s*:\s*["']([^"']+)["']/);
|
| if (m2) { permalink = m2[1]; postUrl = `https://www.facebook.com/groups/${groupId}/permalink/${permalink}/`; }
|
| }
|
|
|
| const isStoryCreated = resp.includes("story") || resp.includes("story_id");
|
| const isPending = resp.includes('pending_post_footer_title') || resp.includes('pending_post_header') || resp.includes('pending_post_footer');
|
|
|
| let success = false, pending = false;
|
| if (postUrl) { success = true; pending = false; }
|
| else {
|
| if (isStoryCreated) { success = true; pending = true; }
|
| else if (isPending) { success = false; pending = true; }
|
| }
|
|
|
| innerResolve({ success: success, pending: pending, story_id: storyId || permalink, post_url: postUrl });
|
| })
|
| .catch(err => innerResolve({ success: false, pending: false, error: 'خطأ شبكة: ' + err.message, post_url: null }));
|
| } catch (e) {
|
| innerResolve({ success: false, pending: false, error: 'خطأ برمجي: ' + e.message, post_url: null });
|
| }
|
| });
|
| },
|
| args: [FB_CONFIG, text, photoIds, targetGroupId, docId]
|
| }, results => {
|
| clearTimeout(timeout);
|
| if (hasResolved) return;
|
| hasResolved = true;
|
|
|
| if (chrome.runtime.lastError) {
|
| resolve({ success: false, error: 'خطأ: ' + chrome.runtime.lastError.message, post_url: null });
|
| } else if (results && results[0] && results[0].result) {
|
| resolve(results[0].result);
|
| } else {
|
| resolve({ success: false, error: 'لم يتم استلام استجابة صالحة من فيسبوك.', post_url: null });
|
| }
|
| });
|
| });
|
| }
|
|
|
| global.FritreeFacebookBg = {
|
| getUserId: getFacebookUserId,
|
| getPageId: getFacebookPageId,
|
| resolveActiveUserId,
|
| ensureSession: ensureFacebookAndCaptureKeys,
|
| uploadImage: uploadFacebookImage,
|
| publishToGroup,
|
| fetchGroups: fetchAllFacebookGroups,
|
| refreshSession: refreshFacebookSession,
|
| config: FB_CONFIG
|
| };
|
|
|
| })(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this); |