NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Sci-Hub downloader // @namespace https://openuserjs.org/users/clemente // @match *://*/* // @grant GM_xmlhttpRequest // @version 1.11 // @author clemente // @license MIT // @description Display a banner to download the article on Sci-Hub if available // @description:de Zeigen Sie ein Banner an, um den Artikel über Sci-Hub herunterzuladen, falls verfügbar // @description:es Despliegue un banner para descargar el artículo sobre Sci-Hub si está disponible // @description:fr Affiche une bannière pour télécharger l'article sur Sci-Hub si disponible // @description:it Mostra un banner per scaricare l'articolo su Sci-Hub, se disponibile // @icon https://sci-hub.it.nf/misc/img/favicon.ico // @connect sci-hub.it.nf // @inject-into content // @noframes // @homepageURL https://openuserjs.org/scripts/clemente/Sci-Hub_downloader // @supportURL https://openuserjs.org/scripts/clemente/Sci-Hub_downloader/issues // ==/UserScript== /* jshint esversion: 6 */ const SCI_HUB_URL = "https://sci-hub.it.nf"; function getUserLanguage() { const language = (navigator.language || 'en').slice(0, 2); return ['de', 'en', 'es', 'fr', 'it'].includes(language) ? language : 'en'; } const downloadMessages = { de: 'Herunterladen von Sci-Hub', en: 'Download from Sci-Hub', es: 'Descargar desde Sci-Hub', fr: 'Télécharger sur Sci-Hub', it: 'Scarica da Sci-Hub', }; const errorMessages = { de: 'Es gibt einen Fehler bei der Verbindung zu Sci-Hub. Sie sollten die Sci-Hub-Adresse und Ihr Netzwerk überprüfen.', en: 'There is an error connecting to Sci-Hub. You should check the Sci-Hub address and your network.', es: 'Hay un error de conexión con Sci-Hub. Deberías comprobar la dirección de Sci-Hub y tu red.', fr: 'Il y a une erreur de connexion à Sci-Hub. Vous devez vérifier l’adresse de Sci-Hub et votre réseau.', it: 'C\'è un errore di connessione a Sci-Hub. Dovresti controllare l\'indirizzo di Sci-Hub e la tua rete.', }; function getDoiReference() { const detectedDoiMeta = document.querySelector('meta[name="citation_doi"], meta[name="dc.Identifier"][scheme="doi"]'); if (detectedDoiMeta) return detectedDoiMeta.content; return null; } class NetworkError extends Error { constructor(status, ...params) { super(...params); if(Error.captureStackTrace) { Error.captureStackTrace(this, NetworkError); } this.name = 'NetworkError'; if (status) { this.message = `Website responded with status ${status}.`; } else { this.message = "Unknown error."; } } } function gm_fetch(url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: url, onload: function({ status, responseText }) { if (status < 200 && status >= 300) return reject(new NetworkError(status)); resolve(responseText); }, onerror: function() { reject(new NetworkError()); }, }); }); } async function getDownloadLink(doiReference) { try { const scihubPageHtml = await gm_fetch(`${SCI_HUB_URL}/${doiReference}`); const parser = new DOMParser(); const scihubPageDocument = parser.parseFromString(scihubPageHtml, "text/html"); const pdfDownloadLink = scihubPageDocument.querySelector(`a[onclick$="?download=true'"]`); const match = pdfDownloadLink.getAttribute("onclick").match(/^location\.href='(.*)'$/); const downloadLink = match[1]; return downloadLink; } catch (e) { if (e instanceof NetworkError) { // If this is a network error, Sci-Hub is probably not working and it should be noted to the user console.error(e); return null; } const fallbackLink = `${SCI_HUB_URL}/${doiLink}`; return fallbackLink; } } function buildBanner(isDownloadAvailable) { const bannerElement = document.createElement('div'); bannerElement.style = ` background-color: ${isDownloadAvailable ? 'orange' : 'red'}; min-height: 40px; display: flex; justify-content: center; align-items: center; position: relative; z-index: 2147483647; `; return bannerElement; } function buildBannerContent(downloadLink) { const language = getUserLanguage(); if (!downloadLink) { const errorMessage = document.createElement('span'); errorMessage.textContent = errorMessages[language]; errorMessage.style = ` color: white; font-size: 16px; font-family: arial; `; return errorMessage; } const downloadLinkElement = document.createElement('a'); downloadLinkElement.textContent = downloadMessages[language]; downloadLinkElement.href = downloadLink; downloadLinkElement.download = true; downloadLinkElement.style = ` color: white; font-size: 16px; font-family: arial; `; return downloadLinkElement; } async function displayBannerWhenDoiIsDetected() { const doiReference = getDoiReference(); if (!doiReference) return; console.log("DOI detected:", doiReference); const downloadLink = await getDownloadLink(doiReference); if (!downloadLink) { console.log("No download link found."); } else { console.log("Download link retrieved:", downloadLink); } const banner = buildBanner(downloadLink); const bannerContent = buildBannerContent(downloadLink); banner.append(bannerContent); document.body.prepend(banner); } displayBannerWhenDoiIsDetected();