MediaFire Downloader

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

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==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();
})();