您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Bypass FileCrypt
当前为
// ==UserScript== // @name Bypass FileCrypt (New) // @namespace Bhunter // @version 1.0.1 // @description Bypass FileCrypt // @author Bhunter // @license MIT // @match http://filecrypt.cc/* // @match http://www.filecrypt.cc/* // @match http://filecrypt.co/* // @match http://www.filecrypt.co/* // @match https://filecrypt.cc/* // @match https://www.filecrypt.cc/* // @match https://filecrypt.co/* // @match https://www.filecrypt.co/* // @run-at document-end // @connect dcrypt.it // @connect self // @grant GM.xmlHttpRequest // ==/UserScript== (function() { 'use strict'; // Determine if dark theme is used const isDarkTheme = document.head.querySelector('meta[name="theme-color"]') !== null || document.body.classList.contains('dark') || window.getComputedStyle(document.body).backgroundColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)/)?.[1] < 100; // Add stylesheet to document addStylesheet(isDarkTheme); // Remove ads removeAds(); // Apply main functionality based on URL if (document.location.href.includes("/Link/")) { processSingleLink(); } else if (document.location.href.includes("/Container/")) { waitForCaptchaSolved(); } })(); // Add stylesheet to document function addStylesheet(isDarkTheme) { const style = document.createElement('style'); // Define the colors based on theme const colors = isDarkTheme ? { background: '#1e1e2e', text: '#cdd6f4', accent: '#cba6f7', border: '#313244', itemBg: '#181825', itemHover: '#11111b', actionBg: '#45475a', actionText: '#cdd6f4' } : { background: '#ffffff', text: '#333333', accent: '#4f46e5', border: '#e5e7eb', itemBg: '#f9fafb', itemHover: '#f3f4f6', actionBg: '#e0e7ff', actionText: '#4f46e5' }; // Stylesheet content style.textContent = ` /* Main container */ .fc-container { background-color: ${colors.background}; color: ${colors.text}; border: 1px solid ${colors.border}; border-radius: 12px; box-shadow: 0 10px 15px -3px ${isDarkTheme ? 'rgba(0, 0, 0, 0.4)' : 'rgba(0, 0, 0, 0.1)'}; max-width: 660px; margin: 20px auto 30px; overflow: hidden; font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif; font-size: 14px; line-height: 1.5; position: relative; z-index: 10; } /* Header */ .fc-header { padding: 14px 18px; border-bottom: 1px solid ${colors.border}; display: flex; justify-content: space-between; align-items: center; } .fc-title { margin: 0; font-weight: 600; font-size: 16px; } .fc-counter { padding: 4px 10px; border-radius: 20px; font-size: 12px; background-color: ${colors.actionBg}; color: ${colors.actionText}; } /* Content area */ .fc-content { max-height: 350px; overflow-y: auto; padding: 12px 0; scrollbar-width: thin; scrollbar-color: ${colors.border} transparent; } .fc-content::-webkit-scrollbar { width: 6px; } .fc-content::-webkit-scrollbar-track { background: transparent; } .fc-content::-webkit-scrollbar-thumb { background-color: ${colors.border}; border-radius: 3px; } /* Loading */ .fc-loading { padding: 16px; text-align: center; } .fc-loading p { margin-top: 12px; font-size: 14px; } .fc-spinner { animation: fc-rotate 2s linear infinite; } .fc-spinner-path { stroke-dasharray: 1, 200; stroke-dashoffset: 0; animation: fc-dash 1.5s ease-in-out infinite; stroke: ${colors.accent}; } @keyframes fc-rotate { 100% { transform: rotate(360deg); } } @keyframes fc-dash { 0% { stroke-dasharray: 1, 200; stroke-dashoffset: 0; } 50% { stroke-dasharray: 89, 200; stroke-dashoffset: -35px; } 100% { stroke-dasharray: 89, 200; stroke-dashoffset: -124px; } } /* Domain headers */ .fc-domain-header { padding: 6px 16px; font-size: 13px; font-weight: 500; color: ${colors.accent}; display: flex; align-items: center; gap: 6px; } .fc-domain-header:not(:first-child) { margin-top: 10px; } .fc-domain-count { background-color: ${colors.actionBg}; border-radius: 10px; padding: 1px 6px; font-size: 11px; } /* Link items */ .fc-link-item { padding: 8px 16px; margin: 2px 0; display: flex; align-items: center; gap: 10px; border-radius: 4px; transition: background-color 0.2s; cursor: pointer; } .fc-link-item:hover { background-color: ${colors.itemHover}; } .fc-link-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; font-size: 14px; } .fc-link-path { opacity: 0.7; } /* Copy button */ .fc-copy-btn { width: 28px; height: 28px; min-width: 28px; background-color: transparent; color: ${colors.accent}; border: none; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; transition: background-color 0.2s; margin: 0; } .fc-copy-btn:hover { background-color: ${colors.actionBg}; } /* Footer */ .fc-footer { padding: 12px 16px; border-top: 1px solid ${colors.border}; display: flex; justify-content: space-between; align-items: center; } .fc-info-text { opacity: 0.7; font-size: 12px; } .fc-copy-all { padding: 8px 12px; background-color: ${colors.accent}; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; transition: all 0.2s ease; } .fc-copy-all:disabled { opacity: 0.5; cursor: not-allowed; } .fc-copy-all:hover:not(:disabled) { filter: brightness(1.1); } /* Notification */ .fc-notification { position: fixed; top: 10px; right: 10px; background-color: rgba(50, 50, 50, 0.9); color: white; padding: 10px 15px; border-radius: 8px; font-size: 14px; z-index: 9999; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); transition: opacity 0.3s ease; } `; document.head.appendChild(style); } // Remove ads function removeAds() { const usenetAds = document.querySelectorAll('a[href*="/pink/"]'); for (const ad of usenetAds) { if (ad.parentNode) { ad.parentNode.remove(); } } } // Check if captcha is solved by looking for download buttons function waitForCaptchaSolved() { // Function to check if captcha is solved based on visible elements function isCaptchaSolved() { // Look for download buttons or elements that appear after captcha return document.querySelectorAll('.dlcdownload').length > 0; } // If captcha is already solved, proceed immediately if (isCaptchaSolved()) { processContainerPage(); return; } // Otherwise, wait for captcha to be solved const captchaObserver = new MutationObserver((mutations, observer) => { if (isCaptchaSolved()) { observer.disconnect(); processContainerPage(); } }); captchaObserver.observe(document.body, { childList: true, subtree: true }); } // Process single link page async function processSingleLink() { if (document.body.getElementsByTagName("SCRIPT").length === 0) { window.stop(); let htmlContent = document.body.innerHTML; if (!htmlContent || document.body.children.length === 0) { try { const response = await fetch(document.location.href); htmlContent = await response.text(); } catch (error) { console.error("Failed to fetch page content:", error); return; } } const httpIndex = htmlContent.lastIndexOf("http"); if (httpIndex !== -1) { const endIndex = htmlContent.indexOf('id=', httpIndex) + 43; let finalUrl = htmlContent.substring(httpIndex, endIndex).replace(/&/g, '&'); window.location.href = finalUrl; } } } // Process container page function processContainerPage() { // Find the best container to insert our link box const containerSection = findBestContainer(); // Create container elements const { container, content, counter, copyAllBtn } = createLinkBox(); // Insert the box at the appropriate location containerSection.insertBefore(container, containerSection.firstChild); // Try to get DLC file const dlcButtons = document.getElementsByClassName("dlcdownload"); if (dlcButtons.length > 0) { const dlcId = dlcButtons[0].getAttribute("onclick")?.split("'")[1]; if (dlcId) { fetchDlcAndDecrypt(dlcId, { content, counter, copyAllBtn }); return; } } // Fall back to manual link extraction extractLinks({ content, counter, copyAllBtn }); } // Find the best container for inserting our box function findBestContainer() { // Try various selectors in order of preference const selectors = [ '.content .window', '.download', '.content', 'main', 'article', '.container', '#container' ]; for (const selector of selectors) { const element = document.querySelector(selector); if (element) { return element; } } // Fallback to body if no suitable container found return document.body; } // Create DOM structure for the link box function createLinkBox() { // Create container const container = document.createElement("div"); container.className = "fc-container"; // Create header const header = document.createElement("div"); header.className = "fc-header"; const title = document.createElement("h3"); title.className = "fc-title"; title.innerHTML = "🔓 Decrypted Links"; const counter = document.createElement("span"); counter.className = "fc-counter"; counter.id = "fc-counter"; counter.textContent = "Loading..."; header.appendChild(title); header.appendChild(counter); container.appendChild(header); // Create content area const content = document.createElement("div"); content.className = "fc-content"; content.id = "fc-content"; // Add loading animation const loadingDiv = document.createElement("div"); loadingDiv.className = "fc-loading"; loadingDiv.id = "fc-loading"; loadingDiv.innerHTML = ` <svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <circle class="fc-spinner fc-spinner-path" cx="12" cy="12" r="10" fill="none" stroke-width="2" /> </svg> <p>Decrypting links...</p> `; content.appendChild(loadingDiv); container.appendChild(content); // Create footer const footer = document.createElement("div"); footer.className = "fc-footer"; // Add info text const infoText = document.createElement("small"); infoText.className = "fc-info-text"; infoText.textContent = "Click link to open, or use copy button"; // Add copy all button const copyAllBtn = document.createElement("button"); copyAllBtn.className = " fc-copy-all"; copyAllBtn.id = "fc-copy-all"; copyAllBtn.textContent = "Copy All"; copyAllBtn.disabled = true; footer.appendChild(infoText); footer.appendChild(copyAllBtn); container.appendChild(footer); return { container, content, counter, copyAllBtn }; } // Fetch DLC file and decrypt it async function fetchDlcAndDecrypt(dlcId, elements) { try { // Update the loading message const loadingDiv = document.getElementById("fc-loading"); const loadingText = loadingDiv.querySelector("p"); loadingText.textContent = "Fetching DLC file..."; // Fetch the DLC file const response = await fetch(`https://${document.location.hostname}/DLC/${dlcId}.dlc`); if (!response.ok) throw new Error('Failed to fetch DLC file'); const dlcContent = await response.text(); loadingText.textContent = "Decrypting links via dcrypt.it..."; // Use GM.xmlHttpRequest for dcrypt.it (since it may require CORS handling) GM.xmlHttpRequest({ method: "POST", url: "http://dcrypt.it/decrypt/paste", headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "content=" + encodeURIComponent(dlcContent), onload: function(response) { try { const result = JSON.parse(response.response); if (result.success && result.success.links && result.success.links.length > 0) { displayLinks(result.success.links, elements); } else { throw new Error("No links were found in the dcrypt.it response"); } } catch (error) { console.error("Error parsing dcrypt.it response:", error); extractLinks(elements); } }, onerror: function() { console.error("Error connecting to dcrypt.it"); extractLinks(elements); } }); } catch (error) { console.error("Error fetching DLC:", error); extractLinks(elements); } } // Extract links directly from page function extractLinks(elements) { const loadingDiv = document.getElementById("fc-loading"); const loadingText = loadingDiv.querySelector("p"); loadingText.textContent = "Extracting links directly..."; const encLinks = document.querySelectorAll("[onclick^=openLink]"); if (encLinks.length === 0) { showError("No links found on this page."); return; } // Update counter to show progress elements.counter.textContent = `0/${encLinks.length}`; let completedLinks = 0; const validLinks = []; // Process each link with a small delay between requests to avoid overloading const processLink = (index) => { if (index >= encLinks.length) { if (validLinks.length > 0) { displayLinks(validLinks, elements); } else { showError("Failed to extract any valid links."); } return; } const link = encLinks[index]; const onclick = link.getAttribute("onclick"); const encParam = onclick.split("'")[1]; const encValue = link.getAttribute(encParam); const linkUrl = `http://${document.location.hostname}/Link/${encValue}.html`; fetchFinalLink(linkUrl) .then(finalLink => { completedLinks++; elements.counter.textContent = `${completedLinks}/${encLinks.length}`; if (finalLink) { validLinks.push(finalLink); } // Process next link with a small delay setTimeout(() => processLink(index + 1), 100); }) .catch(() => { completedLinks++; elements.counter.textContent = `${completedLinks}/${encLinks.length}`; setTimeout(() => processLink(index + 1), 100); }); }; // Start processing links processLink(0); } // Show error message function showError(message) { const loadingDiv = document.getElementById("fc-loading"); loadingDiv.innerHTML = ` <div style="color:var(--fc-accent,#4f46e5);font-size:24px;margin-bottom:10px">❌</div> <p style="margin:0">${message}</p> `; const counter = document.getElementById("fc-counter"); if (counter) counter.textContent = "Error"; } // Fetch a single link's destination async function fetchFinalLink(url) { try { const response = await fetch(url); if (!response.ok) return null; const html = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, "text/html"); // Try to find the redirect URL in scripts const scripts = doc.querySelectorAll("script"); for (const script of scripts) { if (script.textContent.includes("top.location.href=")) { const matches = script.textContent.match(/top\.location\.href\s*=\s*['"]([^'"]+)['"]/); if (matches && matches[1]) { return await resolveRedirect(matches[1]); } } } return null; } catch (error) { console.error("Error fetching link:", error); return null; } } // Resolve final URL from redirect async function resolveRedirect(url) { try { // Using fetch with HEAD method to get the final URL const controller = new AbortController(); const signal = controller.signal; // Set a timeout to abort the request const timeoutId = setTimeout(() => controller.abort(), 5000); const response = await fetch(url, { method: 'HEAD', signal, redirect: 'follow' }); clearTimeout(timeoutId); return response.url; } catch (error) { // If HEAD fails, try GET with GM.xmlHttpRequest return new Promise((resolve) => { GM.xmlHttpRequest({ method: "GET", url: url, onreadystatechange: function(response) { if (response.readyState === 2) { // HEADERS_RECEIVED resolve(response.finalUrl); this.abort(); } }, onerror: function() { resolve(url); // Return original URL if everything fails } }); }); } } // Display links with modern UI function displayLinks(links, elements) { // Update counter elements.counter.textContent = `${links.length} Links`; // Clear loading indicator elements.content.innerHTML = ''; // Enable copy all button elements.copyAllBtn.disabled = false; elements.copyAllBtn.addEventListener('click', () => { navigator.clipboard.writeText(links.join('\n')) .then(() => { const originalText = elements.copyAllBtn.textContent; elements.copyAllBtn.textContent = "✓ Copied"; setTimeout(() => { elements.copyAllBtn.textContent = originalText; }, 2000); }); }); // Group links by domain for better organization const linksByDomain = {}; links.forEach(link => { try { const url = new URL(link); const domain = url.hostname; if (!linksByDomain[domain]) { linksByDomain[domain] = []; } linksByDomain[domain].push(link); } catch (e) { // If parsing fails, put in "Other" category if (!linksByDomain["Other"]) { linksByDomain["Other"] = []; } linksByDomain["Other"].push(link); } }); // Sort domains alphabetically const domains = Object.keys(linksByDomain).sort(); // Create link items by domain domains.forEach((domain, domainIndex) => { // Add domain header if multiple domains exist if (domains.length > 1) { const domainHeader = document.createElement("div"); domainHeader.className = "fc-domain-header"; domainHeader.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <circle cx="12" cy="12" r="4"></circle> </svg> <span>${domain}</span> <span class="fc-domain-count">${linksByDomain[domain].length}</span> `; elements.content.appendChild(domainHeader); } // Add links for this domain linksByDomain[domain].forEach(link => { const linkItem = createLinkItem(link); elements.content.appendChild(linkItem); }); }); } // Create a link item element function createLinkItem(link) { const linkItem = document.createElement("div"); linkItem.className = "fc-link-item"; // Link text container const linkText = document.createElement("span"); linkText.className = "fc-link-text"; linkText.title = link; // Parse and display URL try { const url = new URL(link); // If there's a path or query, show them differently if (url.pathname !== "/" || url.search) { linkText.innerHTML = `${url.hostname}<span class="fc-link-path">${url.pathname}${url.search}</span>`; } else { linkText.textContent = url.hostname; } } catch (e) { linkText.textContent = link; } // Link click handler to open link linkItem.addEventListener('click', () => { window.open(link, '_blank'); }); // Copy button const copyBtn = document.createElement("button"); copyBtn.className = "fc-copy-btn"; copyBtn.innerHTML = ` <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect> <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path> </svg> `; copyBtn.addEventListener('click', (e) => { e.stopPropagation(); navigator.clipboard.writeText(link) .then(() => { // Visual feedback when copied copyBtn.innerHTML = ` <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M20 6L9 17l-5-5"></path> </svg> `; setTimeout(() => { copyBtn.innerHTML = ` <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect> <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path> </svg> `; }, 1500); }); }); linkItem.appendChild(linkText); linkItem.appendChild(copyBtn); return linkItem; }