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