MediaFire Downloader

Top-center button, selection menu, and location.replace for individual files.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         MediaFire Downloader
// @namespace    http://tampermonkey.net/
// @match        *://www.mediafire.com/folder/*
// @match        *://www.mediafire.com/file/*
// @match        *://www.mediafire.com/file_premium/*
// @version      2.0
// @description  Top-center button, selection menu, and location.replace for individual files.
// @author       CizgiciCocuk
// @license      GNU GPL v3
// @grant        none
// ==/UserScript==

/* jshint esversion: 8 */

(function() {
    'use strict';

    const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
    let downloadInitiated = false;

    const escapeHTML = (str) => {
        return str.replace(/[&<>"']/g, (m) => ({
            '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
        })[m]);
    };

    const getNameFromLink = (el) => {
        let name = el.querySelector('.filename, .name, .title')?.innerText || el.getAttribute('title') || el.innerText;
        if (!name || name.trim().length === 0 || name.includes('Unknown File')) {
            try {
                const parts = el.href.split('/');
                for (let i = parts.length - 1; i >= 0; i--) {
                    if (parts[i].length > 5 && !['file', 'file_premium'].includes(parts[i])) {
                        name = decodeURIComponent(parts[i].replace(/\+/g, ' '));
                        break;
                    }
                }
            } catch (e) { name = "File"; }
        }
        return (name || "Unknown File").trim();
    };

    // --- FOLDER PAGE LOGIC (KEPT AS IS) ---
    const injectBulkButton = () => {
        if (document.getElementById('mf-universal-bulk-btn')) return;

        const bulkBtn = document.createElement('button');
        bulkBtn.id = 'mf-universal-bulk-btn';
        bulkBtn.innerText = '🚀 SELECT DOWNLOADS';

        Object.assign(bulkBtn.style, {
            position: 'fixed', top: '10px', left: '50%', transform: 'translateX(-50%)',
            zIndex: '2147483647', padding: '12px 20px', backgroundColor: '#28a745',
            color: 'white', border: '2px solid white', borderRadius: '8px',
            fontWeight: 'bold', cursor: 'pointer', boxShadow: '0 4px 15px rgba(0,0,0,0.4)',
            fontFamily: 'sans-serif'
        });

        document.body.appendChild(bulkBtn);
        bulkBtn.onclick = showSelectionMenu;
    };

    const showSelectionMenu = () => {
        const existing = document.getElementById('mf-selection-menu');
        if (existing) existing.remove();

        const linkElements = Array.from(document.querySelectorAll('a[href*="/file/"], a[href*="/file_premium/"]'))
            .filter(a => !a.href.includes('/folder/'));

        const uniqueFiles = [];
        const seen = new Set();
        linkElements.forEach(el => {
            if (!seen.has(el.href)) {
                uniqueFiles.push({ name: getNameFromLink(el), href: el.href });
                seen.add(el.href);
            }
        });

        if (uniqueFiles.length === 0) {
            alert("No files detected. Scroll down to load more content!");
            return;
        }

        const menu = document.createElement('div');
        menu.id = 'mf-selection-menu';
        Object.assign(menu.style, {
            position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
            width: '450px', maxHeight: '70vh', backgroundColor: '#ffffff', zIndex: '2147483648',
            padding: '20px', borderRadius: '12px', boxShadow: '0 0 50px rgba(0,0,0,0.5)',
            display: 'flex', flexDirection: 'column', color: '#333', fontFamily: 'sans-serif', border: '1px solid #ccc'
        });

        let listHtml = '';
        uniqueFiles.forEach((f, i) => {
            listHtml += `
                <div style="margin-bottom:8px; display:flex; align-items:center; gap:10px; border-bottom:1px solid #eee; padding-bottom:4px;">
                    <input type="checkbox" id="mf-chk-${i}" data-url="${f.href}" checked style="cursor:pointer; width:16px; height:16px;">
                    <label for="mf-chk-${i}" style="font-size:13px; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; flex-grow:1;">${escapeHTML(f.name)}</label>
                </div>`;
        });

        menu.innerHTML = `
            <div style="display:flex; justify-content:space-between; margin-bottom:15px;">
                <h3 style="margin:0; font-size:16px;">Batch Download</h3>
                <span style="font-size:12px; color:#666;">${uniqueFiles.length} files</span>
            </div>
            <div style="margin-bottom:10px; display:flex; gap:10px;">
                <button id="mf-select-all" style="flex:1; cursor:pointer;">Select All</button>
                <button id="mf-deselect-all" style="flex:1; cursor:pointer;">None</button>
            </div>
            <div style="overflow-y:auto; flex-grow:1;">${listHtml}</div>
            <div style="margin-top:20px; display:flex; gap:12px;">
                <button id="mf-start" style="flex:2; padding:12px; background:#28a745; color:white; border:none; border-radius:6px; cursor:pointer; font-weight:bold;">START</button>
                <button id="mf-close" style="flex:1; padding:12px; background:#eee; border:none; border-radius:6px; cursor:pointer;">Cancel</button>
            </div>
        `;

        document.body.appendChild(menu);

        document.getElementById('mf-select-all').onclick = () => { menu.querySelectorAll('input[type="checkbox"]').forEach(c => { c.checked = true; }); };
        document.getElementById('mf-deselect-all').onclick = () => { menu.querySelectorAll('input[type="checkbox"]').forEach(c => { c.checked = false; }); };
        document.getElementById('mf-close').onclick = () => { menu.remove(); };

        document.getElementById('mf-start').onclick = async () => {
            const selected = Array.from(menu.querySelectorAll('input[type="checkbox"]:checked'))
                                  .map(c => c.getAttribute('data-url'));

            if (selected.length === 0) return;
            menu.remove();

            for (let i = 0; i < selected.length; i++) {
                window.open(selected[i], '_blank');
                await wait(5000);
            }
        };
    };

    // --- INDIVIDUAL FILE PAGE LOGIC (UPDATED TO REDIRECT) ---
    const handleFilePage = () => {
        if (downloadInitiated) return;

        // Using direct redirect to download URL
        const downloadLinkInput = document.querySelector('.download_link .input') ||
                                 document.querySelector('#downloadButton');

        if (downloadLinkInput) {
            const downloadUrl = downloadLinkInput.getAttribute('href');
            if (downloadUrl) {
                downloadInitiated = true;

                // Redirect immediately (Aditya's focus-retention technique)
                location.replace(downloadUrl);

                // Close after 5 seconds
                setTimeout(() => { window.close(); }, 5000);
            }
        }
    };

    const route = () => {
        const url = window.location.href;
        if (url.includes('/folder/')) {
            injectBulkButton();
        } else if (url.includes('/file/') || url.includes('/file_premium/')) {
            handleFilePage();
        }
    };

    const observer = new MutationObserver(route);
    observer.observe(document.documentElement, { childList: true, subtree: true });
    route();
})();