This script helps you get download links on F95Zone faster and easier. It adds a small icon next to links to send them to JDownloader 2 or copy them instantly.
// ==UserScript==
// @name F95Zone.to | Link Grabber
// @namespace https://greasyfork.org/fr/users/1468290-payamarre
// @version 2.1
// @description This script helps you get download links on F95Zone faster and easier. It adds a small icon next to links to send them to JDownloader 2 or copy them instantly.
// @author NoOne
// @match https://f95zone.to/*
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM_setClipboard
// @grant GM_notification
// @connect f95zone.to
// @connect 127.0.0.1
// @connect localhost
// @license MIT
// @icon https://www.google.com/s2/favicons?domain=f95zone.to
// @antifeature ads Redirects links through external site to bypass Gofile & Pixeldrain download quotas.
// ==/UserScript==
(function() {
'use strict';
const TM_ORIGIN = `moz-extension://${GM_getValue("script_id") || (() => { let id = crypto.randomUUID(); GM_setValue("script_id", id); return id; })()}`;
const BYPASS = { GOFILE: "https://gf.1drv.eu.org/", PIXEL: "https://cdn.pixeldrain.eu.cc/" };
const DEFAULT_HOSTS = [
{ id: "bowfile", name: "Bowfile.com", pattern: "bowfile.com" },
{ id: "bunkr", name: "Bunkrrr.org", pattern: "bunkrrr.org" },
{ id: "buzzheavier", name: "Buzzheavier.com", pattern: "buzzheavier.com" },
{ id: "datanodes", name: "Datanodes.to", pattern: "datanodes.to" },
{ id: "google", name: "Drive.google.com", pattern: "drive.google.com" },
{ id: "filesfm", name: "Files.fm", pattern: "files.fm" },
{ id: "gofile", name: "Gofile.io", pattern: "gofile.io" },
{ id: "kraken", name: "Krakenfiles.com", pattern: "krakenfiles.com" },
{ id: "mediafire", name: "Mediafire.com", pattern: "mediafire.com" },
{ id: "mega", name: "Mega.nz", pattern: "mega.nz" },
{ id: "mixdrop", name: "Mixdrop.ag", pattern: "mixdrop.ag" },
{ id: "pixeldrain", name: "Pixeldrain.com", pattern: "pixeldrain.com" },
{ id: "uploadhaven", name: "Uploadhaven.com", pattern: "uploadhaven.com" },
{ id: "uploadnow", name: "Uploadnow.io", pattern: "uploadnow.io" },
{ id: "viking", name: "Vikingfile.com", pattern: "vikingfile.com" },
{ id: "workupload", name: "Workupload.com", pattern: "workupload.com" }
].sort((a, b) => a.name.localeCompare(b.name));
const globalStyle = document.createElement("style");
globalStyle.textContent = `
#ug-modal-overlay { position: fixed !important; top: 0 !important; left: 0 !important; width: 100vw !important; height: 100vh !important; background: rgba(0, 0, 0, 0.8) !important; display: flex !important; align-items: center !important; justify-content: center !important; z-index: 2147483647 !important; font-family: 'Inter', system-ui, sans-serif !important; backdrop-filter: blur(4px); }
.ug-modal { border-radius: 16px !important; width: 520px !important; display: flex !important; flex-direction: column !important; max-height: 85vh !important; box-shadow: 0 20px 50px rgba(0,0,0,0.6) !important; overflow: hidden !important; border: 1px solid rgba(128,128,128,0.2) !important; }
.ug-dark { background: #1c1e26 !important; color: #d1d5db !important; }
.ug-dark .ug-header { background: #232630 !important; border-bottom: 1px solid #2f3341 !important; }
.ug-dark .ug-card { background: #232630 !important; border: 1px solid #2f3341 !important; }
.ug-dark .ug-kbd { background: #1c1e26 !important; border: 1px solid #3f445b !important; color: #58a6ff !important; }
.ug-dark .ug-input { background: #1c1e26 !important; border: 1px solid #3f445b !important; color: #fff !important; }
.ug-light { background: #f0f2f5 !important; color: #1f2937 !important; }
.ug-light .ug-header { background: #ffffff !important; border-bottom: 1px solid #e5e7eb !important; }
.ug-light .ug-card { background: #ffffff !important; border: 1px solid #e5e7eb !important; }
.ug-light .ug-kbd { background: #f9fafb !important; border: 1px solid #d1d5db !important; color: #2563eb !important; }
.ug-light .ug-input { background: #ffffff !important; border: 1px solid #d1d5db !important; color: #111 !important; }
.ug-header { padding: 18px 24px !important; display: flex !important; justify-content: space-between !important; align-items: center !important; font-weight: 600 !important; }
.ug-theme-toggle { cursor: pointer !important; opacity: 0.7 !important; transition: 0.2s !important; }
.ug-theme-toggle:hover { opacity: 1 !important; color: #3b82f6 !important; }
.ug-content { padding: 24px !important; overflow-y: auto !important; flex: 1 !important; }
.ug-section { margin-bottom: 28px !important; }
.ug-label { font-size: 11px !important; color: #6b7280 !important; text-transform: uppercase !important; margin-bottom: 12px !important; display: block; letter-spacing: 1.2px !important; font-weight: 700 !important; }
.ug-card { border-radius: 12px !important; padding: 16px !important; margin-bottom: 12px !important; }
.ug-row { display: flex !important; justify-content: space-between !important; align-items: center !important; margin-bottom: 14px !important; gap: 15px !important; }
.ug-info b { font-size: 14px !important; display: block !important; }
.ug-info span { font-size: 12px !important; opacity: 0.6 !important; line-height: 1.4 !important; }
.ug-kbd { padding: 6px 12px !important; border-radius: 8px !important; font-family: ui-monospace, monospace !important; font-weight: 600 !important; font-size: 12px !important; cursor: pointer !important; min-width: 90px !important; text-align: center !important; transition: 0.2s !important; }
.ug-toggle-label { position: relative !important; display: inline-block !important; width: 40px !important; height: 22px !important; cursor: pointer !important; }
.ug-toggle-label input { opacity: 0 !important; width: 0 !important; height: 0 !important; }
.ug-toggle-slider { position: absolute !important; cursor: pointer !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; background-color: #4b5563 !important; border-radius: 20px !important; transition: .3s !important; }
input:checked + .ug-toggle-slider { background-color: #3b82f6 !important; }
.ug-toggle-slider:before { position: absolute !important; content: "" !important; height: 16px !important; width: 16px !important; left: 3px !important; bottom: 3px !important; background-color: white !important; border-radius: 50% !important; transition: .3s !important; }
input:checked + .ug-toggle-slider:before { transform: translateX(18px) !important; }
.ug-input-bar { display: flex !important; align-items: center !important; position: relative !important; width: 100% !important; margin-bottom: 12px !important; }
.ug-input { width: 100% !important; border-radius: 24px !important; padding: 12px 50px 12px 20px !important; font-size: 14px !important; outline: none !important; border: 1px solid transparent !important; }
.ug-add-btn { position: absolute !important; right: 6px !important; width: 34px !important; height: 34px !important; border-radius: 50% !important; background: #3b82f6 !important; color: white !important; border: none !important; cursor: pointer !important; display: flex !important; align-items: center !important; justify-content: center !important; }
.ug-list-item { display: flex !important; align-items: center !important; padding: 12px 8px !important; border-bottom: 1px solid rgba(128,128,128,0.1) !important; gap: 15px !important; }
.ug-del-btn { color: #ef4444 !important; cursor: pointer !important; border: none !important; background: none !important; font-size: 16px !important; opacity: 0.6 !important; }
.ug-domain-text { flex: 1 !important; font-size: 14px !important; }
.ug-disabled { opacity: 0.25 !important; text-decoration: line-through !important; }
.dlx { cursor:pointer; background:none; border:none; font-size:16px; margin-left:8px; color:#ffffff !important; display:inline-block; transition:color 0.2s; padding:0; vertical-align:middle; text-decoration:none !important; }
.dlx:hover { color:#ff7300 !important; }
.dlx-loading { animation: jd-spin 2s infinite linear; }
.action-success { color:#2ecc71 !important; }
@keyframes jd-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
`;
document.head.appendChild(globalStyle);
if (!document.getElementById('ug-fa-css')) {
const fa = document.createElement("link");
fa.id = 'ug-fa-css'; fa.rel = "stylesheet";
fa.href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css";
document.head.appendChild(fa);
}
function getCleanDomain(url) {
try { if (url.includes('/masked/')) { const parts = url.split('/masked/'); if (parts[1]) return parts[1].split('/')[0].toLowerCase(); }
return new URL(url).hostname.replace('www.', '').toLowerCase(); } catch(e) { return null; }
}
function refreshAllButtons() {
document.querySelectorAll('.dlx').forEach(b => b.remove());
document.querySelectorAll('.dlx-p').forEach(a => a.classList.remove('dlx-p'));
findLinks();
}
function toggleHost(domain) {
if (!domain) return;
const defaultHost = DEFAULT_HOSTS.find(h => domain.includes(h.pattern));
if (defaultHost) {
const current = GM_getValue("svc_" + defaultHost.id, true);
GM_setValue("svc_" + defaultHost.id, !current);
GM_notification({ text: `${defaultHost.name}: ${!current ? 'ENABLED' : 'DISABLED'}`, title: "F95 Grabber", timeout: 2000 });
} else {
let list = GM_getValue("custom_list_v2", []);
const idx = list.findIndex(i => i.domain === domain);
if (idx !== -1) { list.splice(idx, 1); } else { list.push({ domain: domain, enabled: true }); }
GM_setValue("custom_list_v2", list);
}
refreshAllButtons();
}
function createModal() {
if (document.getElementById('ug-modal-overlay')) return;
const overlay = document.createElement('div');
overlay.id = 'ug-modal-overlay';
const theme = GM_getValue("ug_theme", "dark");
let shortcut = GM_getValue("hotkey_v3", { alt: true, code: "KeyQ", display: "ALT + Q" });
const renderHosts = () => DEFAULT_HOSTS.map(h => `
<div class="ug-list-item">
<span class="ug-domain-text">${h.name}</span>
<label class="ug-toggle-label">
<input type="checkbox" class="cfg-host-live" data-id="${h.id}" ${GM_getValue("svc_"+h.id, true) ? 'checked' : ''}>
<span class="ug-toggle-slider"></span>
</label>
</div>`).join('');
const renderCustom = () => GM_getValue("custom_list_v2", []).map((item, index) => `
<div class="ug-list-item">
<button class="ug-del-btn" data-index="${index}"><i class="fa-solid fa-trash-can"></i></button>
<span class="ug-domain-text ${item.enabled ? '' : 'ug-disabled'}">${item.domain}</span>
<label class="ug-toggle-label">
<input type="checkbox" class="cfg-custom-live" data-index="${index}" ${item.enabled ? 'checked' : ''}>
<span class="ug-toggle-slider"></span>
</label>
</div>`).join('');
overlay.innerHTML = `
<div class="ug-modal ug-${theme}">
<div class="ug-header">
<div><i class="fa-solid fa-gear"></i> F95 Grabber Settings</div>
<i id="ug-theme-icon" class="fa-solid ${theme === 'dark' ? 'fa-moon' : 'fa-sun'} ug-theme-toggle"></i>
</div>
<div class="ug-content">
<div class="ug-section">
<span class="ug-label">Automation</span>
<div class="ug-card">
<div class="ug-row">
<div class="ug-info">
<b>Send to JDownloader</b>
<span>Direct transfer to port 9666. If OFF, copies to clipboard.</span>
</div>
<label class="ug-toggle-label">
<input type="checkbox" id="cfg-jd-live" ${GM_getValue("jdEnabled", false) ? 'checked' : ''}>
<span class="ug-toggle-slider"></span>
</label>
</div>
</div>
</div>
<div class="ug-section">
<span class="ug-label">Interaction</span>
<div class="ug-card">
<div class="ug-row">
<div class="ug-info">
<b>Shortcut</b>
<span>Hover a link and press to toggle custom domain.</span>
</div>
<div id="jd-shortcut-text" class="ug-kbd">${shortcut.display}</div>
</div>
</div>
</div>
<div class="ug-section">
<span class="ug-label">Custom Domains</span>
<div class="ug-input-bar">
<input type="text" id="new-domain" class="ug-input" placeholder="Add domain (e.g. mega.nz)...">
<button id="add-domain" class="ug-add-btn"><i class="fa-solid fa-plus"></i></button>
</div>
<div id="custom-list-container">${renderCustom()}</div>
</div>
<div class="ug-section">
<span class="ug-label">Default File Hosts</span>
<div id="default-hosts-container">${renderHosts()}</div>
</div>
</div>
</div>`;
document.body.appendChild(overlay);
overlay.onclick = (e) => { if (e.target === overlay) overlay.remove(); };
document.getElementById('ug-theme-icon').onclick = function() {
const newT = GM_getValue("ug_theme", "dark") === 'dark' ? 'light' : 'dark';
GM_setValue('ug_theme', newT);
overlay.querySelector('.ug-modal').className = `ug-modal ug-${newT}`;
this.className = `fa-solid ${newT === 'dark' ? 'fa-moon' : 'fa-sun'} ug-theme-toggle`;
};
const shortcutBtn = document.getElementById('jd-shortcut-text');
shortcutBtn.onclick = () => {
shortcutBtn.textContent = "...";
shortcutBtn.style.color = "#fbbf24";
const recordHandler = (e) => {
if (["Control", "Alt", "Shift", "Meta"].includes(e.key)) return;
e.preventDefault();
const combo = { ctrl: e.ctrlKey, alt: e.altKey, shift: e.shiftKey, code: e.code, display: `${e.ctrlKey ? 'CTRL + ' : ''}${e.altKey ? 'ALT + ' : ''}${e.shiftKey ? 'SHIFT + ' : ''}${e.key.toUpperCase()}` };
GM_setValue("hotkey_v3", combo);
shortcutBtn.textContent = combo.display;
shortcutBtn.style.color = "";
window.removeEventListener('keydown', recordHandler, true);
};
window.addEventListener('keydown', recordHandler, true);
};
document.getElementById('cfg-jd-live').onchange = (e) => GM_setValue("jdEnabled", e.target.checked);
overlay.addEventListener('change', (e) => {
if (e.target.classList.contains('cfg-host-live')) {
GM_setValue("svc_" + e.target.dataset.id, e.target.checked);
refreshAllButtons();
}
if (e.target.classList.contains('cfg-custom-live')) {
let list = GM_getValue("custom_list_v2", []);
list[e.target.dataset.index].enabled = e.target.checked;
GM_setValue("custom_list_v2", list);
e.target.closest('.ug-list-item').querySelector('.ug-domain-text').classList.toggle('ug-disabled', !e.target.checked);
refreshAllButtons();
}
});
document.getElementById('add-domain').onclick = () => {
const input = document.getElementById('new-domain');
const d = getCleanDomain(input.value.trim().includes('://') ? input.value.trim() : 'http://' + input.value.trim());
if (d) {
let list = GM_getValue("custom_list_v2", []);
if (!list.find(i => i.domain === d)) {
list.push({ domain: d, enabled: true });
GM_setValue("custom_list_v2", list);
document.getElementById('custom-list-container').innerHTML = renderCustom();
input.value = "";
refreshAllButtons();
}
}
};
overlay.addEventListener('click', (e) => {
if (e.target.closest('.ug-del-btn')) {
const idx = e.target.closest('.ug-del-btn').dataset.index;
let list = GM_getValue("custom_list_v2", []);
list.splice(idx, 1);
GM_setValue("custom_list_v2", list);
document.getElementById('custom-list-container').innerHTML = renderCustom();
refreshAllButtons();
}
});
}
GM_registerMenuCommand("F95 Grabber Settings", createModal);
function handleFinalLink(link, btn) {
if (GM_getValue("jdEnabled", false)) {
GM_xmlhttpRequest({
method: "POST", url: `http://127.0.0.1:9666/flashgot`, data: "urls=" + encodeURIComponent(link),
headers: { "Content-Type": "application/x-www-form-urlencoded", "Origin": TM_ORIGIN, "Referer": TM_ORIGIN + "/" },
onload: () => flashSuccess(btn)
});
} else { GM_setClipboard(link); flashSuccess(btn); }
}
function flashSuccess(btn) {
const originalContent = btn.innerHTML;
btn.innerHTML = '<i class="fa-solid fa-check action-success"></i>';
setTimeout(() => { if(btn) btn.innerHTML = btn.dataset.originalIcon || originalContent; }, 1500);
}
function triggerCaptcha(anchor, btn, cb) {
btn.innerHTML = '<i class="fa-solid fa-circle-exclamation" style="color:#f1c40f;"></i>';
const w = window.open(anchor.href, "captcha", "width=600,height=800");
const t = setInterval(() => { if(w && w.closed){ clearInterval(t); btn.innerHTML = '<i class="fa-solid fa-spinner dlx-loading"></i>'; setTimeout(cb, 500); } }, 800);
}
function processMasked(anchor, btn, id) {
btn.innerHTML = '<i class="fa-solid fa-spinner dlx-loading"></i>';
const makeReq = () => {
GM_xmlhttpRequest({
method: "POST", url: anchor.href, headers: {"Content-Type": "application/x-www-form-urlencoded"}, data: "xhr=1&download=1",
onload: r => {
let data; try { data = JSON.parse(r.responseText); } catch(e) { triggerCaptcha(anchor, btn, makeReq); return; }
if(!data || !data.msg || /captcha|verify/i.test(data.msg)) { triggerCaptcha(anchor, btn, makeReq); return; }
let url = "";
if(id === "gofile") { let m = data.msg.match(/gofile\.io\/d\/([\w\d]+)/); if(m) url = BYPASS.GOFILE + m[1]; }
else if(id === "pixeldrain") { let m = data.msg.match(/pixeldrain\.com\/u\/([\w\d]+)/); if(m) url = BYPASS.PIXEL + m[1]; }
else { let m = data.msg.match(/href="([^"]+)"/i) || data.msg.match(/(https?:\/\/[^\s<>"]+)/i); if(m) url = m[1]; }
if(url) {
btn.href = url;
btn.dataset.originalIcon = '<i class="fa-solid fa-copy"></i>';
btn.dataset.bypassed = "true";
handleFinalLink(url, btn);
} else btn.innerHTML = '<i class="fa-solid fa-skull" style="color:#888;"></i>';
}
});
};
makeReq();
}
function findLinks() {
const active = [...DEFAULT_HOSTS.filter(h => GM_getValue("svc_"+h.id, true)), ...GM_getValue("custom_list_v2", []).filter(i => i.enabled).map(i => ({ id: "custom", pattern: i.domain }))];
active.forEach(host => {
const links = document.querySelectorAll(`a[href*="${host.pattern}"]:not(.dlx):not(.dlx-p)`);
links.forEach(a => {
a.classList.add('dlx-p');
const btn = document.createElement("a");
btn.className = "dlx"; btn.href = a.href;
const isMasked = a.href.includes('/masked/');
const iconHTML = isMasked ? '<i class="fa-solid fa-arrows-rotate"></i>' : '<i class="fa-solid fa-copy"></i>';
btn.innerHTML = iconHTML; btn.dataset.originalIcon = iconHTML;
btn.onclick = (e) => { e.preventDefault(); e.stopPropagation(); if(isMasked && !btn.dataset.bypassed) processMasked(a, btn, host.id); else handleFinalLink(btn.href, btn); };
a.insertAdjacentElement("afterend", btn);
});
});
}
let hovered = null;
document.addEventListener('mouseover', e => hovered = e.target.closest('a'));
window.addEventListener('keydown', e => {
const hk = GM_getValue("hotkey_v3", { alt: true, code: "KeyQ" });
if (e.code === hk.code && e.ctrlKey === !!hk.ctrl && e.altKey === !!hk.alt && e.shiftKey === !!hk.shift && hovered) {
e.preventDefault();
const d = getCleanDomain(hovered.href);
if(d) toggleHost(d);
}
});
findLinks();
const observer = new MutationObserver(() => findLinks());
observer.observe(document.body, {childList: true, subtree: true});
})();