MediaFire Downloader

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

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

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