MediaFire Downloader

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

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

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