Decrypt all FileCrypt links
// ==UserScript==
// @name Decrypt FileCrypt Links
// @version 3.0
// @description Decrypt all FileCrypt links
// @author SH3LL
// @grant GM.xmlHttpRequest
// @match *://filecrypt.cc/*
// @match *://www.filecrypt.cc/*
// @match *://filecrypt.co/*
// @match *://www.filecrypt.co/*
// @run-at document-end
// @connect self
// @connect *
// @namespace https://greatest.deepsurf.us/users/762057
// ==/UserScript==
(function() {
'use strict';
// ==================== CONFIGURATION ====================
const CONFIG = {
hostname: document.location.hostname,
isDarkMode: !!document.head.querySelector('meta[name="theme-color"]')
};
const STYLES = {
get bgColor() { return CONFIG.isDarkMode ? '#0b0d15' : 'white'; },
get textColor() { return CONFIG.isDarkMode ? 'white' : 'black'; },
get borderColor() { return CONFIG.isDarkMode ? '#444' : '#ddd'; },
get buttonBg() { return CONFIG.isDarkMode ? '#333' : '#f0f0f0'; },
get buttonHoverBg() { return CONFIG.isDarkMode ? '#555' : '#e0e0e0'; },
get groupBg() { return CONFIG.isDarkMode ? '#1a1d2e' : '#f9f9f9'; }
};
// Storage for grouped links and UI elements
const linkGroups = new Map();
const groupElements = new Map();
let mainContainer = null;
let totalLinksCount = 0;
let pendingCount = 0;
// ==================== INITIALIZATION ====================
function init() {
removeUsenetAds();
injectStyles();
const path = document.location.href;
if (path.includes('/Link/')) {
handleSingleLink();
} else if (path.includes('/Container/')) {
handleContainer();
} else {
const links = document.querySelectorAll('a[href*="Link/"]');
if (links.length > 0) {
handleContainer();
}
}
}
function injectStyles() {
const css = `
.fc-bypass-container {
background-color: ${STYLES.bgColor};
border-radius: 10px;
padding: 1em;
margin: 1em 0;
color: ${STYLES.textColor};
z-index: 10;
position: relative;
}
.fc-bypass-header {
font-size: 1.2em;
font-weight: bold;
margin-bottom: 0.5em;
}
.fc-bypass-status {
font-size: 0.9em;
color: ${CONFIG.isDarkMode ? '#aaa' : '#666'};
margin-bottom: 1em;
}
.fc-bypass-groups-wrapper {
display: flex;
flex-wrap: wrap;
gap: 1em;
align-items: flex-start;
justify-content: center;
}
.fc-bypass-group {
background-color: ${STYLES.groupBg};
border: 1px solid ${STYLES.borderColor};
border-radius: 8px;
padding: 1em;
display: inline-block;
min-width: 200px;
max-width: 100%;
}
.fc-bypass-group-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1em;
margin-bottom: 0.8em;
padding-bottom: 0.5em;
border-bottom: 1px solid ${STYLES.borderColor};
}
.fc-bypass-group-title {
font-weight: bold;
color: ${STYLES.textColor};
}
.fc-bypass-links-container {
display: flex;
flex-direction: column;
gap: 0.4em;
}
.fc-bypass-link-row {
display: inline-flex;
align-items: center;
gap: 0.5em;
}
.fc-bypass-link {
color: ${STYLES.textColor};
cursor: pointer;
word-break: break-all;
}
.fc-bypass-link:hover {
text-decoration: underline;
}
.fc-bypass-btn {
background-color: ${STYLES.buttonBg};
color: ${STYLES.textColor};
border: 1px solid ${STYLES.borderColor};
border-radius: 4px;
padding: 0.3em 0.6em;
cursor: pointer;
font-size: 0.85em;
white-space: nowrap;
flex-shrink: 0;
}
.fc-bypass-btn:hover {
background-color: ${STYLES.buttonHoverBg};
}
.fc-bypass-btn:disabled {
opacity: 0.6;
cursor: default;
}
.fc-bypass-btn-primary {
background-color: #4a90d9;
color: white;
border-color: #3a7bc8;
}
.fc-bypass-btn-primary:hover {
background-color: #3a7bc8;
}
.fc-bypass-controls {
display: flex;
gap: 0.5em;
margin-bottom: 1em;
flex-wrap: wrap;
justify-content: center;
}
`;
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
}
// ==================== AD REMOVAL ====================
function removeUsenetAds() {
const allLinks = document.getElementsByTagName('A');
for (const link of allLinks) {
if (link.href && link.href.includes('/pink/')) {
link.parentNode?.remove();
break;
}
}
const adSelectors = [
'[class*="usenet"]',
'[class*="sponsor"]',
'[id*="usenet"]',
'[id*="sponsor"]'
];
for (const selector of adSelectors) {
const ads = document.querySelectorAll(selector);
for (const ad of ads) {
ad.remove();
}
}
}
// ==================== SINGLE LINK HANDLING ====================
function handleSingleLink() {
console.log('[Bypass] Handling single link page');
const linkFromDom = extractLinkFromDOM();
if (linkFromDom) {
console.log('[Bypass] Link trovato nel DOM:', linkFromDom);
resolveFinalLink(linkFromDom);
return;
}
const linkFromScripts = extractLinkFromScripts();
if (linkFromScripts) {
console.log('[Bypass] Link trovato negli script:', linkFromScripts);
resolveFinalLink(linkFromScripts);
return;
}
if (document.body.children.length > 0) {
console.log('[Bypass] Cerco link nel body HTML');
const linkFromBody = extractIntermediateLink(document.body.innerHTML);
if (linkFromBody) {
resolveFinalLink(linkFromBody);
return;
}
}
console.log('[Bypass] Faccio fetch della pagina');
fetchAndExtractLink();
}
function extractLinkFromDOM() {
const links = document.querySelectorAll('a[href*="Link/"], a[href*="filecrypt"]');
for (const link of links) {
if (link.href && link.href.includes('/Link/')) {
return link.href;
}
}
return null;
}
function extractLinkFromScripts() {
const scripts = document.getElementsByTagName('SCRIPT');
for (const script of scripts) {
const content = script.innerHTML;
let match = content.match(/top\.location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/window\.location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/window\.open\(['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/self\.location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/parent\.location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
}
return null;
}
function fetchAndExtractLink() {
GM.xmlHttpRequest({
method: 'GET',
url: document.location.href,
onload: (response) => {
console.log('[Bypass] Fetch completato, estraggo link');
const intermediateLink = extractIntermediateLink(response.responseText);
if (intermediateLink) {
console.log('[Bypass] Link estratto dal fetch:', intermediateLink);
resolveFinalLink(intermediateLink);
} else {
console.log('[Bypass] Nessun link trovato nel fetch');
}
},
onerror: (error) => {
console.log('[Bypass] Errore nel fetch:', error);
}
});
}
function resolveFinalLink(intermediateLink) {
if (!intermediateLink) {
console.log('[Bypass] Link intermedio vuoto');
return;
}
if (intermediateLink.startsWith('http') &&
!intermediateLink.includes('filecrypt') &&
!intermediateLink.includes('/Link/')) {
console.log('[Bypass] URL diretto, navigo:', intermediateLink);
window.location.href = intermediateLink;
return;
}
console.log('[Bypass] Risolvo link intermedio:', intermediateLink);
GM.xmlHttpRequest({
method: 'GET',
url: intermediateLink,
onload: (response) => {
console.log('[Bypass] Risposta ricevuta per:', intermediateLink);
if (response.finalUrl && response.finalUrl !== intermediateLink) {
console.log('[Bypass] Redirect a:', response.finalUrl);
window.location.href = response.finalUrl;
return;
}
const extracted = extractIntermediateLink(response.responseText);
if (extracted && extracted !== intermediateLink) {
console.log('[Bypass] Link estratto dalla risposta:', extracted);
window.location.href = extracted;
} else {
console.log('[Bypass] Uso link intermedio come ultima spiaggia');
window.location.href = intermediateLink;
}
},
onerror: (error) => {
console.log('[Bypass] Errore nella risoluzione:', error);
window.location.href = intermediateLink;
}
});
}
function extractIntermediateLink(html) {
if (!html) return null;
const patterns = [
/top\.location\.href\s*=\s*['"]([^'"]+)['"]/,
/window\.location\.href\s*=\s*['"]([^'"]+)['"]/,
/location\.href\s*=\s*['"]([^'"]+)['"]/,
/self\.location\.href\s*=\s*['"]([^'"]+)['"]/,
/parent\.location\.href\s*=\s*['"]([^'"]+)['"]/,
/window\.open\(['"]([^'"]+)['"]/,
/href="([^"]*\/Link\/[^"]*\.html)"/,
/"([^"]*\/Link\/[^"]*\.html)"/,
/id=([a-zA-Z0-9]+)/
];
for (const pattern of patterns) {
const match = html.match(pattern);
if (match && match[1]) {
let link = match[1];
if (!link.startsWith('http')) {
link = `https://${CONFIG.hostname}/Link/${link}.html`;
}
return link.replace(/&/g, '&');
}
}
const lastHttpIndex = html.lastIndexOf('http');
if (lastHttpIndex !== -1) {
const idIndex = html.indexOf('id=', lastHttpIndex);
if (idIndex !== -1) {
const url = html.substring(lastHttpIndex, idIndex + 43);
return url.replace(/&/g, '&');
}
}
return null;
}
// ==================== CONTAINER HANDLING ====================
function handleContainer() {
console.log('[Bypass] Handling container page');
const downloadBtn = document.querySelector('.download');
if (!downloadBtn) {
console.log('[Bypass] Nessun pulsante download trovato');
return;
}
const article = downloadBtn.closest('article')
|| downloadBtn.parentNode?.parentNode?.parentNode?.parentNode;
if (!article?.parentNode) {
console.log('[Bypass] Articolo non trovato');
return;
}
mainContainer = createMainContainer();
article.parentNode.insertBefore(mainContainer, article);
extractLinksLocally();
}
function createMainContainer() {
const container = document.createElement('DIV');
container.className = 'fc-bypass-container';
container.id = 'fc-bypass-main';
const header = document.createElement('DIV');
header.className = 'fc-bypass-header';
header.textContent = 'Decrypted Links';
container.appendChild(header);
const status = document.createElement('DIV');
status.className = 'fc-bypass-status';
status.id = 'fc-bypass-status';
status.textContent = 'Decrypting links...';
container.appendChild(status);
const controls = document.createElement('DIV');
controls.className = 'fc-bypass-controls';
controls.id = 'fc-bypass-controls';
const copyAllBtn = createButton('Copy All Links', 'fc-bypass-btn fc-bypass-btn-primary', copyAllLinks);
copyAllBtn.id = 'fc-bypass-copy-all';
controls.appendChild(copyAllBtn);
container.appendChild(controls);
const groupsWrapper = document.createElement('DIV');
groupsWrapper.className = 'fc-bypass-groups-wrapper';
groupsWrapper.id = 'fc-bypass-groups';
container.appendChild(groupsWrapper);
return container;
}
// ==================== LINK EXTRACTION ====================
function extractLinksLocally() {
const encryptedButtons = findEncryptedButtons();
if (encryptedButtons.length === 0) {
updateStatus('No download links found on this page.', true);
return;
}
pendingCount = encryptedButtons.length;
console.log(`[Bypass] Trovati ${pendingCount} link crittati`);
updateStatus(`Decrypting ${pendingCount} links...`);
encryptedButtons.forEach(button => processEncryptedButton(button));
}
function findEncryptedButtons() {
let buttons = document.querySelectorAll("button.download[onclick*='openLink']");
if (buttons.length === 0) {
buttons = document.querySelectorAll("[onclick*='openLink']");
}
if (buttons.length === 0) {
buttons = document.querySelectorAll("button[data-id], a[data-id]");
}
return Array.from(buttons);
}
function processEncryptedButton(button) {
const onclick = button.getAttribute('onclick');
let encryptedId = null;
if (onclick) {
let match = onclick.match(/this\.getAttribute\(['"]([^'"]+)['"]\)/);
if (match && match[1]) {
encryptedId = button.getAttribute(match[1]);
}
if (!encryptedId) {
match = onclick.match(/getAttribute\(['"]([^'"]+)['"]\)/);
if (match && match[1]) {
encryptedId = button.getAttribute(match[1]);
}
}
if (!encryptedId) {
match = onclick.match(/\/Link\/([^'"\.]+)\.html/);
if (match && match[1]) {
encryptedId = match[1];
}
}
}
if (!encryptedId) {
for (const attr of button.attributes) {
if (attr.name.startsWith('data-') && attr.value) {
encryptedId = attr.value;
break;
}
}
}
if (!encryptedId && button.dataset) {
for (const key in button.dataset) {
if (button.dataset[key]) {
encryptedId = button.dataset[key];
break;
}
}
}
if (!encryptedId) {
console.log('[Bypass] ID non trovato per il pulsante');
onLinkProcessed();
return;
}
console.log('[Bypass] ID trovato:', encryptedId);
const row = button.closest('tr');
let linkStatus = 'unknown';
if (row) {
const statusIcon = row.querySelector('td.status i');
if (statusIcon) {
if (statusIcon.classList.contains('online')) {
linkStatus = 'online';
} else if (statusIcon.classList.contains('offline')) {
linkStatus = 'offline';
}
}
}
const linkUrl = `https://${CONFIG.hostname}/Link/${encryptedId}.html`;
fetchAndDecryptLink(linkUrl, linkStatus);
}
function fetchAndDecryptLink(url, linkStatus = 'unknown') {
console.log('[Bypass] Decripto:', url);
GM.xmlHttpRequest({
method: 'GET',
url: url,
onload: (response) => {
console.log('[Bypass] Risposta ricevuta per:', url);
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, 'text/html');
const redirectUrl = findRedirectUrl(doc);
if (redirectUrl) {
console.log('[Bypass] URL di redirect trovato:', redirectUrl);
resolveAndDisplayLink(redirectUrl, linkStatus);
} else {
console.log('[Bypass] Nessun redirect trovato');
onLinkProcessed();
}
},
onerror: (error) => {
console.log(`[Bypass] Errore nel fetch: ${url}`, error);
onLinkProcessed();
}
});
}
function findRedirectUrl(doc) {
const scripts = doc.getElementsByTagName('SCRIPT');
for (const script of scripts) {
const content = script.innerHTML;
let match = content.match(/top\.location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/window\.location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/location\.href\s*=\s*['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
match = content.match(/window\.open\(['"]([^'"]+)['"]/);
if (match && match[1]) return match[1];
}
return null;
}
// ==================== Resolve Links ====================
function resolveAndDisplayLink(encryptedUrl, linkStatus = 'unknown') {
console.log('[Bypass] Risolvo URL:', encryptedUrl);
// Prova prima con HEAD
GM.xmlHttpRequest({
method: 'HEAD',
url: encryptedUrl,
onload: (response) => {
let finalUrl = response.finalUrl || encryptedUrl;
finalUrl = transformUrl(finalUrl);
if (response.finalUrl && response.finalUrl !== encryptedUrl) {
console.log(`[Bypass] Redirect a: ${finalUrl}`);
addLinkToUI(finalUrl, false, 'online');
} else {
console.log(`[Bypass] Link online: ${finalUrl}`);
verifyWithGetRequest(encryptedUrl, linkStatus);
return;
}
onLinkProcessed();
},
onerror: (error) => {
console.log(`[Bypass] HEAD fallito, provo con GET: ${encryptedUrl}`, error);
verifyWithGetRequest(encryptedUrl, linkStatus);
}
});
}
function verifyWithGetRequest(url, linkStatus = 'unknown') {
GM.xmlHttpRequest({
method: 'GET',
url: url,
onload: (response) => {
let finalUrl = response.finalUrl || url;
finalUrl = transformUrl(finalUrl);
if (response.responseText) {
const jsRedirect = extractLinkFromScriptsFromText(response.responseText);
if (jsRedirect) {
console.log(`[Bypass] Redirect JS trovato: ${jsRedirect}`);
finalUrl = jsRedirect;
}
}
console.log(`[Bypass] Link risolto con GET: ${finalUrl}`);
addLinkToUI(finalUrl, false, 'online');
onLinkProcessed();
},
onerror: (error) => {
console.log(`[Bypass] GET fallito per: ${url}`, error);
// Non mostrare come errore, ma come unknown
addLinkToUI(url, false, linkStatus);
onLinkProcessed();
}
});
}
function extractLinkFromScriptsFromText(html) {
if (!html) return null;
const patterns = [
/top\.location\.href\s*=\s*['"]([^'"]+)['"]/,
/window\.location\.href\s*=\s*['"]([^'"]+)['"]/,
/location\.href\s*=\s*['"]([^'"]+)['"]/,
/window\.open\(['"]([^'"]+)['"]/,
/window\.location\.replace\(['"]([^'"]+)['"]/
];
for (const pattern of patterns) {
const match = html.match(pattern);
if (match && match[1]) {
return match[1];
}
}
return null;
}
function transformUrl(url) {
if (url.includes('terabytez.org/login?redirect=')) {
return url.replace('/login?redirect=', '/');
}
return url;
}
function onLinkProcessed() {
pendingCount--;
if (pendingCount > 0) {
updateStatus(`Decrypting links... (${pendingCount} remaining)`);
} else {
if (totalLinksCount > 0) {
updateStatus(`Done! ${totalLinksCount} link${totalLinksCount > 1 ? 's' : ''} decrypted.`);
} else {
updateStatus('No links could be decrypted.', true);
}
}
}
// ==================== LIVE UI UPDATES ====================
function getHostFromUrl(url) {
try {
return new URL(url).hostname;
} catch {
return 'Unknown Host';
}
}
function addLinkToUI(url, isError = false, linkStatus = 'unknown') {
const host = getHostFromUrl(url);
totalLinksCount++;
if (!linkGroups.has(host)) {
linkGroups.set(host, []);
}
linkGroups.get(host).push({ url, isError, linkStatus });
if (!groupElements.has(host)) {
const groupEl = createGroupElement(host);
groupElements.set(host, groupEl);
insertGroupSorted(groupEl, host);
}
const group = groupElements.get(host);
const linksContainer = group.querySelector('.fc-bypass-links-container');
const linkRow = createLinkRow(url, isError, linkStatus);
linksContainer.appendChild(linkRow);
updateGroupTitle(host);
}
function createGroupElement(host) {
const group = document.createElement('DIV');
group.className = 'fc-bypass-group';
group.dataset.host = host;
const groupHeader = document.createElement('DIV');
groupHeader.className = 'fc-bypass-group-header';
const title = document.createElement('SPAN');
title.className = 'fc-bypass-group-title';
title.textContent = host;
groupHeader.appendChild(title);
const copyGroupBtn = createButton('Copy Links', 'fc-bypass-btn', () => {
const links = (linkGroups.get(host) || []).map(l => l.url);
copyLinksToClipboard(links);
showCopyFeedback(copyGroupBtn, 'Copied!');
});
groupHeader.appendChild(copyGroupBtn);
group.appendChild(groupHeader);
const linksContainer = document.createElement('DIV');
linksContainer.className = 'fc-bypass-links-container';
group.appendChild(linksContainer);
return group;
}
function insertGroupSorted(groupEl, host) {
const wrapper = document.getElementById('fc-bypass-groups');
if (!wrapper) return;
const existingGroups = Array.from(wrapper.children);
let inserted = false;
for (const existing of existingGroups) {
const existingHost = existing.dataset.host;
if (host.localeCompare(existingHost) < 0) {
wrapper.insertBefore(groupEl, existing);
inserted = true;
break;
}
}
if (!inserted) {
wrapper.appendChild(groupEl);
}
}
function updateGroupTitle(host) {
const group = groupElements.get(host);
if (!group) return;
const title = group.querySelector('.fc-bypass-group-title');
const count = linkGroups.get(host)?.length || 0;
title.textContent = `${host} (${count})`;
}
function createLinkRow(url, isError = false, linkStatus = 'unknown') {
const row = document.createElement('DIV');
row.className = 'fc-bypass-link-row';
const link = document.createElement('SPAN');
link.className = 'fc-bypass-link';
link.title = url;
const actualStatus = (isError && linkStatus === 'online') ? 'online' : linkStatus;
const actualError = isError && linkStatus !== 'online';
if (actualError) {
link.textContent = `${truncateUrl(url)} (error)`;
link.style.color = 'red';
link.style.cursor = 'default';
} else if (actualStatus === 'offline') {
link.textContent = truncateUrl(url);
link.style.color = 'red';
link.addEventListener('click', () => window.open(url, '_blank'));
} else if (actualStatus === 'online') {
link.textContent = truncateUrl(url);
link.style.color = '#4CAF50';
link.addEventListener('click', () => window.open(url, '_blank'));
} else {
link.textContent = truncateUrl(url);
link.style.color = '#FFA500'; // Arancione per "da verificare"
link.addEventListener('click', () => window.open(url, '_blank'));
}
row.appendChild(link);
const copyBtn = createButton('Copy', 'fc-bypass-btn', () => {
copyLinksToClipboard([url]);
showCopyFeedback(copyBtn, 'Copied!');
});
row.appendChild(copyBtn);
return row;
}
function createButton(text, className, onClick) {
const btn = document.createElement('BUTTON');
btn.className = className;
btn.textContent = text;
btn.addEventListener('click', onClick);
return btn;
}
// ==================== UTILITY FUNCTIONS ====================
function updateStatus(message, isError = false) {
const status = document.getElementById('fc-bypass-status');
if (status) {
status.textContent = message;
status.style.color = isError ? 'red' : (CONFIG.isDarkMode ? '#aaa' : '#666');
}
}
function truncateUrl(url, maxLength = 40) {
if (url.length <= maxLength) return url;
const ellipsis = '...';
const availableChars = maxLength - ellipsis.length;
const startChars = Math.ceil(availableChars / 2);
const endChars = Math.floor(availableChars / 2);
return url.substring(0, startChars) + ellipsis + url.substring(url.length - endChars);
}
function copyLinksToClipboard(links) {
const text = links.join('\n');
navigator.clipboard.writeText(text);
}
function copyAllLinks() {
const allLinks = [];
const sortedHosts = Array.from(linkGroups.keys()).sort();
for (const host of sortedHosts) {
const links = linkGroups.get(host) || [];
allLinks.push(...links.map(l => l.url));
}
if (allLinks.length === 0) {
alert('No links to copy yet!');
return;
}
copyLinksToClipboard(allLinks);
const copyAllBtn = document.getElementById('fc-bypass-copy-all');
if (copyAllBtn) {
showCopyFeedback(copyAllBtn, `Copied ${allLinks.length}!`);
}
}
function showCopyFeedback(button, message) {
const originalText = button.textContent;
button.textContent = message;
button.disabled = true;
setTimeout(() => {
button.textContent = originalText;
button.disabled = false;
}, 1500);
}
// ==================== START ====================
init();
})();