Facebook Image Downloader

Facebook image, post, story, whole profile post, image downloader

// ==UserScript==
// @name         Facebook Image Downloader
// @namespace    http://tampermonkey.net/
// @version      1.01
// @description  Facebook image, post, story, whole profile post, image downloader
// @author       Bibek Chand Sah
// @match        https://www.facebook.com/*
// @match        https://facebook.com/*
// @match        https://m.facebook.com/*
// @grant        GM_download
// @grant        GM_addStyle
// @icon         https://cdn-icons-png.flaticon.com/512/5968/5968764.png
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Add styles for the download button, terminal UI, and notifications
    GM_addStyle(`
        #facebook-downloader-container {
            position: fixed;
            top: 60px;
            right: 10px;
            z-index: 9999;
            display: inline-block;
        }

        #facebook-downloader-btn {
            position: relative;
            background: #1877f2;
            color: white;
            border: none;
            padding: 10px 15px;
            border-radius: 5px;
            cursor: pointer;
            font-weight: bold;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            display: flex;
            align-items: center;
            gap: 8px;
            transition: all 0.3s ease;
            user-select: none;
        }

        #drag-handle {
            position: absolute;
            top: -15px;
            left: -15px;
            background: rgba(255,255,255,0.9);
            border: 2px solid #1877f2;
            border-radius: 50%;
            width: 25px;
            height: 25px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 14px;
            cursor: grab;
            transition: all 0.2s ease;
            animation: subtle-pulse 3s ease-in-out infinite;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            z-index: 1;
        }

        #facebook-downloader-btn:hover {
            background: #166fe5;
            transform: translateY(-1px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.4);
        }

        #facebook-downloader-btn:hover ~ #terminal-toggle-btn {
            opacity: 1;
            visibility: visible;
            transform: translateX(0);
        }

        #drag-handle {
            background: rgba(255,255,255,0.9);
            border: 2px solid #1877f2;
            border-radius: 50%;
            width: 30px;
            height: 30px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 16px;
            cursor: grab;
            transition: all 0.2s ease;
            animation: subtle-pulse 3s ease-in-out infinite;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
        }

        @keyframes subtle-pulse {
            0%, 100% { opacity: 0.8; }
            50% { opacity: 1; transform: scale(1.05); }
        }

        #drag-handle:hover {
            background: rgba(255,255,255,1);
            transform: scale(1.2);
            animation: none;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        }

        #drag-handle:active {
            cursor: grabbing;
            transform: scale(0.95);
        }

        #facebook-downloader-btn.dragging {
            opacity: 0.8;
            transform: rotate(2deg);
            z-index: 10000;
            box-shadow: 0 8px 16px rgba(0,0,0,0.3);
        }

        #facebook-downloader-btn:hover .drag-handle {
            animation: none;
            transform: scale(1.2);
        }

        #terminal-toggle-btn {
            position: absolute;
            top: 50%;
            left: -35px;
            transform: translateY(-50%);
            background: #333;
            color: white;
            border: none;
            padding: 5px 8px;
            border-radius: 3px;
            cursor: pointer;
            font-weight: bold;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            font-size: 12px;
            opacity: 0;
            transition: all 0.3s ease;
            z-index: 1;
        }

        #contributor-btn {
            position: absolute;
            top: 50%;
            left: -70px;
            transform: translateY(-50%);
            background: #24292e;
            color: white;
            border: none;
            padding: 5px 8px;
            border-radius: 3px;
            cursor: pointer;
            font-weight: bold;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            font-size: 12px;
            opacity: 0;
            transition: all 0.3s ease;
            z-index: 1;
            text-decoration: none;
            display: flex;
            align-items: center;
            gap: 3px;
        }

        #contributor-btn:hover {
            background: #0366d6;
            transform: translateY(-50%) translateY(-1px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.4);
        }

        #position-dropdown {
            position: absolute;
            top: 50%;
            left: -105px;
            transform: translateY(-50%);
            background: #4a90e2;
            color: white;
            border: none;
            padding: 5px 8px;
            border-radius: 3px;
            cursor: pointer;
            font-weight: bold;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            font-size: 12px;
            opacity: 0;
            transition: all 0.3s ease;
            z-index: 1;
            display: flex;
            align-items: center;
            gap: 3px;
        }

        #position-dropdown:hover {
            background: #357abd;
            transform: translateY(-50%) translateY(-1px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.4);
        }

        .position-menu {
            position: absolute;
            bottom: -135px;
            left: -140px;
            background: white;
            border: 1px solid #ddd;
            border-radius: 5px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.2);
            padding: 5px;
            display: none;
            z-index: 1000;
            min-width: 120px;
        }

        .position-menu.show {
            display: block;
        }

        .position-option {
            padding: 8px 12px;
            cursor: pointer;
            border-radius: 3px;
            font-size: 11px;
            color: #333;
            transition: background 0.2s ease;
        }

        .position-option:hover {
            background: #f0f0f0;
        }

        .position-option.active {
            background: #4a90e2;
            color: white;
        }

        #facebook-downloader-btn:hover #terminal-toggle-btn,
        #facebook-downloader-btn:hover #contributor-btn,
        #facebook-downloader-btn:hover #position-dropdown {
            opacity: 1;
        }

        #terminal-toggle-btn:hover {
            background: #444;
            box-shadow: 0 4px 8px rgba(0,0,0,0.4);
        }

        #terminal-console {
            position: fixed;
            bottom: -300px;
            left: 0;
            right: 0;
            height: 300px;
            background: #1e1e1e;
            border-top: 2px solid #333;
            z-index: 9998;
            transition: bottom 0.3s ease;
            display: flex;
            flex-direction: column;
        }

        #terminal-console.show {
            bottom: 0;
        }

        #terminal-header {
            background: #333;
            color: white;
            padding: 8px 16px;
            font-size: 14px;
            font-weight: bold;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        #terminal-close {
            background: none;
            border: none;
            color: #ccc;
            font-size: 18px;
            cursor: pointer;
            padding: 0;
            width: 20px;
            height: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        #terminal-close:hover {
            color: white;
        }

        #terminal-content {
            flex: 1;
            background: #1e1e1e;
            color: #00ff00;
            font-family: 'Courier New', monospace;
            font-size: 12px;
            padding: 16px;
            overflow-y: auto;
            white-space: pre-wrap;
            line-height: 1.4;
        }

        #terminal-content::-webkit-scrollbar {
            width: 8px;
        }

        #terminal-content::-webkit-scrollbar-track {
            background: #2d2d2d;
        }

        #terminal-content::-webkit-scrollbar-thumb {
            background: #555;
            border-radius: 4px;
        }

        #terminal-content::-webkit-scrollbar-thumb:hover {
            background: #777;
        }

        .log-info {
            color: #00ff00;
        }

        .log-success {
            color: #00ff00;
            font-weight: bold;
        }

        .log-error {
            color: #ff4444;
            font-weight: bold;
        }

        .log-warning {
            color: #ffaa00;
        }

        .log-progress {
            color: #44aaff;
        }

        #download-progress {
            position: fixed;
            top: 60px;
            right: 10px;
            z-index: 9999;
            background: rgba(0,0,0,0.8);
            color: white;
            padding: 10px;
            border-radius: 5px;
            display: none;
            max-width: 300px;
            word-wrap: break-word;
        }

        .notification {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 10000;
            background: rgba(0, 0, 0, 0.9);
            color: white;
            padding: 20px 30px;
            border-radius: 10px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
            font-size: 16px;
            font-weight: bold;
            text-align: center;
            min-width: 300px;
            animation: fadeInOut 3s ease-in-out;
        }

        .notification.error {
            background: rgba(220, 53, 69, 0.9);
            border: 2px solid #dc3545;
        }

        .notification.warning {
            background: rgba(255, 193, 7, 0.9);
            border: 2px solid #ffc107;
            color: #000;
        }

        .notification.info {
            background: #20a464e6;
            border: 2px solid #00ff73ff;
        }

        @keyframes fadeInOut {
            0% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
            15% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
            85% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
            100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
        }

        .fb-download-icon {
            position: absolute;
            top: 10px;
            right: 10px;
            width: 30px;
            height: 30px;
            background: rgba(0, 0, 0, 0.7);
            border-radius: 50%;
            cursor: pointer;
            z-index: 1000;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
            opacity: 0;
            font-size: 14px;
        }

        .fb-download-icon:hover {
            background: rgba(0, 0, 0, 0.9);
            transform: scale(1.1);
        }

        div.x10l6tqk.x13vifvy:hover .fb-download-icon {
            opacity: 1;
        }

        div.xh8yej3:hover .fb-download-icon {
            opacity: 1;
        }

        div.x6s0dn4.x78zum5.xdt5ytf.xl56j7k.x1n2onr6 {
            position: relative !important;
        }

        div.x6s0dn4.x78zum5.xdt5ytf.xl56j7k.x1n2onr6:hover .fb-download-icon {
            opacity: 1;
        }

        div.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x18d0r48.x1ey2m1c.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xl8spv7.xt2wqj3 {
            position: relative !important;
        }

        div.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x18d0r48.x1ey2m1c.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xl8spv7.xt2wqj3:hover .fb-download-icon {
            opacity: 1;
        }
    `);

    // Create container for download button and drag handle
    const downloaderContainer = document.createElement('div');
    downloaderContainer.id = 'facebook-downloader-container';

    // Create bulk download button
    const downloadBtn = document.createElement('button');
    downloadBtn.id = 'facebook-downloader-btn';
    downloadBtn.innerHTML = 'Download All Images';

    // Create separate drag handle
    const dragHandle = document.createElement('div');
    dragHandle.id = 'drag-handle';
    dragHandle.innerHTML = '🌠';
    dragHandle.title = 'Drag to move';

    // Create terminal toggle button
    const terminalToggleBtn = document.createElement('button');
    terminalToggleBtn.id = 'terminal-toggle-btn';
    terminalToggleBtn.textContent = '⬇️';
    terminalToggleBtn.title = 'Toggle Terminal Console';

    // Create contributor button
    const contributorBtn = document.createElement('a');
    contributorBtn.id = 'contributor-btn';
    contributorBtn.href = 'https://github.com/bibekchandsah/fb-ig-image-auto-download';
    contributorBtn.target = '_blank';
    contributorBtn.title = 'View on GitHub - Contribute';
    contributorBtn.innerHTML = '<span style="font-size: 14px;">⭐</span>';

    // Create position dropdown
    const positionDropdown = document.createElement('button');
    positionDropdown.id = 'position-dropdown';
    positionDropdown.title = 'Change icon position';
    positionDropdown.innerHTML = '📍';

    // Create dropdown menu
    const positionMenu = document.createElement('div');
    positionMenu.className = 'position-menu';
    positionMenu.innerHTML = `
        <div class="position-option active" data-position="top-left">Top Left</div>
        <div class="position-option" data-position="top-right">Top Right</div>
        <div class="position-option" data-position="bottom-right">Bottom Right</div>
        <div class="position-option" data-position="bottom-left">Bottom Left</div>
        <div class="position-option" data-position="center">Center</div>
    `;
    positionDropdown.appendChild(positionMenu);

    // Assemble the container - download button contains all control buttons
    downloadBtn.appendChild(dragHandle);
    downloadBtn.appendChild(terminalToggleBtn);
    downloadBtn.appendChild(contributorBtn);
    downloadBtn.appendChild(positionDropdown);
    downloaderContainer.appendChild(downloadBtn);

    document.body.appendChild(downloaderContainer);

    // Add drag functionality to the separate handle
    let isDragging = false;
    let dragOffset = { x: 0, y: 0 };

    dragHandle.addEventListener('mousedown', function(e) {
        e.preventDefault();
        e.stopPropagation();
        isDragging = true;

        const rect = downloaderContainer.getBoundingClientRect();
        dragOffset.x = e.clientX - rect.left;
        dragOffset.y = e.clientY - rect.top;

        downloaderContainer.classList.add('dragging');
        document.body.style.userSelect = 'none';
    });

    // Prevent drag handle from triggering download on any click event
    dragHandle.addEventListener('click', function(e) {
        e.preventDefault();
        e.stopPropagation();
    });

    document.addEventListener('mousemove', function(e) {
        if (!isDragging) return;

        e.preventDefault();
        const x = e.clientX - dragOffset.x;
        const y = e.clientY - dragOffset.y;

        // Keep container within viewport bounds
        const maxX = window.innerWidth - downloaderContainer.offsetWidth;
        const maxY = window.innerHeight - downloaderContainer.offsetHeight;

        const constrainedX = Math.max(0, Math.min(x, maxX));
        const constrainedY = Math.max(0, Math.min(y, maxY));

        downloaderContainer.style.left = constrainedX + 'px';
        downloaderContainer.style.top = constrainedY + 'px';
        downloaderContainer.style.right = 'auto';
    });

    document.addEventListener('mouseup', function(e) {
        if (isDragging) {
            isDragging = false;
            downloaderContainer.classList.remove('dragging');
            document.body.style.userSelect = '';

            // Save position to localStorage
            const rect = downloaderContainer.getBoundingClientRect();
            localStorage.setItem('fb-downloader-pos', JSON.stringify({
                left: rect.left,
                top: rect.top
            }));
        }
    });

    // Additional safety: end drag on mouse leave (prevents sticking)
    document.addEventListener('mouseleave', function(e) {
        if (isDragging) {
            isDragging = false;
            downloaderContainer.classList.remove('dragging');
            document.body.style.userSelect = '';
        }
    });

    // End drag if Escape key is pressed
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape' && isDragging) {
            isDragging = false;
            downloaderContainer.classList.remove('dragging');
            document.body.style.userSelect = '';
        }
    });

    // Restore saved position
    const savedPos = localStorage.getItem('fb-downloader-pos');
    if (savedPos) {
        try {
            const pos = JSON.parse(savedPos);
            downloaderContainer.style.left = pos.left + 'px';
            downloaderContainer.style.top = pos.top + 'px';
            downloaderContainer.style.right = 'auto';
        } catch (e) {
            console.log('Could not restore container position:', e);
        }
    }

    // Create terminal console
    const terminalConsole = document.createElement('div');
    terminalConsole.id = 'terminal-console';

    const terminalHeader = document.createElement('div');
    terminalHeader.id = 'terminal-header';
    terminalHeader.innerHTML = `
        <span>Facebook Downloader Terminal</span>
        <button id="terminal-close">×</button>
    `;

    const terminalContent = document.createElement('div');
    terminalContent.id = 'terminal-content';
    terminalContent.textContent = 'Terminal initialized. Ready for operations...\n';

    terminalConsole.appendChild(terminalHeader);
    terminalConsole.appendChild(terminalContent);
    document.body.appendChild(terminalConsole);

    // Add event listeners for terminal (after elements are in DOM)
    terminalToggleBtn.addEventListener('click', function(e) {
        e.preventDefault();
        e.stopPropagation();
        toggleTerminal();
    });

    // Prevent contributor button from triggering download
    contributorBtn.addEventListener('click', function(e) {
        e.stopPropagation(); // Don't prevent default since we want the link to work
    });

    // Position dropdown functionality
    let currentPosition = localStorage.getItem('fb-icon-position') || 'top-left';

    const positionSettings = {
        'top-left': { top: '10px', left: '10px', right: 'auto', bottom: 'auto', transform: 'none' },
        'top-right': { top: '10px', right: '10px', left: 'auto', bottom: 'auto', transform: 'none' },
        'bottom-right': { bottom: '10px', right: '10px', top: 'auto', left: 'auto', transform: 'none' },
        'bottom-left': { bottom: '10px', left: '10px', top: 'auto', right: 'auto', transform: 'none' },
        'center': { top: '50%', right: '50%', left: 'auto', bottom: 'auto', transform: 'none' }
    };

    function updateIconPosition(position) {
        const settings = positionSettings[position];
        const iconStyle = `
            .fb-download-icon {
                position: absolute;
                top: ${settings.top};
                right: ${settings.right};
                bottom: ${settings.bottom};
                left: ${settings.left};
                transform: ${settings.transform};
                background: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 5px;
                border-radius: 50%;
                cursor: pointer;
                font-size: 16px;
                z-index: 1000;
                opacity: 0;
                transition: all 0.3s ease;
                width: 30px;
                height: 30px;
                display: flex;
                align-items: center;
                justify-content: center;
            }
        `;

        // Remove old style if exists
        const oldStyle = document.getElementById('fb-icon-position-style');
        if (oldStyle) oldStyle.remove();

        // Add new style
        const styleElement = document.createElement('style');
        styleElement.id = 'fb-icon-position-style';
        styleElement.textContent = iconStyle;
        document.head.appendChild(styleElement);

        // Update active option in menu
        positionMenu.querySelectorAll('.position-option').forEach(option => {
            option.classList.remove('active');
            if (option.dataset.position === position) {
                option.classList.add('active');
            }
        });

        currentPosition = position;
        localStorage.setItem('fb-icon-position', position);

        // Log the change
        if (typeof logToTerminal === 'function') {
            logToTerminal(`Icon position changed to: ${position}`, 'info');
        }
    }

    // Initialize with saved position
    updateIconPosition(currentPosition);

    // Position dropdown event listeners
    positionDropdown.addEventListener('click', function(e) {
        e.preventDefault();
        e.stopPropagation();
        positionMenu.classList.toggle('show');
    });

    // Position option click handlers
    positionMenu.addEventListener('click', function(e) {
        if (e.target.classList.contains('position-option')) {
            e.preventDefault();
            e.stopPropagation();
            const position = e.target.dataset.position;
            updateIconPosition(position);
            positionMenu.classList.remove('show');
        }
    });

    // Close dropdown when clicking outside
    document.addEventListener('click', function(e) {
        if (!positionDropdown.contains(e.target)) {
            positionMenu.classList.remove('show');
        }
    });

    document.getElementById('terminal-close').addEventListener('click', () => {
        if (terminalVisible) {
            toggleTerminal();
        }
    });

    // Create progress indicator
    const progressDiv = document.createElement('div');
    progressDiv.id = 'download-progress';
    document.body.appendChild(progressDiv);

    let downloadCount = 0;
    let isDownloading = false;
    let addedIcons = new Set();
    let terminalVisible = false;

    // Notification system
    function showNotification(message, type = 'info', duration = 3000) {
        // Remove any existing notifications
        const existingNotifications = document.querySelectorAll('.notification');
        existingNotifications.forEach(notif => notif.remove());

        // Create notification element
        const notification = document.createElement('div');
        notification.className = `notification ${type}`;
        notification.textContent = message;

        // Add to page
        document.body.appendChild(notification);

        // Remove after duration
        setTimeout(() => {
            if (notification.parentNode) {
                notification.parentNode.removeChild(notification);
            }
        }, duration);

        return notification;
    }

    // Terminal logging functions
    function logToTerminal(message, type = 'info') {
        const timestamp = new Date().toLocaleTimeString();
        const logLine = `[${timestamp}] ${message}\n`;

        const content = document.getElementById('terminal-content');
        const logElement = document.createElement('span');
        logElement.className = `log-${type}`;
        logElement.textContent = logLine;

        content.appendChild(logElement);
        content.scrollTop = content.scrollHeight;
    }

    function clearTerminal() {
        const content = document.getElementById('terminal-content');
        content.innerHTML = '';
        logToTerminal('Terminal cleared', 'info');
    }

    // Terminal toggle functionality
    function toggleTerminal() {
        terminalVisible = !terminalVisible;
        const terminal = document.getElementById('terminal-console');

        if (terminalVisible) {
            terminal.classList.add('show');
            terminalToggleBtn.textContent = '⬆️';
            terminalToggleBtn.title = 'Hide Terminal Console';
            logToTerminal('Terminal opened', 'info');
        } else {
            terminal.classList.remove('show');
            terminalToggleBtn.textContent = '⬇️';
            terminalToggleBtn.title = 'Show Terminal Console';
        }
    }

    // Notification system
    function showNotification(message, type = 'info', duration = 3000) {
        // Remove any existing notifications
        const existingNotifications = document.querySelectorAll('.notification');
        existingNotifications.forEach(notif => notif.remove());

        // Create notification element
        const notification = document.createElement('div');
        notification.className = `notification ${type}`;
        notification.textContent = message;

        // Add to page
        document.body.appendChild(notification);

        // Remove after duration
        setTimeout(() => {
            if (notification.parentNode) {
                notification.parentNode.removeChild(notification);
            }
        }, duration);

        return notification;
    }

    function extractImageUrl(img) {
        if (img.src) {
            return img.src;
        } else if (img.dataset && img.dataset.src) {
            return img.dataset.src;
        } else if (img.getAttribute('data-src')) {
            return img.getAttribute('data-src');
        }
        return null;
    }

    // Function to extract post date from Facebook post
    function extractPostDate(divElement) {
        try {
            // Find the closest post container first
            const postContainer = divElement.closest('div.x1n2onr6.x1ja2u2z.x1jx94hy.xw5cjc7.x1dmpuos.x1vsv7so.xau1kf4.x9f619.xh8yej3.x6ikm8r.x10wlt62.xquyuld') ||
                                divElement.querySelector('div.x1n2onr6.x1ja2u2z.x1jx94hy.xw5cjc7.x1dmpuos.x1vsv7so.xau1kf4.x9f619.xh8yej3.x6ikm8r.x10wlt62.xquyuld');

            if (!postContainer) {
                console.log('Facebook Date Extractor: No post container found');
                return null;
            }

            // Try multiple approaches to find date elements
            let dateText = null;

            // Approach 1: Look for the specific date structure you mentioned
            const dateDiv = postContainer.querySelector('div.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x6s0dn4.x17zd0t2.x78zum5.x1q0g3np.x1a02dak');
            if (dateDiv) {
                console.log('Facebook Date Extractor: Found date div');
                const dateSpan = dateDiv.querySelector('span.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x1hl2dhg.x16tdsg8.x1vvkbs.x4k7w5x.x1h91t0o.x1h9r5lt.x1jfb8zj.xv2umb2.x1beo9mf.xaigb6o.x12ejxvf.x3igimt.xarpa2k.xedcshv.x1lytzrv.x1t2pt76.x7ja8zs.x1qrby5j');
                if (dateSpan) {
                    console.log('Facebook Date Extractor: Found date span');
                    const dateAnchor = dateSpan.querySelector('a.x1i10hfl.xjbqb8w.x1ejq31n.x18oe1m7.x1sy0etr.xstzfhl.x972fbf.x10w94by.x1qhh985.x14e42zd.x9f619.x1ypdohk.xt0psk2.x3ct3a4.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x16tdsg8.x1hl2dhg.xggy1nq.x1a2a7pz.xkrqix3.x1sur9pj.xi81zsa.x1s688f');
                    if (dateAnchor) {
                        console.log('Facebook Date Extractor: Found date anchor');
                        const finalSpan = dateAnchor.querySelector('span.x1rg5ohu.x6ikm8r.x10wlt62.x16dsc37.xt0b8zv');
                        if (finalSpan) {
                            dateText = finalSpan.textContent || finalSpan.innerText;
                            console.log('Facebook Date Extractor: Found date text (Approach 1):', dateText);
                        }
                    }
                }
            }

            // Approach 2: Look for any time/date related elements
            if (!dateText || dateText.length < 3) {
                console.log('Facebook Date Extractor: Trying Approach 2 - time elements');
                const timeElements = postContainer.querySelectorAll('time, [datetime], [data-utime], [title*="20"], [aria-label*="20"]');
                for (let timeEl of timeElements) {
                    const text = timeEl.textContent || timeEl.innerText || timeEl.getAttribute('datetime') ||
                                timeEl.getAttribute('data-utime') || timeEl.getAttribute('title') || timeEl.getAttribute('aria-label');
                    if (text && text.trim().length > 2) {
                        dateText = text;
                        console.log('Facebook Date Extractor: Found date text (Approach 2):', dateText);
                        break;
                    }
                }
            }

            // Approach 3: Look for spans that might contain date text (more aggressive)
            if (!dateText || dateText.length < 3) {
                console.log('Facebook Date Extractor: Trying Approach 3 - span search');
                const spans = postContainer.querySelectorAll('span, a');
                for (let span of spans) {
                    const text = span.textContent || span.innerText;
                    if (text && text.trim().length > 2 && text.trim().length < 50) {
                        // Check for date patterns
                        if (/\\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\s+\\d{1,2}[,\\s]*\\d{4}/i.test(text) ||
                            /\\b\\d{1,2}[/\\-]\\d{1,2}[/\\-]\\d{4}\\b/.test(text) ||
                            /\\b\\d{4}[/\\-]\\d{1,2}[/\\-]\\d{1,2}\\b/.test(text) ||
                            /\\b(yesterday|today|\\d+\\s*(h|hour|hours|m|min|minute|minutes|d|day|days)\\s*ago)\\b/i.test(text) ||
                            /\\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\s+\\d{1,2}\\b/i.test(text) ||
                            text.includes('20') && (text.includes('Jan') || text.includes('Feb') || text.includes('Mar') ||
                            text.includes('Apr') || text.includes('May') || text.includes('Jun') ||
                            text.includes('Jul') || text.includes('Aug') || text.includes('Sep') ||
                            text.includes('Oct') || text.includes('Nov') || text.includes('Dec'))) {
                            dateText = text;
                            console.log('Facebook Date Extractor: Found date text (Approach 3):', dateText);
                            break;
                        }
                    }
                }
            }

            // Approach 4: Really aggressive search - look for any text that might be a date
            if (!dateText || dateText.length < 3) {
                console.log('Facebook Date Extractor: Trying Approach 4 - aggressive search');
                const allElements = postContainer.querySelectorAll('*');
                for (let elem of allElements) {
                    const text = elem.textContent || elem.innerText;
                    if (text && elem.children.length === 0 && text.trim().length > 2 && text.trim().length < 30) {
                        // Look for very specific patterns
                        if (/^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\s+\\d{1,2}[,\\s]*\\d{4}$/i.test(text.trim()) ||
                            /^\\d{1,2}[/\\-]\\d{1,2}[/\\-]\\d{4}$/.test(text.trim()) ||
                            /^(yesterday|today|\\d+\\s*(h|hour|hours|m|min|minute|minutes|d|day|days)\\s*ago)$/i.test(text.trim())) {
                            dateText = text.trim();
                            console.log('Facebook Date Extractor: Found date text (Approach 4):', dateText);
                            break;
                        }
                    }
                }
            }

            if (dateText) {
                console.log('Facebook Date Extractor: Raw date text:', dateText);

                // First, handle the Facebook dash-separated character issue
                let cleanDate = dateText;

                // Remove the dash-separated character formatting that Facebook uses
                // This converts "-S---e--p-------t-e----m--b---er-- --25--" to "September 25"
                cleanDate = cleanDate.replace(/-+/g, '').replace(/\s+/g, ' ').trim();

                console.log('Facebook Date Extractor: After removing dashes:', cleanDate);

                // Now remove any remaining invalid filename characters
                cleanDate = cleanDate.replace(/[<>:"/\\|?*\x00-\x1f\x7f-\x9f]/g, '').trim();

                console.log('Facebook Date Extractor: After removing invalid chars:', cleanDate);

                // Replace multiple spaces with single spaces
                cleanDate = cleanDate.replace(/\s+/g, ' ');

                console.log('Facebook Date Extractor: Final cleaning:', cleanDate);

                // Validate the cleaned date
                if (cleanDate.length > 2 && cleanDate.length < 50) {
                    // Check if it contains reasonable date content
                    const hasMonth = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December)\b/i.test(cleanDate);
                    const hasNumber = /\d/.test(cleanDate);
                    const hasTimeIndicator = /\b(AM|PM|at|ago|hour|min|day|yesterday|today)\b/i.test(cleanDate);

                    if (hasMonth || hasNumber || hasTimeIndicator) {
                        console.log('Facebook Date Extractor: Final date:', cleanDate);
                        return cleanDate;
                    }
                }

                console.log('Facebook Date Extractor: Date validation failed');
                return null;
            }

            console.log('Facebook Date Extractor: No date found');
            return null;
        } catch (error) {
            console.log('Facebook Date Extractor: Error extracting post date:', error);
            return null;
        }
    }

    // Function to determine image type based on CSS classes
    function getImageType(img) {
        const className = img.className;

        // Check for new image class (priority check)
        if (className.includes('xz74otr') && className.includes('x16uus16') && className.includes('xbiv7yw') && className.includes('xjbqb8w') && className.includes('xu25z0z') && className.includes('x1fmog5m') && className.includes('x1o0tod') && className.includes('x10l6tqk') && className.includes('xwa60dl') && className.includes('x1cb1t30') && className.includes('xh8yej3') && className.includes('x1ja2u2z')) {
            return 'story-view';
        }
        // Check for post view (existing class)
        else if (className.includes('x15mokao') && className.includes('x1ga7v0g') && className.includes('x16uus16') && className.includes('xbiv7yw') && className.includes('x1bwycvy') && className.includes('x193iq5w') && className.includes('x4fas0m') && className.includes('x19kjcj4')) {
            return 'post-view';
        }
        // Check for multiple photos (existing class)
        else if (className.includes('xz74otr') && className.includes('x15mokao') && className.includes('x1ga7v0g') && className.includes('x16uus16') && className.includes('xbiv7yw')) {
            return 'multiple-photos';
        }
        // Check for post photo (priority 3)
        else if (className.includes('x15mokao') && className.includes('x1ga7v0g') && className.includes('x16uus16') && className.includes('xbiv7yw') && className.includes('xl1xv1r')) {
            return 'post-photo';
        }
        // Check for profile photo (priority 1)
        else if (className.includes('x1rg5ohu') && className.includes('xl1xv1r') && !className.includes('x15mokao')) {
            return 'profile-photo';
        }
        // Check for cover photo (priority 2)
        else if (className.includes('xz74otr') && className.includes('x1ey2m1c') && className.includes('x9f619')) {
            return 'cover-photo';
        }
        // Fallback
        else {
            return 'unknown-photo';
        }
    }

    // Function to generate filename
    function generateFilename(altText, index, imageType, postDate) {
        let filename = `fb-image-${index}-`;

        // Add post date if available
        if (postDate) {
            filename += `${postDate}-`;
        }

        filename += `${imageType}-`;

        if (altText) {
            let cleanAlt = altText.replace(/[<>:"/\\|?*]/g, '').trim();
            if (cleanAlt.length > 50) {
                cleanAlt = cleanAlt.substring(0, 50) + '...';
            }
            filename += cleanAlt;
        } else {
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
            filename += timestamp;
        }

        return filename + '.jpg';
    }

    // Function to download image
    async function downloadImage(img, divElement) {
        const imageUrl = extractImageUrl(img);
        if (!imageUrl) {
            logToTerminal('Could not extract image URL from current image', 'error');
            showNotification('❌ Failed to extract image URL!\nThe image source could not be found.', 'error', 4000);
            return;
        }

        const altText = img.alt || img.getAttribute('alt') || '';
        const imageType = getImageType(img);
        const postDate = extractPostDate(divElement);
        downloadCount++;
        const filename = generateFilename(altText, downloadCount, imageType, postDate);

        try {
            logToTerminal(`Starting download: ${filename}`, 'info');
            GM_download(imageUrl, filename);
            logToTerminal(`Successfully downloaded: ${filename}`, 'success');
            showNotification(`✅ Image downloaded!\n${filename}`, 'info', 2500);
            console.log(`Downloaded: ${filename}`);
        } catch (error) {
            logToTerminal(`Failed to download image: ${filename} - ${error.message}`, 'error');
            showNotification(`❌ Download failed!\n${filename}\n${error.message}`, 'error', 4000);
            console.error('Failed to download image:', error);
        }
    }

    // Function to add download icon to a div
    function addDownloadIcon(divElement) {
        // Check if icon already exists
        if (divElement.querySelector('.fb-download-icon') || addedIcons.has(divElement)) {
            return false;
        }

        // Find the specific image with the target classes - try all six selectors
        let img = divElement.querySelector('img.x1rg5ohu.x5yr21d.xl1xv1r.xh8yej3'); // Priority 1

        if (!img) {
            // Try the second image selector
            img = divElement.querySelector('img.xz74otr.x1ey2m1c.x9f619.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3'); // Priority 2
        }

        if (!img) {
            // Try the third image selector
            img = divElement.querySelector('img.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3.xl1xv1r'); // Priority 3
        }

        if (!img) {
            // Try the fourth image selector (multiple photos)
            img = divElement.querySelector('img.xz74otr.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3'); // Priority 4
        }

        if (!img) {
            // Try the fifth image selector (post view)
            img = divElement.querySelector('img.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1bwycvy.x193iq5w.x4fas0m.x19kjcj4'); // Priority 5
        }

        if (!img) {
            // Try the sixth image selector (special photo)
            img = divElement.querySelector('img.xz74otr.x16uus16.xbiv7yw.xjbqb8w.xu25z0z.x1fmog5m.x1o0tod.x10l6tqk.xwa60dl.x1cb1t30.xh8yej3.x1ja2u2z'); // Priority 6
        }

        if (!img) {
            return false;
        }

        // Create download icon
        const iconContainer = document.createElement('div');
        iconContainer.className = 'fb-download-icon';
        iconContainer.title = 'Download this image';
        iconContainer.textContent = '💾';

        // Add click event
        iconContainer.addEventListener('click', async (e) => {
            e.preventDefault();
            e.stopPropagation();

            // Find current image at click time - try all six selectors
            let currentImg = divElement.querySelector('img.x1rg5ohu.x5yr21d.xl1xv1r.xh8yej3');

            if (!currentImg) {
                currentImg = divElement.querySelector('img.xz74otr.x1ey2m1c.x9f619.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3');
            }

            if (!currentImg) {
                currentImg = divElement.querySelector('img.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3.xl1xv1r');
            }

            if (!currentImg) {
                currentImg = divElement.querySelector('img.xz74otr.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3');
            }

            if (!currentImg) {
                currentImg = divElement.querySelector('img.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1bwycvy.x193iq5w.x4fas0m.x19kjcj4');
            }

            if (!currentImg) {
                currentImg = divElement.querySelector('img.xz74otr.x16uus16.xbiv7yw.xjbqb8w.xu25z0z.x1fmog5m.x1o0tod.x10l6tqk.xwa60dl.x1cb1t30.xh8yej3.x1ja2u2z');
            }

            if (currentImg) {
                await downloadImage(currentImg, divElement);

                // Visual feedback
                const originalBg = iconContainer.style.background;
                iconContainer.style.background = 'rgba(0, 128, 0, 0.8)';
                setTimeout(() => {
                    iconContainer.style.background = originalBg;
                }, 1000);
            } else {
                // Check if this might be a video by looking for video elements
                const hasVideo = divElement.querySelector('video') !== null;
                const hasVideoIcon = divElement.querySelector('[aria-label*="video" i]') !== null;

                if (hasVideo || hasVideoIcon) {
                    logToTerminal('Video content detected - cannot download videos as images', 'warning');
                    showNotification('📹 This appears to be a video, not an image!\nVideos cannot be downloaded with this tool.', 'warning', 4000);
                } else {
                    logToTerminal('No current image found for download - content may be a video or unsupported format', 'error');
                    showNotification('🚫 No image found!\nThis might be a video or unsupported content.', 'error', 4000);
                }
            }
        });

        divElement.appendChild(iconContainer);
        addedIcons.add(divElement);
        return true;
    }

    // Function to wait for a specified time
    function delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // Function to scroll to load more content
    async function scrollToLoadMore() {
        const initialHeight = document.body.scrollHeight;
        window.scrollTo(0, document.body.scrollHeight);

        // Wait for potential new content to load
        await delay(3000);

        const newHeight = document.body.scrollHeight;
        return newHeight > initialHeight;
    }

    // Function to collect and download new images from current viewport
    async function collectAndDownloadNewImages(downloadedUrls) {
        const allDivs = [
            ...document.querySelectorAll('div.xh8yej3'),
            ...document.querySelectorAll('div.x1qjc9v5.x1q0q8m5.x1qhh985.x18b5jzi.x10w94by.x1t7ytsu.x14e42zd.x13fuv20.x972fbf.x1ey2m1c.x9f619.x78zum5.xdt5ytf.x1iyjqo2.xs83m0k.xtijo5x.x1o0tod.x1qughib.xat24cr.x14z9mp.x1lziwak.xdj266r.x2lwn1j.xeuugli.x18d9i69.xyri2b.x1c1uobl.xexx8yu.x10l6tqk.x13vifvy.x1ja2u2z'),
            ...document.querySelectorAll('div.x10l6tqk.x13vifvy'),
            ...document.querySelectorAll('div.x6s0dn4.x78zum5.xdt5ytf.xl56j7k.x1n2onr6'),
            ...document.querySelectorAll('div.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x18d0r48.x1ey2m1c.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xl8spv7.xt2wqj3')
        ];

        let newImagesDownloaded = 0;

        logToTerminal(`Scanning ${allDivs.length} posts for new images`, 'progress');

        for (const div of allDivs) {
            // Try to find image with any of the supported selectors
            let img = div.querySelector('img.x1rg5ohu.x5yr21d.xl1xv1r.xh8yej3') ||
                     div.querySelector('img.xz74otr.x1ey2m1c.x9f619.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3') ||
                     div.querySelector('img.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3.xl1xv1r') ||
                     div.querySelector('img.xz74otr.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3') ||
                     div.querySelector('img.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1bwycvy.x193iq5w.x4fas0m.x19kjcj4') ||
                     div.querySelector('img.xz74otr.x16uus16.xbiv7yw.xjbqb8w.xu25z0z.x1fmog5m.x1o0tod.x10l6tqk.xwa60dl.x1cb1t30.xh8yej3.x1ja2u2z');

            if (img) {
                const imageUrl = extractImageUrl(img);
                if (imageUrl && !downloadedUrls.has(imageUrl)) {
                    downloadedUrls.add(imageUrl);

                    const altText = img.alt || img.getAttribute('alt') || '';
                    const imageType = getImageType(img);
                    const postDate = extractPostDate(div);
                    downloadCount++;
                    const filename = generateFilename(altText, downloadCount, imageType, postDate);

                    try {
                        logToTerminal(`Downloading: ${filename}`, 'progress');
                        GM_download(imageUrl, filename);
                        newImagesDownloaded++;

                        progressDiv.textContent = `Downloaded ${downloadCount} images - ${filename.substring(0, 50)}...`;
                        await delay(300);
                    } catch (error) {
                        logToTerminal(`Failed to download: ${filename} - ${error.message}`, 'error');
                        console.error('Failed to download image:', error);
                    }
                }
            }
        }

        if (newImagesDownloaded > 0) {
            logToTerminal(`Downloaded ${newImagesDownloaded} new images from current viewport`, 'success');
        }

        return newImagesDownloaded;
    }

    // Function to scroll and download images simultaneously
    async function scrollAndDownloadImages() {
        const downloadedUrls = new Set();
        let hasMoreContent = true;
        let noNewImagesCount = 0;
        let noNewContentCount = 0;
        let scrollAttempts = 0;

        logToTerminal('Starting bulk download process', 'info');
        logToTerminal('Collecting images from initial viewport', 'progress');

        // Download images from the initial viewport
        await collectAndDownloadNewImages(downloadedUrls);

        while (hasMoreContent && noNewImagesCount < 5 && noNewContentCount < 5) {
            const beforeHeight = document.body.scrollHeight;
            const beforeDownloadCount = downloadCount;

            // Scroll down
            logToTerminal(`Scrolling down (attempt ${scrollAttempts + 1})`, 'progress');
            window.scrollTo(0, document.body.scrollHeight);
            scrollAttempts++;

            // Wait for content to load
            await delay(2000);

            // Download new images that appeared
            const newImages = await collectAndDownloadNewImages(downloadedUrls);

            const afterHeight = document.body.scrollHeight;
            const afterDownloadCount = downloadCount;

            // Check if we found new content or images
            if (afterHeight > beforeHeight) {
                noNewContentCount = 0; // Reset counter if new content appeared
                logToTerminal(`New content loaded, page height: ${afterHeight}px`, 'info');
            } else {
                noNewContentCount++;
                logToTerminal(`No new content found (${noNewContentCount}/5)`, 'warning');
            }

            if (afterDownloadCount > beforeDownloadCount) {
                noNewImagesCount = 0; // Reset counter if new images were downloaded
            } else {
                noNewImagesCount++;
                logToTerminal(`No new images found (${noNewImagesCount}/5)`, 'warning');
            }

            progressDiv.textContent = `Scrolling and downloading... Found ${downloadCount} images (attempt ${scrollAttempts})`;

            // Check if we've reached the end
            if (window.innerHeight + window.scrollY >= document.body.scrollHeight - 100) {
                if (noNewContentCount >= 3 && noNewImagesCount >= 3) {
                    hasMoreContent = false;
                    logToTerminal('Reached end of content', 'info');
                }
            }
        }

        // Final attempt to collect any remaining images
        logToTerminal('Performing final scan for any remaining images', 'progress');
        await delay(2000);
        await collectAndDownloadNewImages(downloadedUrls);

        logToTerminal(`Bulk download completed! Total attempts: ${scrollAttempts}`, 'success');
        return { totalDownloaded: downloadCount, scrollAttempts };
    }

    // Function to find and download all images
    async function findAndDownloadAllImages() {
        if (isDownloading) {
            logToTerminal('Download already in progress!', 'warning');
            alert('Download already in progress!');
            return;
        }

        isDownloading = true;
        downloadCount = 0; // Reset counter
        progressDiv.style.display = 'block';
        progressDiv.textContent = 'Starting simultaneous scroll and download...';

        // Clear terminal and show it if not visible
        clearTerminal();
        if (!terminalVisible) {
            toggleTerminal();
        }

        logToTerminal('=== Starting Facebook Image Download Session ===', 'info');
        logToTerminal('Initializing bulk download process...', 'progress');

        try {
            // Scroll and download images simultaneously
            const { totalDownloaded, scrollAttempts } = await scrollAndDownloadImages();

            const successMessage = `Download complete! Successfully downloaded ${totalDownloaded} images after ${scrollAttempts} scroll attempts.`;
            progressDiv.textContent = successMessage;
            logToTerminal(`=== Download Session Complete ===`, 'success');
            logToTerminal(`Total images downloaded: ${totalDownloaded}`, 'success');
            logToTerminal(`Scroll attempts: ${scrollAttempts}`, 'info');

            if (totalDownloaded === 0) {
                const noImagesMessage = 'No images found with the specified classes. Make sure you are on a Facebook page with images.';
                progressDiv.textContent = noImagesMessage;
                logToTerminal(noImagesMessage, 'warning');
            }

            await delay(5000);
            progressDiv.style.display = 'none';

        } catch (error) {
            const errorMessage = `Error occurred during download process: ${error.message}`;
            console.error('Error during download process:', error);
            progressDiv.textContent = 'Error occurred during download process';
            logToTerminal(`=== Download Session Failed ===`, 'error');
            logToTerminal(errorMessage, 'error');
            await delay(3000);
            progressDiv.style.display = 'none';
        }

        isDownloading = false;
    }

    // Function to scan for target divs with priority system
    function scanForImages() {
        // First, find all post containers
        const postContainers = document.querySelectorAll('div.x1n2onr6.x1ja2u2z.x1jx94hy.xw5cjc7.x1dmpuos.x1vsv7so.xau1kf4.x9f619.xh8yej3.x6ikm8r.x10wlt62.xquyuld');
        let newIconsAdded = 0;

        postContainers.forEach(postContainer => {
            let hasAddedIcon = false;

            // Priority 1: Check for xh8yej3 div first
            const priority1Div = postContainer.querySelector('div.xh8yej3');

            if (priority1Div) {
                const priority1Img = priority1Div.querySelector('img.x1rg5ohu.x5yr21d.xl1xv1r.xh8yej3');

                if (priority1Img && addDownloadIcon(priority1Div)) {
                    newIconsAdded++;
                    hasAddedIcon = true;
                    return; // Skip other divs in this post container
                }
            }

            // Priority 2: Check for the new long div class
            const priority2Div = postContainer.querySelector('div.x1qjc9v5.x1q0q8m5.x1qhh985.x18b5jzi.x10w94by.x1t7ytsu.x14e42zd.x13fuv20.x972fbf.x1ey2m1c.x9f619.x78zum5.xdt5ytf.x1iyjqo2.xs83m0k.xtijo5x.x1o0tod.x1qughib.xat24cr.x14z9mp.x1lziwak.xdj266r.x2lwn1j.xeuugli.x18d9i69.xyri2b.x1c1uobl.xexx8yu.x10l6tqk.x13vifvy.x1ja2u2z');

            if (priority2Div && !hasAddedIcon) {
                const priority2Img = priority2Div.querySelector('img.xz74otr.x1ey2m1c.x9f619.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3');

                if (priority2Img && addDownloadIcon(priority2Div)) {
                    newIconsAdded++;
                    hasAddedIcon = true;
                    return; // Skip other divs in this post container
                }
            }

            // Priority 3: Check for regular divs (x10l6tqk x13vifvy) - handle differently for multiple photos
            const priority3Divs = postContainer.querySelectorAll('div.x10l6tqk.x13vifvy');

            priority3Divs.forEach(div => {
                // Check if this div has multiple photos image
                const multiplePhotosImg = div.querySelector('img.xz74otr.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3');

                if (multiplePhotosImg) {
                    // For multiple photos, add icon to each individual div
                    if (addDownloadIcon(div)) {
                        newIconsAdded++;
                    }
                } else if (!hasAddedIcon) {
                    // For single post photos, use priority system
                    const priority3Img = div.querySelector('img.x15mokao.x1ga7v0g.x16uus16.xbiv7yw.x1ey2m1c.x5yr21d.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xh8yej3.xl1xv1r');

                    if (priority3Img && addDownloadIcon(div)) {
                        newIconsAdded++;
                        hasAddedIcon = true;
                    }
                }
            });
        });

        // Also scan for standalone divs not inside post containers (fallback)
        const standaloneDivs1 = document.querySelectorAll('div.xh8yej3:not(.xdj266r .xh8yej3)');
        const standaloneDivs2 = document.querySelectorAll('div.x1qjc9v5.x1q0q8m5.x1qhh985.x18b5jzi.x10w94by.x1t7ytsu.x14e42zd.x13fuv20.x972fbf.x1ey2m1c.x9f619.x78zum5.xdt5ytf.x1iyjqo2.xs83m0k.xtijo5x.x1o0tod.x1qughib.xat24cr.x14z9mp.x1lziwak.xdj266r.x2lwn1j.xeuugli.x18d9i69.xyri2b.x1c1uobl.xexx8yu.x10l6tqk.x13vifvy.x1ja2u2z:not(.xdj266r .x1qjc9v5)');
        const standaloneDivs3 = document.querySelectorAll('div.x10l6tqk.x13vifvy:not(.xdj266r .x10l6tqk.x13vifvy)');
        const standaloneDivs4 = document.querySelectorAll('div.x6s0dn4.x78zum5.xdt5ytf.xl56j7k.x1n2onr6');
        const standaloneDivs5 = document.querySelectorAll('div.xdj266r.x14z9mp.xat24cr.x1lziwak.xexx8yu.xyri2b.x18d9i69.x1c1uobl.x18d0r48.x1ey2m1c.xtijo5x.x1o0tod.x10l6tqk.x13vifvy.xl8spv7.xt2wqj3');

        [...standaloneDivs1, ...standaloneDivs2, ...standaloneDivs3, ...standaloneDivs4, ...standaloneDivs5].forEach(div => {
            if (addDownloadIcon(div)) {
                newIconsAdded++;
            }
        });

        if (newIconsAdded > 0) {
            logToTerminal(`Added ${newIconsAdded} download icons to new posts`, 'info');
            console.log(`Added ${newIconsAdded} download icons to Facebook posts`);
        }
    }

    // Start monitoring
    function startMonitoring() {
        logToTerminal('Facebook Simple Image Downloader script loaded successfully', 'success');
        logToTerminal('Individual download icons will appear on hover', 'info');
        logToTerminal('Click the Download button or press Ctrl+Shift+D for bulk download', 'info');
        logToTerminal('Press Ctrl+` to toggle this terminal', 'info');
        console.log('Facebook Simple Image Downloader loaded');

        // Initial scan
        setTimeout(scanForImages, 2000);

        // Set up observer for new content
        const observer = new MutationObserver(() => {
            setTimeout(scanForImages, 1000);
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // Periodic scan
        setInterval(scanForImages, 5000);
    }

    // Add click event to bulk download button
    downloadBtn.addEventListener('click', function(e) {
        // Only trigger download if the button itself (or its text) is clicked, not child elements
        if (e.target === downloadBtn || e.target.tagName === undefined) {
            findAndDownloadAllImages();
        }
    });

    // Add keyboard shortcuts
    document.addEventListener('keydown', function(e) {
        // Ctrl + Shift + D for bulk download
        if (e.ctrlKey && e.shiftKey && e.key === 'D') {
            e.preventDefault();
            findAndDownloadAllImages();
        }
        // Ctrl + ` for terminal toggle
        else if (e.ctrlKey && e.key === '`') {
            e.preventDefault();
            toggleTerminal();
        }
    });

    // Wait for page to load
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', startMonitoring);
    } else {
        startMonitoring();
    }

    console.log('Facebook Image Downloader loaded. Individual download icons will appear on hover. Click the "Download All Images" button or press Ctrl+Shift+D to start bulk downloading.');

})();