// ==UserScript==
// @name PixelDrain Bypass (DL-L-D-Folder combined)
// @namespace jAstn
// @author It's a Me, jAstn!
// @version 5.3
// @description Combined Pixeldrain bypass: /u/ download-button bypass, /l/ gallery bypass links, /d/ folder bypass links.
// @match https://pixeldrain.com/u/*
// @match https://pixeldrain.com/l/*
// @match https://pixeldrain.com/d/*
// @grant GM_openInTab
// @grant GM_setClipboard
// @grant GM_registerMenuCommand
// @icon https://pixeldrain.com/favicon.ico
// @run-at document-end
// ==/UserScript==
// CHANGELOG:
// v5.3:
// - SPA navigation watcher: pushState/replaceState interceptor instead of 500 ms polling -> responds immediately
// v5.2:
// - Automatically switches between folder and file views without reloading (Download <-> Download (Bypassed))
// - replaceNativeDownloadButtons is now active only on /u/ and /d/ file pages (guarded by isFilePage)
// - Body classes 'd-folder'/'dl-d-folder' are set during /d/ navigation(for optional CSS rules)
// - cleanupUI removes old buttons/popups during navigation and prevents duplicates
// v5.1:
// - Download button bypass (U-module) is now active only on /u/ and /d/ file pages (.mp4, etc.), not on /l/ or /d/ folder pages
// - Added a new 'dir-file' branch: on /d/ file pages, the button builds the /api/filesystem/{folderId}/{path} URL instead of /api/file/
// - D-module (Show Bypass Links) runs only on folder overview pages
// v5.0:
// - Combined from: PixelDrain U-Folder v1.0.2, L-Folder v4.3, and D-Folder v4.3
// - Added one @match block (/u/*, /l/*, /d/*), combined grants,unique IDs, and unique identifiers
(function () {
'use strict';
/* ═══════════════════════════════════════════════════════════
Shared constants
═══════════════════════════════════════════════════════════ */
const PIXELDRAIN_VIEW = 'https://pixeldrain.com/u/';
const FILE_ID_REGEX = /\/api\/file\/(\w+)\//;
const API_KEY = ''; // <--- SET YOUR API KEY HERE
const PREFERRED_PROXY = 'https://cdn01.pixeldrain.eu.cc/'; // U
const PIXELDRAIN_BYPASS = 'https://cdn01.pixeldrain.eu.cc/api/file/'; // L
const PIXELDRAIN_BYPASS_FS = 'https://cdn01.pixeldrain.eu.cc/api/filesystem/'; // D
// File pages under /d/ (U-module active, download button is replaced)
const FILE_EXT_REGEX = /\.(mp4|mkv|webm|avi|mov|mp3|zip|rar|7z|pdf)$/i;
if (!API_KEY) {
console.warn('[Pixeldrain Bypass] API key is missing — file sizes will show as N/A.');
}
function openBypassInNewTab(url) {
GM_openInTab(url, {
active: true, // set to false if you want background tabs
insert: true
});
}
// A /d/ page with a file at the end (for example .../Videos/file.mp4),
function isDFilePage() {
return location.pathname.startsWith('/d/') && FILE_EXT_REGEX.test(location.pathname);
}
/* ═══════════════════════════════════════════════════════════
U-Modul: Download-Button-Bypass (/u/ und /d/-Datei-Seiten)
═══════════════════════════════════════════════════════════ */
const DEFAULT_PROXIES = [
'https://pixeldrain-bypass.gamedrive.org/api/file/',
'https://pixeldrainbypass.org/api/file/',
'https://cdn.pixeldrain.eu.cc/api/file/'
];
const PROXY_JSON_URL = 'https://pixeldrain-bypass.gamedrive.org/api/proxy.json';
const PROXY_LIST_KEY = 'pd_proxy_list_v5';
const PROXY_TS_KEY = 'pd_proxy_list_ts_v5';
const CACHE_TTL_MS = 12 * 60 * 60 * 1000;
let uObserver = null;
function nowMs() {
return Date.now();
}
function normalizeProxy(entry) {
if (!entry || typeof entry !== 'string') return null;
let url = entry.trim();
if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
return url.endsWith('/') ? url : url + '/';
}
async function fetchProxyPool() {
const ts = parseInt(localStorage.getItem(PROXY_TS_KEY) || '0', 10);
const cached = localStorage.getItem(PROXY_LIST_KEY);
if (cached && (nowMs() - ts) < CACHE_TTL_MS) {
try {
const parsed = JSON.parse(cached);
if (Array.isArray(parsed) && parsed.length) return parsed;
} catch (e) { }
}
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 2000);
const response = await fetch(PROXY_JSON_URL, { cache: 'no-store', signal: controller.signal });
clearTimeout(timeoutId);
if (response.ok) {
const data = await response.json();
let rawList = [];
if (data && Array.isArray(data.proxies)) rawList = data.proxies;
else if (data && typeof data.proxy === 'string') rawList = [data.proxy];
else if (Array.isArray(data)) rawList = data;
const normalized = rawList.map(normalizeProxy).filter(Boolean);
if (normalized.length) {
localStorage.setItem(PROXY_LIST_KEY, JSON.stringify(normalized));
localStorage.setItem(PROXY_TS_KEY, String(nowMs()));
return normalized;
}
}
} catch (e) {
if (cached) {
try {
const parsed = JSON.parse(cached);
if (Array.isArray(parsed) && parsed.length) return parsed;
} catch (err) { }
}
}
return DEFAULT_PROXIES;
}
async function getRandomProxyNode() {
return PREFERRED_PROXY;
}
function readInitialNode() {
try {
if (window.initial_node && typeof window.initial_node === 'object') {
return window.initial_node;
}
} catch (e) { }
const scripts = document.querySelectorAll('script');
for (const s of scripts) {
const text = s.textContent || '';
const idx = text.indexOf('window.initial_node =');
if (idx !== -1) {
try {
const jsonSegment = text.slice(idx + 'window.initial_node ='.length).split(';')[0];
return JSON.parse(jsonSegment.trim());
} catch (e) { }
}
}
return null;
}
function countValidFiles() {
const init = readInitialNode();
if (!init) return 0;
if (Array.isArray(init.path) && init.path.length > 0 && init.path[0].type === 'file') {
if (!Array.isArray(init.children) || init.children.length === 0) return 1;
}
if (Array.isArray(init.children)) {
return init.children.filter(c => c && c.type === 'file' && c.name !== '.search_index.gz').length;
}
return 0;
}
async function buildBypassEndpoints(type) {
const proxyBase = await getRandomProxyNode();
if (!proxyBase) return null;
const currentUrl = window.location.href;
if (type === 'file') {
const fileId = currentUrl.replace(`${location.origin}/u/`, '').split('/')[0].split('?')[0];
return proxyBase + 'api/file/' + fileId;
}
if (type === 'dir-file') {
// /d/{folderId}/{relativePath} -> /api/filesystem/{folderId}/{relativePath}
const m = location.pathname.match(/^\/d\/([^\/]+)\/(.+)$/);
if (!m) return null;
const folderId = m[1];
const relPath = safeDecode(m[2]); // For example: "Videos/8thStreet...mp4"
const encodedPath = relPath.split('/').map(seg => encodeURIComponent(seg)).join('/');
return `${PIXELDRAIN_BYPASS_FS}${folderId}/${encodedPath}`;
}
if (type === 'gallery') {
const links = document.querySelectorAll('a.file');
const urlList = [];
const urlNames = [];
links.forEach(link => {
const childDiv = link.querySelector('div');
const bg = childDiv ? childDiv.style.backgroundImage : '';
const match = bg.match(FILE_ID_REGEX);
if (match && match[1]) {
urlList.push(proxyBase + match[1]);
urlNames.push((link.textContent || '').trim());
}
});
return { urlList, urlNames };
}
if (type === 'dir') {
const init = readInitialNode();
if (!init) return { urlList: [], urlNames: [], dirId: null };
let dirId = (Array.isArray(init.path) && init.path[0]) ? init.path[0].id : null;
if (!dirId) {
const match = window.location.pathname.match(/\/d\/([^\/\?#]+)/);
if (match) dirId = match[1];
}
const files = Array.isArray(init.children) ? init.children.filter(c => c && c.type === 'file') : [];
const urlList = [];
const urlNames = [];
for (const f of files) {
if (!f || !f.name || f.name === '.search_index.gz') continue;
const encoded = encodeURIComponent(f.name).replace(/%2F/g, '/');
urlList.push(`${proxyBase}d/${dirId || ''}/${encoded}`);
urlNames.push(f.name);
}
return { urlList, urlNames, dirId };
}
if (type === 'dir-single') {
const match = window.location.pathname.match(/\/d\/([^\/\?#]+)/);
return match ? `${proxyBase}ds/${match[1]}` : null;
}
return null;
}
function openTab(url) {
if (!url) return;
if (typeof GM_openInTab === 'function') {
GM_openInTab(url, { active: true, insert: true });
} else {
window.open(url, '_blank');
}
}
async function executeDirectBypass() {
const currentUrl = window.location.href;
if (currentUrl.includes('/u/')) {
const target = await buildBypassEndpoints('file');
if (target) openTab(target);
} else if (isDFilePage()) {
const target = await buildBypassEndpoints('dir-file');
if (target) openTab(target);
} else if (currentUrl.includes('/d/')) {
if (countValidFiles() === 1) {
const target = await buildBypassEndpoints('dir-single');
if (target) openTab(target);
} else {
const data = await buildBypassEndpoints('dir');
if (data && data.urlList) {
for (const link of data.urlList) {
openTab(link);
await new Promise(r => setTimeout(r, 150));
}
}
}
}
}
function injectStyles() {
if (document.getElementById('pd-bypass-styles')) return;
const path = window.location.pathname;
if (path.startsWith('/d/') && path.endsWith('.mp4')) document.body.classList.add('dl-d-folder');
else if (path.startsWith('/d/')) document.body.classList.add('d-folder');
const style = document.createElement('style');
style.id = 'pd-bypass-styles';
style.textContent = `
.file_preview .block.center,
div[class*="block"][class*="center"],
.progress_bar_outer,
div[class*="progress_bar_outer"] {
display: none !important;
visibility: hidden !important;
}
.pd-modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(15, 17, 23, 0.75);
backdrop-filter: blur(4px);
z-index: 2147483646;
display: flex;
align-items: center;
justify-content: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.pd-modal-card {
background: #1e222b;
border: 1px solid #3b4252;
border-radius: 10px;
width: 90%;
max-width: 620px;
max-height: 80vh;
padding: 20px;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
gap: 16px;
color: #eceff4;
position: relative;
}
.pd-modal-close {
position: absolute;
top: 14px;
right: 18px;
font-size: 20px;
cursor: pointer;
color: #4c566a;
transition: color 0.15s ease;
}
.pd-modal-close:hover {
color: #bf616a;
}
.pd-modal-list {
max-height: 50vh;
overflow-y: auto;
background: #171a21;
border: 1px solid #2e3440;
border-radius: 6px;
padding: 12px;
display: flex;
flex-direction: column;
gap: 8px;
}
.pd-modal-link {
color: #88c0d0;
font-size: 12px;
word-break: break-all;
text-decoration: none;
padding: 6px;
border-radius: 4px;
background: rgba(136, 192, 208, 0.05);
transition: background 0.15s ease;
}
.pd-modal-link:hover {
background: rgba(136, 192, 208, 0.15);
}
.pd-export-btn {
margin-left: 8px !important;
background-color: #4c566a !important;
color: #eceff4 !important;
}
/* Body-Klassen für /d/-Ansichten (vom URL-Watcher gesetzt) */
body.dl-d-folder .grid.svelte-1nlv5t7 > button:nth-child(3) {
display: flex !important;
}
body.d-folder .grid.svelte-1nlv5t7 > button:nth-child(3) {
display: none;
}
`;
(document.head || document.documentElement).appendChild(style);
}
function hideTargetElements() {
const bannerTarget = document.querySelector("#body > div > div.file_preview_row.svelte-jngqwx > div.file_preview.svelte-jngqwx.checkers.toolbar_visible > div.block.svelte-1j18l4r.center") || document.querySelector(".file_preview .block.center");
if (bannerTarget) {
bannerTarget.style.display = 'non2e';
}
const progressBarTarget = document.querySelector("#body > div > div.progress_bar_outer.svelte-wn2jie") || document.querySelector(".progress_bar_outer");
if (progressBarTarget) {
progressBarTarget.style.display = 'none';
}
}
async function displayLinksModal() {
injectStyles();
let overlay = document.getElementById('pd-modal-overlay');
if (overlay) overlay.remove();
overlay = document.createElement('div');
overlay.id = 'pd-modal-overlay';
overlay.className = 'pd-modal-overlay';
const card = document.createElement('div');
card.className = 'pd-modal-card';
const closeBtn = document.createElement('span');
closeBtn.className = 'pd-modal-close';
closeBtn.innerHTML = '×';
closeBtn.onclick = () => overlay.remove();
// const modalTitle = document.createElement('div');
// modalTitle.style.cssText = 'font-size: 14px; font-weight: bold; color: #88c0d0; text-transform: uppercase;';
// modalTitle.textContent = 'Bypass Export Links (Credits: Boring Otaku)';
const currentUrl = window.location.href;
let links = [];
if (currentUrl.includes('/u/')) {
const url = await buildBypassEndpoints('file');
if (url) links = [url];
} else if (isDFilePage()) {
const url = await buildBypassEndpoints('dir-file');
if (url) links = [url];
} else if (currentUrl.includes('/l/')) {
const data = await buildBypassEndpoints('gallery');
if (data) links = data.urlList || [];
} else if (currentUrl.includes('/d/')) {
if (countValidFiles() === 1) {
const url = await buildBypassEndpoints('dir-single');
if (url) links = [url];
} else {
const data = await buildBypassEndpoints('dir');
if (data) links = data.urlList || [];
}
}
const listContainer = document.createElement('div');
listContainer.className = 'pd-modal-list';
if (links.length === 0) {
const emptyMsg = document.createElement('div');
emptyMsg.style.cssText = 'color: #d8dee9; font-size: 12px; text-align: center; padding: 10px;';
emptyMsg.textContent = 'No bypass links found for this target.';
listContainer.appendChild(emptyMsg);
} else {
links.forEach(l => {
const a = document.createElement('a');
a.href = l;
a.textContent = l;
a.className = 'pd-modal-link';
a.target = '_blank';
listContainer.appendChild(a);
});
}
const actions = document.createElement('div');
actions.style.cssText = 'display: flex; justify-content: flex-end; gap: 10px;';
const copyBtn = document.createElement('button');
copyBtn.style.cssText = 'padding: 8px 16px; font-size: 12px; font-weight: 600; background: #a3be8c; color: #2e3440; border: none; border-radius: 6px; cursor: pointer;';
copyBtn.textContent = 'Copy All Links';
copyBtn.onclick = () => {
if (typeof GM_setClipboard === 'function') {
GM_setClipboard(links.join('\n'));
} else {
navigator.clipboard.writeText(links.join('\n'));
}
copyBtn.textContent = 'Copied';
setTimeout(() => { copyBtn.textContent = 'Copy All Links'; }, 1500);
};
actions.appendChild(copyBtn);
card.appendChild(closeBtn);
// card.appendChild(modalTitle);
card.appendChild(listContainer);
card.appendChild(actions);
overlay.appendChild(card);
document.body.appendChild(overlay);
}
function replaceNativeDownloadButtons() {
injectStyles();
hideTargetElements();
// Nur auf /u/ und /d/-Datei-Seiten aktiv (Ordner-/Galerie-Seiten unangetastet)
if (!isFilePage()) return;
const targets = document.querySelectorAll('a[href*="/api/file/"], button, .button');
targets.forEach(el => {
const text = (el.textContent || '').trim().toLowerCase();
if (text.includes('download') && !el.dataset.pdHijacked) {
el.dataset.pdHijacked = 'true';
if (el.tagName === 'A') {
el.removeAttribute('href');
el.style.cursor = 'pointer';
}
const labelSpan = el.querySelector('span') || el;
labelSpan.textContent = 'Download (Bypassed)';
el.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
executeDirectBypass();
}, true);
if (!document.getElementById('pd-export-btn') && el.parentElement) {
if (uObserver) uObserver.disconnect();
const exportBtn = el.cloneNode(true);
exportBtn.id = 'pd-export-btn';
exportBtn.classList.add('pd-export-btn');
const exportSpan = exportBtn.querySelector('span') || exportBtn;
exportSpan.textContent = 'Export Links';
exportBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
displayLinksModal();
}, true);
el.parentElement.appendChild(exportBtn);
if (uObserver) {
uObserver.observe(document.body, { childList: true, subtree: true });
}
}
}
});
}
function initUBypass() {
replaceNativeDownloadButtons();
uObserver = new MutationObserver(() => {
replaceNativeDownloadButtons();
});
uObserver.observe(document.body, { childList: true, subtree: true });
}
/* ═══════════════════════════════════════════════════════════
L-module: Gallery bypass (/l/, /u/)
═══════════════════════════════════════════════════════════ */
let lObserver = null;
function extractGalleryFileName(link) {
const clone = link.cloneNode(true);
clone.querySelectorAll('.icon_container, p.filesize').forEach(el => el.remove());
const name = clone.textContent.replace(/\s+/g, ' ').trim();
return name.length ? name : 'Unknown';
}
function enhanceGalleryLinks() {
const galleryDivs = Array.from(document.querySelectorAll('div[class^="gallery"]'));
galleryDivs.forEach(div => {
const links = div.querySelectorAll('a[class^="file"]');
links.forEach(link => {
link.style.width = "275px";
link.style.height = "220px";
const icon = link.querySelector('.icon_container');
if (!icon) return;
const bgImage = icon.style.backgroundImage;
const match = bgImage.match(FILE_ID_REGEX);
if (match && match[1]) {
const fileID = match[1];
link.href = PIXELDRAIN_VIEW + fileID;
link.target = '_blank';
}
});
});
}
function getBypassUrls(type) {
const currentUrl = window.location.href;
if (type === "file") {
const fileID = currentUrl.replace(`${location.origin}/u/`, "");
return PIXELDRAIN_BYPASS + fileID;
}
if (type === "gallery") {
const links = document.querySelectorAll('a.file');
const combined = [];
links.forEach(link => {
const icon = link.querySelector('div.icon_container');
const bgImage = icon?.style?.backgroundImage;
const match = bgImage?.match(FILE_ID_REGEX);
if (match && match[1]) {
const fileID = match[1];
const name = extractGalleryFileName(link);
const url = PIXELDRAIN_BYPASS + fileID;
combined.push({ name, url, fileID });
}
});
return combined;
}
}
function startDownload(link) {
const a = document.createElement("a");
a.href = link;
a.download = '';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
function handleBypassDownload() {
const currentUrl = window.location.href;
if (currentUrl.includes(`${location.origin}/u/`)) {
openBypassInNewTab(getBypassUrls("file"));
}
if (currentUrl.includes(`${location.origin}/l/`)) {
getBypassUrls("gallery")
.forEach(({ url }) => openBypassInNewTab(url));
}
}
async function fetchFileSize(fileID) {
try {
const res = await fetch(`https://pixeldrain.com/api/file/${fileID}/info`, {
headers: {
'Authorization': `Basic ${btoa(":" + API_KEY)}`
}
});
const json = await res.json();
if (json.size) {
const size = parseInt(json.size, 10);
return formatBytes(size);
}
} catch (e) {
console.warn("Failed to fetch file size", fileID, e);
}
return 'N/A';
}
function formatBytes(bytes) {
if (!bytes || bytes === 0) return '0 B';
if (bytes >= 1024 * 1024 * 1024) return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
if (bytes >= 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
if (bytes >= 1024) return (bytes / 1024).toFixed(2) + ' KB';
return bytes.toFixed(0) + ' B';
}
function handleShowBypassLinks() {
const popupBox = document.getElementById('popupBox');
popupBox.innerHTML = '';
const headerContainer = document.createElement('div');
headerContainer.style.position = 'sticky';
headerContainer.style.top = '0';
headerContainer.style.background = '#2f3541';
headerContainer.style.zIndex = '1001';
headerContainer.style.padding = '10px 10px 0 10px';
headerContainer.style.borderBottom = '1px solid #555';
headerContainer.style.display = 'flex';
headerContainer.style.justifyContent = 'flex-end';
const popupClose = document.createElement('span');
popupClose.innerHTML = '×';
popupClose.style.cursor = 'pointer';
popupClose.style.fontSize = '24px';
popupClose.style.flexShrink = '0';
popupClose.onclick = () => (popupBox.style.display = 'none');
headerContainer.appendChild(popupClose);
popupBox.appendChild(headerContainer);
const currentUrl = window.location.href;
let combined;
if (currentUrl.includes(`${location.origin}/u/`)) {
const fileID = currentUrl.replace(`${location.origin}/u/`, "");
const url = PIXELDRAIN_BYPASS + fileID;
let name = 'Unknown';
const headerTitle = document.querySelector('.file_viewer_headerbar_title');
if (headerTitle && headerTitle.textContent.trim().length > 0) {
name = headerTitle.textContent.trim();
}
if (name === 'Unknown') {
const fallback = document.querySelector('.name, .file_name, .filename, h1');
if (fallback && fallback.textContent.trim().length > 0) {
name = fallback.textContent.trim();
}
}
if (name === 'Unknown' && document.title) {
name = document.title.replace(' - Pixeldrain', '').trim();
}
combined = [{ name, url, fileID }];
} else if (currentUrl.includes(`${location.origin}/l/`)) {
combined = getBypassUrls("gallery").sort((a, b) => a.name.trim().localeCompare(b.name.trim()));
}
const table = document.createElement('table');
table.style.width = '100%';
table.style.borderCollapse = 'collapse';
table.style.tableLayout = 'fixed';
table.style.color = '#d7dde8';
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
const headers = ['Filename', 'Size', 'Bypass Link'];
const widths = ['55%', '15%', '30%'];
let sortDirection = { column: 'Filename', asc: true };
headers.forEach((text, i) => {
const th = document.createElement('th');
th.textContent = text;
th.style.width = widths[i];
th.style.padding = '6px';
th.style.borderBottom = '2px solid #ccc';
th.style.textAlign = 'left';
th.style.cursor = 'pointer';
th.onclick = () => {
if (text === 'Filename') {
sortDirection = {
column: 'Filename',
asc: sortDirection.column !== 'Filename' || !sortDirection.asc
};
rowRefs.sort((a, b) =>
sortDirection.asc
? a.name.localeCompare(b.name)
: b.name.localeCompare(a.name)
);
renderRows();
} else if (text === 'Size') {
if (!rowRefs.every(r => r.size !== null)) return;
sortDirection = {
column: 'Size',
asc: sortDirection.column !== 'Size' || !sortDirection.asc
};
rowRefs.sort((a, b) =>
sortDirection.asc ? a.size - b.size : b.size - a.size
);
renderRows();
}
};
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
const tbodyContainer = document.createElement('div');
tbodyContainer.style.overflowY = 'auto';
tbodyContainer.style.maxHeight = 'calc(80vh - 100px)';
tbodyContainer.style.borderTop = '1px solid #555';
const tbodyTable = document.createElement('table');
tbodyTable.style.width = '100%';
tbodyTable.style.borderCollapse = 'collapse';
tbodyTable.style.tableLayout = 'fixed';
tbodyTable.style.color = '#d7dde8';
const tbody = document.createElement('tbody');
tbodyTable.appendChild(tbody);
tbodyContainer.appendChild(tbodyTable);
const rowRefs = combined.map(({ name, url, fileID }) => ({
name,
url,
fileID,
size: null,
tr: document.createElement('tr'),
tdSize: document.createElement('td'),
}));
function renderRows() {
tbody.innerHTML = '';
for (const row of rowRefs) {
const { name, url, fileID, size, tr, tdSize } = row;
tr.innerHTML = '';
const tdName = document.createElement('td');
const textName = document.createElement('text');
textName.href = '#';
textName.textContent = name;
textName.style.color = '#d7dde8';
tdName.appendChild(textName);
tdName.style.padding = '6px';
tdName.style.borderBottom = '1px solid #555';
tdName.style.wordBreak = 'break-word';
tdName.style.width = widths[0];
tdSize.textContent = size !== null ? formatBytes(size) : '...';
tdSize.style.padding = '6px';
tdSize.style.borderBottom = '1px solid #555';
tdSize.style.color = '#ccc';
tdSize.style.width = widths[1];
const tdLink = document.createElement('td');
const a = document.createElement('a');
a.href = url;
a.textContent = url;
a.style.color = '#8ec7ff';
a.addEventListener('click', (e) => {
e.preventDefault();
openBypassInNewTab(url);
});
tdLink.appendChild(a);
tdLink.style.padding = '6px';
tdLink.style.borderBottom = '1px solid #555';
tdLink.style.wordBreak = 'break-word';
tdLink.style.width = widths[2];
tr.appendChild(tdName);
tr.appendChild(tdSize);
tr.appendChild(tdLink);
tbody.appendChild(tr);
}
}
renderRows();
popupBox.appendChild(table);
popupBox.appendChild(tbodyContainer);
const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex';
buttonContainer.style.justifyContent = 'center';
buttonContainer.style.marginTop = '15px';
buttonContainer.style.gap = '10px';
const copyBtn = document.createElement("button");
copyBtn.textContent = '🔗 Copy URLs';
copyBtn.onclick = () => {
const combinedText = rowRefs.map(({ name, url }) => `${name}: ${url}`).join('\n');
navigator.clipboard.writeText(combinedText).then(() => {
copyBtn.textContent = "✔️ Copied";
setTimeout(() => copyBtn.textContent = '🔗 Copy URLs', 2500);
});
};
const saveBtn = document.createElement("button");
saveBtn.textContent = '📄 Save as Text File';
saveBtn.onclick = () => {
const fileIdMatch = currentUrl.match(/\/l\/([^/#?]+)/);
if (fileIdMatch && fileIdMatch[1]) {
const fileName = fileIdMatch[1] + '.txt';
const content = rowRefs.map(({ name, url }) => `${name}: ${url}`).join('\n');
const blob = new Blob([content], { type: 'text/plain' });
const urlBlob = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = urlBlob;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(urlBlob);
}
};
buttonContainer.appendChild(copyBtn);
buttonContainer.appendChild(saveBtn);
popupBox.appendChild(buttonContainer);
(async () => {
if (!API_KEY) {
for (const row of rowRefs) {
row.size = 0;
row.tdSize.textContent = 'N/A';
}
} else {
for (const row of rowRefs) {
try {
const res = await fetch(`https://pixeldrain.com/api/file/${row.fileID}/info`, {
headers: {
'Authorization': `Basic ${btoa(":" + API_KEY)}`
}
});
const json = await res.json();
if (json.size) {
row.size = parseInt(json.size, 10);
row.tdSize.textContent = formatBytes(row.size);
} else {
row.size = 0;
row.tdSize.textContent = 'N/A';
}
} catch (e) {
row.size = 0;
row.tdSize.textContent = 'N/A';
console.warn('Failed to fetch size for', row.fileID, e);
}
}
sortDirection = { column: 'Size', asc: false };
rowRefs.sort((a, b) => b.size - a.size);
renderRows();
}
})();
popupBox.style.display = 'block';
}
function addBypassButtons() {
const linksButton = document.createElement("button");
linksButton.innerHTML = `linkShow Bypass Links`;
linksButton.addEventListener('click', handleShowBypassLinks);
const popupBox = document.createElement("div");
popupBox.id = 'popupBox';
popupBox.style.display = 'none';
popupBox.style.position = 'fixed';
popupBox.style.top = '50%';
popupBox.style.left = '50%';
popupBox.style.transform = 'translate(-50%, -50%)';
popupBox.style.padding = '20px';
popupBox.style.background = '#2f3541';
popupBox.style.border = '2px solid #a4be8c';
popupBox.style.color = '#d7dde8';
popupBox.style.borderRadius = '10px';
popupBox.style.width = '70%';
popupBox.style.height = '90%';
popupBox.style.zIndex = 9999;
popupBox.style.overflowY = 'auto';
document.body.appendChild(popupBox);
const labels = document.querySelectorAll('div.label');
labels.forEach(label => {
if (label.textContent.trim() === 'Size') {
const target = label.nextElementSibling;
if (target) {
target.insertAdjacentElement('afterend', linksButton);
}
}
});
}
function waitForGalleryAndEnhance() {
const check = setInterval(() => {
const gallery = document.querySelector('div[class^="gallery"]');
if (gallery && gallery.querySelector('a[class^="file"]')) {
clearInterval(check);
enhanceGalleryLinks();
}
}, 500);
}
function initLGallery() {
waitForGalleryAndEnhance();
addBypassButtons();
lObserver = new MutationObserver(enhanceGalleryLinks);
lObserver.observe(document.body, { childList: true, subtree: true });
}
/* ═══════════════════════════════════════════════════════════
D-module: Folder bypass (/d/ folder overview)
═══════════════════════════════════════════════════════════ */
let dPopupBox = null;
function getFolderId() {
const match = window.location.pathname.match(/^\/d\/([^\/]+)/);
return match ? match[1] : null;
}
function safeDecode(str) {
try { return decodeURIComponent(str); } catch (e) { return str; }
}
function buildBypassUrl(folderId, relPath) {
const encodedPath = relPath.split('/').map(seg => encodeURIComponent(seg)).join('/');
return `${PIXELDRAIN_BYPASS_FS}${folderId}/${encodedPath}`;
}
function getFileList() {
const folderId = getFolderId();
if (!folderId) return [];
const nodes = Array.from(document.querySelectorAll(`a[href^="/d/${folderId}/"]`));
return nodes.map(a => {
const href = a.getAttribute('href');
const relPath = safeDecode(href.replace(`/d/${folderId}/`, ''));
const fileName = relPath.split('/').pop();
return {
name: fileName,
url: buildBypassUrl(folderId, relPath),
};
});
}
function showBypassLinksD() {
if (!dPopupBox) {
dPopupBox = document.createElement('div');
Object.assign(dPopupBox.style, {
position: 'fixed',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
padding: '20px',
background: '#2f3541',
border: '2px solid #a4be8c',
color: '#d7dde8',
borderRadius: '10px',
width: '70%',
height: '80%',
zIndex: 999999,
overflowY: 'auto',
fontSize: '18px',
});
document.body.appendChild(dPopupBox);
}
dPopupBox.innerHTML = '';
const header = document.createElement('div');
Object.assign(header.style, {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
borderBottom: '1px solid #555',
paddingBottom: '8px',
marginBottom: '10px',
});
const title = document.createElement('div');
title.textContent = 'Pixeldrain Bypass Links';
title.style.fontSize = '18px';
title.style.fontWeight = 'bold';
header.appendChild(title);
const closeBtn = document.createElement('button');
closeBtn.textContent = '×';
Object.assign(closeBtn.style, {
fontSize: '24px',
lineHeight: '20px',
background: 'none',
border: 'none',
color: '#d7dde8',
cursor: 'pointer',
});
closeBtn.onclick = () => (dPopupBox.style.display = 'none');
header.appendChild(closeBtn);
dPopupBox.appendChild(header);
const files = getFileList();
if (files.length === 0) {
const msg = document.createElement('div');
msg.textContent = 'No files found in this folder.';
dPopupBox.appendChild(msg);
dPopupBox.style.display = 'block';
return;
}
const table = document.createElement('table');
Object.assign(table.style, {
width: '100%',
borderCollapse: 'collapse',
color: '#d7dde8',
});
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
const colFile = document.createElement('th');
colFile.textContent = 'Filename';
Object.assign(colFile.style, {
padding: '8px',
borderBottom: '2px solid #555',
width: '50%',
textAlign: 'left',
});
headerRow.appendChild(colFile);
const colLink = document.createElement('th');
colLink.textContent = 'Download Link';
Object.assign(colLink.style, {
padding: '8px',
borderBottom: '2px solid #555',
width: '50%',
textAlign: 'left',
});
headerRow.appendChild(colLink);
thead.appendChild(headerRow);
table.appendChild(thead);
const tbody = document.createElement('tbody');
for (const file of files) {
const tr = document.createElement('tr');
const tdName = document.createElement('td');
tdName.textContent = file.name;
Object.assign(tdName.style, {
padding: '6px',
borderBottom: '1px solid #444',
wordBreak: 'break-word',
});
tr.appendChild(tdName);
const tdLink = document.createElement('td');
const a = document.createElement('a');
a.href = file.url;
a.textContent = 'Download';
a.style.color = '#8ec7ff';
a.addEventListener('click', (e) => {
e.preventDefault();
openBypassInNewTab(file.url);
});
tdLink.appendChild(a);
Object.assign(tdLink.style, {
padding: '6px',
borderBottom: '1px solid #444',
wordBreak: 'break-word',
});
tr.appendChild(tdLink);
tbody.appendChild(tr);
}
table.appendChild(tbody);
dPopupBox.appendChild(table);
dPopupBox.style.display = 'block';
}
function addShowBypassButton() {
const toolbar = Array.from(document.querySelectorAll('div')).find(div => {
if (!div.children) return false;
const labels = div.querySelectorAll('div.label');
if (labels.length < 3) return false;
const labelTexts = Array.from(labels).map(l => l.textContent.trim().toLowerCase());
return labelTexts.includes('directories') && labelTexts.includes('files') && labelTexts.includes('total size');
});
if (!toolbar) return false;
const gridDiv = toolbar.querySelector('div.grid');
if (!gridDiv) return false;
if (document.getElementById('bypassButtonContainer')) return true;
const buttonContainer = document.createElement('div');
buttonContainer.id = 'bypassButtonContainer';
buttonContainer.style.display = 'flex';
buttonContainer.style.justifyContent = 'center';
buttonContainer.style.marginTop = '15px';
buttonContainer.style.gap = '10px';
const btn = document.createElement('button');
btn.textContent = 'Show Bypass Links';
btn.title = 'Show direct bypass download links for all files in this folder';
Object.assign(btn.style, {
cursor: 'pointer',
padding: '12px 30px',
fontSize: '16px',
fontWeight: '600',
borderRadius: '6px',
backgroundColor: '#4a90e2',
color: 'white',
border: 'none',
boxShadow: '0 3px 6px rgba(0,0,0,0.2)',
transition: 'background-color 0.3s ease',
minWidth: '160px',
minHeight: '40px',
});
btn.addEventListener('mouseenter', () => btn.style.backgroundColor = '#357ABD');
btn.addEventListener('mouseleave', () => btn.style.backgroundColor = '#4a90e2');
btn.addEventListener('click', showBypassLinksD);
buttonContainer.appendChild(btn);
gridDiv.appendChild(buttonContainer);
return true;
}
function initObserverD() {
const observer = new MutationObserver(() => {
const added = addShowBypassButton();
if (added) observer.disconnect();
});
observer.observe(document.body, { childList: true, subtree: true });
}
function waitForReadyD() {
const intervalId = setInterval(() => {
const added = addShowBypassButton();
if (added) clearInterval(intervalId);
}, 500);
}
function initDFolder() {
initObserverD();
waitForReadyD();
}
/* ═══════════════════════════════════════════════════════════
Shared startup and SPA navigation watcher (pushState)
Immediately switches between folder and file views without reloading.
═══════════════════════════════════════════════════════════ */
function isFilePage() {
return location.pathname.startsWith('/u/') || isDFilePage();
}
function syncBodyClass() {
const path = location.pathname;
document.body.classList.remove('d-folder', 'dl-d-folder');
if (path.startsWith('/d/')) {
document.body.classList.add(isDFilePage() ? 'dl-d-folder' : 'd-folder');
}
}
function cleanupUI() {
// Alte UI-Reste entfernen, damit keine doppelten Buttons/Popups entstehen
document.getElementById('bypassButtonContainer')?.remove();
document.getElementById('pd-export-btn')?.remove();
document.getElementById('pd-modal-overlay')?.remove();
}
const moduleFlags = { u: false, l: false, d: false };
function dispatchModules() {
const path = location.pathname;
// U: nur /u/ und /d/-Datei-Seiten
if (isFilePage()) {
if (!moduleFlags.u) { moduleFlags.u = true; initUBypass(); }
} else {
moduleFlags.u = false;
}
// L: /l/ und /u/
if (path.startsWith('/l/') || path.startsWith('/u/')) {
if (!moduleFlags.l) {
document.getElementById('popupBox')?.remove();
moduleFlags.l = true;
initLGallery();
}
} else {
moduleFlags.l = false;
}
// D: nur Ordner-Übersicht
if (path.startsWith('/d/') && !isDFilePage()) {
if (!moduleFlags.d) { moduleFlags.d = true; initDFolder(); }
} else {
moduleFlags.d = false;
}
}
let lastPath = location.pathname;
function onUrlChange() {
if (location.pathname === lastPath) return;
lastPath = location.pathname;
cleanupUI();
syncBodyClass();
dispatchModules();
}
function startUrlWatcher() {
// pushState/replaceState abfangen -> sofortige Reaktion auf SPA-Navigation
['pushState', 'replaceState'].forEach(method => {
const orig = history[method];
history[method] = function (...args) {
const result = orig.apply(this, args);
onUrlChange();
return result;
};
});
// Browser-Zurück/Vorwärts
window.addEventListener('popstate', onUrlChange);
// Sicherheitsnetz, falls die App doch mal anders navigiert (langsam, stört nicht)
setInterval(onUrlChange, 2000);
}
if (typeof GM_registerMenuCommand === 'function') {
GM_registerMenuCommand('Show Bypass Links', displayLinksModal);
}
cleanupUI();
syncBodyClass();
dispatchModules();
startUrlWatcher();
})();