Top-center button, selection menu, and location.replace for individual files.
// ==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) => ({
'&': '&', '<': '<', '>': '>', '"': '"', "'": '''
})[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();
})();