您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Copy easly the hash from a torrent on YGG in one click and more...
// ==UserScript== // @namespace https://greasyfork.org/fr/users/868328-invincible812 // @name Copy hash for YGG // @name:fr Copieur de hash pour YGG // @include https://*.yggtorrent.*/* // @include https://yggtorrent.*/* // @include https://*.yggtorrent.* // @include https://yggtorrent.* // @include https://*.ygg.*/* // @include https://ygg.*/* // @include https://*.ygg.* // @include https://ygg.* // @grant GM.xmlHttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // @grant GM_addStyle // @compatible firefox Violentmonkey // @compatible chrome Violentmonkey // @compatible brave Violentmonkey // @compatible opera Violentmonkey // @version 3.2 // @author Invincible812 // @license Free // @icon https://i.ibb.co/nzW3KXp/Copy-hash.png // @description Copy easly the hash from a torrent on YGG in one click and more... // @description:fr Copier facilement le hash d'un torrent sur YGG en un clique et bien plus... // @supportURL https://www3.ygg.re/profile/9385666-invincible813 // @run-at document-end // @require https://code.jquery.com/jquery-3.6.3.min.js // ==/UserScript== window.addEventListener('load', function() { console.log('[COPY HASH FOR YGG] Lancement du script'); const version = `3.2`; const date_maj = `17/05/2024` const nouveauté = `<p><b><u>Nouveautés de la version ${version} :</u></b></p> <div class="nouveaute-list-container" style="font-size: 12x; line-height: 1.2"> <ul style="margin-top: 10px;"> <li>• <u>[MÀJ]</u> <b>v3.2 : Changement d'adresse + passage de YGG en privé</b> <br>Concernant cela, actuellement vous avez malheureusement besoin d'un compte YGG pour pouvoir continuer à utiliser YGG et également le script (qui continuera d'être maintenu aussi longtemps que possible vous inquiétez pas ;). <br><b>Faites attention aux arnaques aux comptes et autres magouilles pour avoir un compte YGG<b>.</li> </ul> </div>`; function showUpdateNotification() { const isClosed = GM_getValue(`updateNotificationClosed_v${version}`, false); if (isClosed) { return; } const isNewInstallation = !GM_getValue("scriptInstalled", false); GM_setValue("scriptInstalled", true); const notificationDiv = document.createElement("div"); notificationDiv.innerHTML = ` <div style="position: fixed; top: 30px; left: 50%; transform: translateX(-50%); background-color: #fff; padding: 20px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); z-index: 9999;"> <div style="display: flex; align-items: center; margin-bottom: 20px;"> <img src="https://i.ibb.co/nzW3KXp/Copy-hash.png" alt="Logo Copieur de Hash pour YGG" style="width: 80px; height: 80px; margin-right: 30px;"> <p style="font-weight: bold; font-size: 17px; margin: 0;">Copieur de Hash pour YGG (Version ${version} - <i>${date_maj}</i>)</p> </div> <p style="font-weight: bold; color: green;">Nouvelle mise à jour installée !</p> ${isNewInstallation ? `<p>Bienvenue ! Merci à toi d'avoir installé mon script.</p> <p>Utilisez le script pour copier les hashs de torrents sur YGGTorrent et les envoyer sur Alldebrid pour un débridage facile !</p> <br> ${nouveauté} <br> <p>À bientôt, </p> <p><i>Le créateur du script</i></p> <a href="https://greasyfork.org/fr/scripts/459498-copy-hash-for-ygg/versions" target="_blank" style="text-decoration: none; margin-right: 10px;"> <button id="readPatchNote" style="padding: 10px 20px; border: none; background-color: #4CAF50; color: white; cursor: pointer; transition: background-color 0.3s; font-weight: bold; text-decoration: underline;">Lire le Patch Note complet</button> </a> <button id="closeNotification" style="padding: 10px 20px; border: none; background-color: #ccc; color: #333; cursor: pointer; transition: background-color 0.3s; font-weight: bold; text-decoration: underline;">Commencer à s'amuser :\u0029</button>` : `<p>Rebienvenue ! Merci à toi de continuer à utiliser mon script.</p> <p>Tu viens d'installer la version ${version} du script.</p><br> ${nouveauté} <br> <p>À bientôt, </p> <p><i>Le créateur du script</i></p> <a href="https://greasyfork.org/fr/scripts/459498-copy-hash-for-ygg/versions" target="_blank" style="text-decoration: none; margin-right: 10px;"> <button id="readPatchNote" style="padding: 10px 20px; border: none; background-color: #4CAF50; color: white; cursor: pointer; transition: background-color 0.3s; font-weight: bold; text-decoration: underline;">Lire le Patch Note complet</button> </a> <button id="closeNotification" style="padding: 10px 20px; border: none; background-color: #ccc; color: #333; cursor: pointer; transition: background-color 0.3s; font-weight: bold; text-decoration: underline;">Compris !</button>`} </div>`; document.body.appendChild(notificationDiv); const closeNotificationButton = document.getElementById("closeNotification"); closeNotificationButton.addEventListener("click", function() { notificationDiv.remove(); GM_setValue(`updateNotificationClosed_v${version}`, true); }); notificationDiv.addEventListener("click", function(event) { if (event.target === notificationDiv) { notificationDiv.remove(); GM_setValue(`updateNotificationClosed_v${version}`, true); } }); const readPatchNoteButton = document.getElementById("readPatchNote"); readPatchNoteButton.addEventListener("mouseover", function() { this.style.backgroundColor = "#45A049"; }); readPatchNoteButton.addEventListener("mouseout", function() { this.style.backgroundColor = "#4CAF50"; }); closeNotificationButton.addEventListener("mouseover", function() { this.style.backgroundColor = "#999"; this.style.color = "#fff"; }); closeNotificationButton.addEventListener("mouseout", function() { this.style.backgroundColor = "#ccc"; this.style.color = "#333"; }); } showUpdateNotification(); const panelMenuList = document.getElementsByClassName('panel-menu-list')[0]; if (panelMenuList) { panelMenuList.insertAdjacentHTML('beforeend', '<li><a href="#" id="menu_settings">Options Copy Hash</a></li>'); } else if(document.getElementsByClassName('ct')[0]) { //console.log("La classe panel-menu-list n'existe pas dans le document."); document.getElementsByClassName('ct')[0].children[0].insertAdjacentHTML('beforeend', '<li><a href="#" id="menu_settings">Options Copy Hash</a></li>'); } const sett = document.querySelector('#menu_settings'); sett.addEventListener('click', function(event) { event.preventDefault(); cfg.open(); }); let Alldebrid_API; const oldConfigKey = "_MonkeyConfig_Options___Script_Copieur_de_hash_pour_YGG___v1_6_cfg"; const oldConfig = GM_getValue(oldConfigKey, null); const newConfigKey = "_MonkeyConfig_Options___Copieur_de_hash_pour_YGG_cfg"; if (oldConfig !== null) { GM_setValue(newConfigKey, oldConfig); GM_deleteValue(oldConfigKey); } const newConfig = { Bouton_Copier_le_Hash: { type: 'select', choices: ['Oui', 'Non'], default: 'Oui' }, Ajouter_URL_Magnet: { type: 'select', choices: ['Oui', 'Non'], default: 'Oui' }, Bouton_Envoyer_sur_Alldebrid: { type: 'select', choices: ['Oui', 'Non'], default: 'Oui' }, Bouton_Envoyer_Torrent: { type: 'select', choices: ['Oui', 'Non'], default: 'Oui' }, API_Alldebrid: { type: 'text' }, }; const cfg = new MonkeyConfig({ title: 'Options - Copieur de hash pour YGG', menuCommand: true, params: newConfig, }); Alldebrid_API = cfg.get('API_Alldebrid'); // --------------------------------------------------------------------------- // function isPremium(callback) { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/user?agent=ScriptYGGHash&apikey=${Alldebrid_API}`, onload: (response) => { const userData = JSON.parse(response.responseText); const isUserPremium = userData?.data?.user?.isPremium || false; callback(isUserPremium); }, }); } // function deleteMagnet(magnetId) { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/delete?agent=ScriptYGGHash&apikey=${Alldebrid_API}&id=${magnetId}`, onload: (response) => { const responseData = JSON.parse(response.responseText); if (responseData && responseData.status === "success") { //console.log("[COPY HASH FOR YGG] Le magnet a été supprimé avec succès."); } else { console.error("Erreur lors de la suppression du magnet."); } }, onerror: () => { console.error("Erreur lors de la suppression du magnet."); } }); } // --------------------------------------------------------------------------- // if (location.pathname.includes('/torrent/')) { document.getElementsByTagName('tbody')[0].children[0].children[1].insertAdjacentHTML('afterbegin', `\n<a style="max-width:100%;color:#555555;top:-1px;font-size:11px;font-weight:700;text-transform:uppercase;border:3px solid #555555;border-radius:25px;padding:5px 10px;transition: all 0.3s ease; cursor:pointer;" class="butt-settings" onmouseover="this.style.background='#999999';this.style.color='#ffffff';" onmouseout="this.style.background='transparent';this.style.color='#555555';">Options <span class="ico_gear"></span></a>`); const sett = document.querySelector('a.butt-settings'); sett.addEventListener('click', function(event) { event.preventDefault(); cfg.open(); }); let boutons1 = cfg.get('Bouton_Copier_le_Hash'); let boutons2 = cfg.get('Bouton_Envoyer_sur_Alldebrid'); let boutons3 = cfg.get('Bouton_Envoyer_Torrent'); let boutons4 = cfg.get('Ajouter_URL_Magnets'); Alldebrid_API = cfg.get('API_Alldebrid'); boutons1 = boutons1 == "Oui" ? true : false; boutons2 = boutons2 == "Oui" ? true : false; boutons3 = boutons3 == "Oui" ? true : false; boutons4 = boutons4 == "Oui" ? true : false; let hash = boutons4 ? 'magnet:?xt=urn:btih:' + document.getElementsByClassName('informations')[0].childNodes[1].childNodes[9].childNodes[3].textContent.replace('Tester', '') : document.getElementsByClassName('informations')[0].childNodes[1].childNodes[9].childNodes[3].textContent.replace('Tester', ''); // function uploadMagnet(apikey, magnetHash, callback) { const apiUrl = `https://api.alldebrid.com/v4/magnet/upload?agent=ScriptYGGHash&apikey=${apikey}&magnets[]=${magnetHash}`; GM.xmlHttpRequest({ method: "GET", url: apiUrl, onload: (response) => { const responseData = JSON.parse(response.responseText); if (responseData && responseData.status === "success" && responseData.data && responseData.data.magnets) { callback(responseData.data.magnets[0]); } else { callback(null); } }, onerror: () => { callback(null); } }); } async function uploadTorrent(apikey, agent, downloadLink, callback) { // Télécharger le fichier à partir du lien de téléchargement const response = await fetch(downloadLink); if (!response.ok) { alert('Connectez vous à votre compte YGG.'); return; } //console.log(response) const fileBlob = await response.blob(); //console.log('fileBlob', fileBlob); // Créer un objet FormData et ajouter le fichier const formData = new FormData(); //console.log('formData', formData); const file = new File([fileBlob], 'downloadedFile.torrent'); //console.log('file', file); formData.append('files[0]', file); // Ajouter les paramètres de requête à l'URL const queryParams = new URLSearchParams({ agent: agent, apikey: apikey, }); const apiUrl = 'https://api.alldebrid.com/v4/magnet/upload/file'; const url = `${apiUrl}?${queryParams.toString()}`; try { // Envoyer la requête POST avec le fichier const uploadResponse = await fetch(url, { method: 'POST', body: formData, }); if (!uploadResponse.ok) { console.error('Failed to upload the file. Status:', uploadResponse.status); callback(null); } const result = await uploadResponse.json(); //console.log('File upload successful:', result); if(result.data.files[0].error){ alert('Connectez vous à votre compte YGG.'); return } callback(true) } catch (error) { console.error('Error during file upload:', error.message); } } function formatSize(size) { if (size < 1024) { return size + " B"; } else if (size < 1024 * 1024) { return (size / 1024).toFixed(2) + " Ko"; } else if (size < 1024 * 1024 * 1024) { return (size / (1024 * 1024)).toFixed(2) + " Mo"; } else { return (size / (1024 * 1024 * 1024)).toFixed(2) + " Go"; } } if (boutons1) { document.getElementsByTagName('tbody')[0].children[0].children[1].insertAdjacentHTML('beforeend', `\n<a style="max-width:100%;color:#d9a65a;top:-1px;font-size:11px;font-weight:700;text-transform:uppercase;border:3px solid #d9a65a;border-radius:25px;padding:5px 10px;transition: all 0.3s ease; cursor:pointer;" onclick="this.textContent='Copié !'" class="butt-hash" onmouseover="this.style.background='#d9a85a';this.style.color='#ffffff';" onmouseout="this.style.background='transparent';this.style.color='#d9ad5a';">Copier le hash <span class="ico_copy"></span>`); document.getElementsByClassName('butt-hash')[0].addEventListener('click', function() { navigator.clipboard.writeText(hash); }); } if (boutons2) { document.getElementsByTagName('tbody')[0].children[0].children[1].insertAdjacentHTML('beforeend', `\n<a style="max-width:100%;color:#ffae42;top:-1px;font-size:11px;font-weight:700;text-transform:uppercase;border:3px solid #ffae42;border-radius:25px;padding:5px 10px;transition: all 0.3s ease; cursor:pointer;" class="butt-alledebrid" onmouseover="this.style.background='#ffc658';this.style.color='#ffffff';" onmouseout="this.style.background='transparent';this.style.color='#ffae42';">Hash vers Alldebrid <span class="ico_link"></span></a> `); const alldebridButton = document.getElementsByClassName('butt-alledebrid')[0]; alldebridButton.addEventListener('click', function() { if (boutons2) { isPremium((userIsPremium) => { if (userIsPremium) { uploadMagnet(Alldebrid_API, hash, (responseMagnet) => { //console.log(responseMagnet); if (responseMagnet !== null) { alldebridButton.textContent = "Envoyé !"; } else { alldebridButton.textContent = "Erreur Magnet :/"; } }); } else { alert("L'utilisateur de cette API n'est pas premium."); } }); } }); } if (boutons3) { document.getElementsByTagName('tbody')[0].children[0].children[1].insertAdjacentHTML('beforeend', `\n<a style="max-width:100%;color:#ffae42;top:-1px;font-size:11px;font-weight:700;text-transform:uppercase;border:3px solid #ffae42;border-radius:25px;padding:5px 10px;transition: all 0.3s ease; cursor:pointer;" class="butt-torrent" onmouseover="this.style.background='#ffc658';this.style.color='#ffffff';" onmouseout="this.style.background='transparent';this.style.color='#ffae42';">Fichier Torrent vers Alldebrid <span class="ico_file"></span></a> `); const torrentButton = document.getElementsByClassName('butt-torrent')[0]; const link = "https://www.ygg.re/engine/download_torrent?id="+document.getElementById('saveFav').attributes[2].value.match(/id=(\d+)/)[1]; torrentButton.addEventListener('click', function() { if (boutons2) { isPremium((userIsPremium) => { if (userIsPremium) { uploadTorrent(Alldebrid_API, "ScriptHashYGG", link, (responseMagnet) => { //console.log('responseMagnet', responseMagnet); if (responseMagnet !== null) { //console.log('ODDDD'); torrentButton.textContent = "Envoyé !"; } else { //console.log('GGGGGGGG'); torrentButton.textContent = "Erreur Torrent :/"; } }); } else { alert("L'utilisateur de cette API n'est pas premium."); } }); } }); } const hash0 = document.getElementsByClassName('informations')[0].children[0].children[4].children[1].textContent.replace('Tester', ''); const newRow = document.createElement('tr'); const progressBar = document.createElement('div'); progressBar.classList.add('progress-bar'); // Ajoutez la classe de barre de progression de Bootstrap progressBar.setAttribute('role', 'progressbar'); progressBar.style.width = '0%'; // Initialisez la largeur de la barre de progression à 0% progressBar.style.display = 'none'; const statusCell = document.createElement('td'); statusCell.style.verticalAlign = 'top'; statusCell.insertAdjacentText('beforeend', 'Alldebrid'); const progressBarStyle = document.createElement('style'); progressBarStyle.textContent = ` .progress-bar { position: relative; background: linear-gradient(to right, rgb(255, 237, 165) 100%, white 0px) 0% 0% / 28.2% no-repeat white; transition: all 1.6s linear 0s; display: none; /* Par défaut, la barre de progression est cachée */ width: 0%; /* Largeur initiale à 0% */ } `; // Ajout du style au header du document document.head.appendChild(progressBarStyle); const infoCell = document.createElement('td'); infoCell.colSpan = 5; infoCell.style.position = 'relative'; // Ajoutez un style pour positionner les éléments de la barre de progression infoCell.classList.add('alldebrid-container'); const statusElement = document.createElement('p'); const downloadSpeedElement = document.createElement('p'); const downloadedSizeElement = document.createElement('p'); const progressElement = document.createElement('p'); const totalSizeElement = document.createElement('p'); const linkElement = document.createElement('p'); const remainingTimeElement = document.createElement('p'); statusElement.textContent = "Statut du torrent : N/A"; downloadSpeedElement.textContent = ""; downloadedSizeElement.textContent = ""; progressElement.textContent = ""; totalSizeElement.textContent = ""; linkElement.textContent = ""; remainingTimeElement.textContent = ""; infoCell.appendChild(statusElement); infoCell.appendChild(downloadSpeedElement); infoCell.appendChild(progressBar); infoCell.appendChild(progressElement); infoCell.appendChild(downloadedSizeElement); infoCell.appendChild(totalSizeElement); infoCell.appendChild(remainingTimeElement); infoCell.appendChild(linkElement); newRow.appendChild(statusCell); newRow.appendChild(infoCell); const table = document.querySelector('.infos-torrent'); table.querySelector('tbody').appendChild(newRow); const buttAllButton = document.getElementsByClassName('butt-alledebrid')[0]; const torrentAll = document.getElementsByClassName('butt-torrent')[0]; let intervalId; let isButtonClicked = false; // function updateProgressBar(progress) { const container = document.getElementsByClassName('alldebrid-container')[0]; if (!container) return; // Sortir de la fonction si aucun conteneur n'est trouvé const progressBar = container.querySelector('.progress-bar'); if (!progressBar) return; // Sortir de la fonction si aucune barre de progression n'est trouvée dans le conteneur if (progress === undefined) { // Si aucun argument n'est fourni, masquer la barre de progression progressBar.style.display = 'none'; } else { // Sinon, mettre à jour la barre de progression avec la valeur fournie et le style donné //container.style.display = 'block'; //container.style.position = 'relative'; container.style.background = 'linear-gradient(to right, rgb(255, 237, 165) 100%, white 0px) 0% 0% / '+progress+'% no-repeat white'; container.style.transition = 'all 1.6s linear 0s'; //container.style.width = progress + '%'; //container.textContent = progress + '%'; } } function onClickHandler() { if (!isButtonClicked) { isButtonClicked = true; function getMagnetStatusAndUnlockLinks(magnetHash) { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/status?agent=ScriptYGGHash&apikey=${Alldebrid_API}`, onload: function(response) { try { const torrentData = JSON.parse(response.responseText); const magnets = torrentData.data.magnets; const matchingMagnet = magnets.find((magnet) => magnet.hash === magnetHash); if (!matchingMagnet) { console.error("Aucun magnet correspondant trouvé."); return; } const status = matchingMagnet.status; const viewLinksElement = document.createElement('a'); viewLinksElement.id = 'viewLinks'; viewLinksElement.classList.add('noselect'); viewLinksElement.textContent = 'Voir les liens'; viewLinksElement.style.display = 'block'; const linksContainer = document.createElement('div'); linksContainer.id = 'linksContainer'; linksContainer.style.display = 'none'; infoCell.appendChild(viewLinksElement); infoCell.appendChild(linksContainer); if (status === "Ready") { viewLinksElement.addEventListener('click', async () => { linksContainer.innerHTML = ''; const links = matchingMagnet.links; if (links && links.length > 0) { const unlockedLinkPromises = []; function unlockLink(linkData) { const filename = linkData.filename || "Inconnu"; const extension = filename.split('.').pop(); if (![".nfo", ".NFO"].includes(`.${extension}`)) { const unlockPromise = new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/link/unlock?agent=ScriptYGGHash&apikey=${Alldebrid_API}&link=${linkData.link}`, onload: function(unlockResponse) { try { const unlockData = JSON.parse(unlockResponse.responseText); const unlockedLink = unlockData.data.link; if (unlockedLink) { resolve({ filename, link: unlockedLink }); } else { console.error(`Échec du débridage du lien: ${linkData.link}`); reject(`Échec du débridage du lien: ${linkData.link}`); } } catch (error) { console.error("Une erreur s'est produite lors du débridage du lien.", error); reject(error); } }, onerror: () => { console.error("Une erreur s'est produite lors du débridage du lien."); reject("Une erreur s'est produite lors du débridage du lien."); }, }); }); unlockedLinkPromises.push(unlockPromise); } } links.forEach(unlockLink); try { const unlockedLinks = await Promise.all(unlockedLinkPromises); unlockedLinks.forEach((link) => { const unlockedLinkElement = document.createElement('a'); const lineBreakElement = document.createElement('br'); unlockedLinkElement.href = link.link; unlockedLinkElement.textContent = link.filename; linksContainer.appendChild(unlockedLinkElement); linksContainer.appendChild(lineBreakElement); }); linksContainer.style.maxHeight = "0px"; linksContainer.style.transition = "max-height 0.8s ease-in-out"; linksContainer.style.display = 'block'; linksContainer.style.maxHeight = linksContainer.scrollHeight + 18 + "px"; const copyAllButton = document.createElement('a'); copyAllButton.textContent = 'Copier tous les liens'; const strongElement = document.createElement('strong'); const underlineElement = document.createElement('u'); underlineElement.appendChild(copyAllButton); strongElement.appendChild(underlineElement); copyAllButton.addEventListener('click', () => { const allLinks = unlockedLinks.map((link) => link.link).join('\n'); const tempTextArea = document.createElement('textarea'); tempTextArea.value = allLinks; document.body.appendChild(tempTextArea); tempTextArea.select(); document.execCommand('copy'); document.body.removeChild(tempTextArea); alert('Tous les liens ont été copiés dans le presse-papiers.'); }); linksContainer.appendChild(copyAllButton); } catch (error) { console.error("Une erreur s'est produite lors du débridage des liens.", error); } } else { console.error("Aucun lien trouvé pour le magnet prêt."); } }); } else { console.error(`Le magnet n'est pas prêt (Statut: ${status})`); } } catch (error) { console.error("Une erreur s'est produite lors de la récupération du statut du magnet.", error); } }, onerror: () => { console.error("Une erreur s'est produite lors de la récupération du statut du magnet."); }, }); } function calculateRemainingTime(downloadSpeed, downloadedSize, totalSize) { if (downloadSpeed === "N/A" || downloadedSize === "N/A" || totalSize === "N/A" || isNaN(downloadSpeed) || downloadSpeed <= 0 || isNaN(downloadedSize) || downloadedSize <= 0 || isNaN(totalSize) || totalSize <= 0) { return "N/A"; } const remainingSeconds = (totalSize - downloadedSize) / downloadSpeed; const hours = Math.floor(remainingSeconds / 3600); const minutes = Math.floor((remainingSeconds % 3600) / 60); const seconds = Math.floor(remainingSeconds % 60); return `${hours}h ${minutes}m ${seconds}s`; } function getMagnetStatus() { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/status?agent=ScriptYGGHash&apikey=${Alldebrid_API}`, onload: (response) => { const torrentData = JSON.parse(response.responseText); const magnets = torrentData.data.magnets; const matchingMagnet = magnets.find((magnet) => magnet.hash === hash0); const nondeb = `Non débridable via le hash, veuillez attendre un peu si c'est un torrent récent, sinon faites via le fichier torrent`; if (matchingMagnet) { const torrentStatus = matchingMagnet.status || "N/A"; statusElement.textContent = `Statut du torrent : ${torrentStatus}`; if (torrentStatus === "In Queue") { if (matchingMagnet.filename == "noname") { statusElement.textContent = `Statut du torrent : ${nondeb}`; } else { statusElement.textContent = `Statut du torrent : En attente`; } } else if (torrentStatus === "Uploading") { if (matchingMagnet.filename == "noname") { statusElement.textContent = `Statut du torrent : ${nondeb}`; } else { statusElement.textContent = `Statut du torrent : Upload en cours`; const uploadedSpeed = matchingMagnet.uploadSpeed ? `${formatSize(matchingMagnet.uploadSpeed)} /s` : "N/A"; const uploadedSize = matchingMagnet.uploaded ? formatSize(matchingMagnet.uploaded) : "N/A"; const totalSize = matchingMagnet.size ? formatSize(matchingMagnet.size) : "N/A"; const progress = uploadedSize !== "N/A" && totalSize !== "N/A" ? ((matchingMagnet.uploaded / matchingMagnet.size) * 100).toFixed(2) + "%" : "N/A"; const remainingTime = calculateRemainingTime(matchingMagnet.uploadSpeed, matchingMagnet.uploaded, matchingMagnet.size); downloadSpeedElement.textContent = `Vitesse d'upload : ${uploadedSpeed}`; progressElement.textContent = `Progression : ${progress}`; updateProgressBar(progress.replace('%','')); downloadedSizeElement.textContent = `Taille de l'upload : ${uploadedSize}`; totalSizeElement.textContent = `Taille totale : ${totalSize}`; remainingTimeElement.textContent = `Temps restant : ${remainingTime}`; } } else if (torrentStatus === "Downloading") { if (matchingMagnet.filename == "noname") { statusElement.textContent = `Statut du torrent : ${nondeb}`; } else { statusElement.textContent = `Statut du torrent : Téléchargement en cours`; const downloadSpeed = matchingMagnet.downloadSpeed ? `${formatSize(matchingMagnet.downloadSpeed)} /s` : "N/A"; const downloadedSize = matchingMagnet.downloaded ? formatSize(matchingMagnet.downloaded) : "N/A"; const totalSize = matchingMagnet.size ? formatSize(matchingMagnet.size) : "N/A"; const progress = downloadedSize !== "N/A" && totalSize !== "N/A" ? ((matchingMagnet.downloaded / matchingMagnet.size) * 100).toFixed(2) + "%" : "N/A"; const remainingTime = calculateRemainingTime(matchingMagnet.downloadSpeed, matchingMagnet.downloaded, matchingMagnet.size); downloadSpeedElement.textContent = `Vitesse de téléchargement : ${downloadSpeed}`; updateProgressBar(progress.replace('%','')); progressElement.textContent = `Progression : ${progress}`; downloadedSizeElement.textContent = `Taille du téléchargement : ${downloadedSize}`; totalSizeElement.textContent = `Taille totale : ${totalSize}`; remainingTimeElement.textContent = `Temps restant : ${remainingTime}`; } } else if (torrentStatus === "Ready") { getMagnetStatusAndUnlockLinks(matchingMagnet.hash); downloadSpeedElement.textContent = ``; updateProgressBar(); downloadedSizeElement.textContent = ``; remainingTimeElement.textContent = ""; statusElement.textContent = `Statut du torrent : Prêt`; const totalSize = matchingMagnet.size ? formatSize(matchingMagnet.size) : "N/A"; totalSizeElement.textContent = `Taille totale : ${totalSize}`; linkElement.innerHTML = ``; } else if (torrentStatus === "Proccessing failed (bad torrent ?)") { if (matchingMagnet.filename == "noname") { statusElement.textContent = `Statut du torrent : ${nondeb}`; } else { statusElement.textContent = `Débridage du torrent échoué`; } } else { downloadSpeedElement.textContent = ""; updateProgressBar(); downloadedSizeElement.textContent = ""; totalSizeElement.textContent = ""; linkElement.textContent = ""; } if (matchingMagnet.status == "Ready" || matchingMagnet.filename == "noname") { clearInterval(intervalId); } if (matchingMagnet.filename == "noname") { deleteMagnet(matchingMagnet.id); } } }, onerror: () => { console.error("Erreur de requête à l'API Alldebrid."); } }); } if (buttAllButton.getAttribute('data-clicked') !== 'true') { buttAllButton.setAttribute('data-clicked', 'true'); intervalId = setInterval(getMagnetStatus, 1000); } } }; buttAllButton.addEventListener('click', onClickHandler); torrentAll.addEventListener('click', onClickHandler); function doesMagnetExist(magnetHash) { return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/status?agent=ScriptYGGHash&apikey=${Alldebrid_API}`, onload: (statusResponse) => { try { const torrentData = JSON.parse(statusResponse.responseText); const magnets = torrentData.data.magnets; const matchingMagnet = magnets.find((magnet) => magnet.hash === magnetHash); if (matchingMagnet) { const magnetExists = false; resolve(magnetExists); }else{ const magnetExists = true; resolve(magnetExists); } } catch (error) { reject(error); } }, onerror: (error) => { reject(error); } }); }); } function isTorrentDebridable(magnetHash) { const nondeb = `Non débridable via le hash, veuillez attendre un peu si c'est un torrent récent, sinon faites via le fichier torrent`; return new Promise((resolve, reject) => { statusElement.textContent = "Statut du torrent : Vérification du torrent en cours"; const intervalId = setInterval(() => { statusElement.textContent += "."; }, 1000); let deleteTheMagnet; doesMagnetExist(magnetHash) .then((exists) => { if (exists) { deleteTheMagnet=true; } else { deleteTheMagnet=false; } }) .catch((error) => { console.error("Une erreur s'est produite lors de la vérification du magnet:", error); }); GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/upload?agent=ScriptYGGHash&apikey=${Alldebrid_API}&magnets[]=${magnetHash}`, onload: (uploadResponse) => { clearInterval(intervalId); try { const uploadData = JSON.parse(uploadResponse.responseText); const magnetId = uploadData?.data?.magnets[0]?.id || null; if (!magnetId) { resolve({ debriable: false, status: "Upload failed" }); } else { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/status?agent=ScriptYGGHash&apikey=${Alldebrid_API}`, onload: (statusResponse) => { try { const torrentData = JSON.parse(statusResponse.responseText); const magnets = torrentData.data.magnets; const matchingMagnet = magnets.find((magnet) => magnet.id === magnetId); if (matchingMagnet) { const torrentStatus = matchingMagnet.status || "N/A"; //console.log(matchingMagnet); if ( (torrentStatus === "In Queue" && matchingMagnet.filename === "noname") || (torrentStatus === "Uploading" && matchingMagnet.filename === "noname") || (torrentStatus === "Downloading" && matchingMagnet.filename === "noname") || (torrentStatus === "N/A" && matchingMagnet.filename === "noname") ) { resolve({ debriable: false, status: nondeb }); deleteMagnet(magnetId); } else { resolve({ debriable: true, status: `Débridable` }); deleteTheMagnet === true ? deleteMagnet(magnetId) : ''; } } else { resolve({ debriable: false, status: "N/A" }); } } catch (error) { resolve({ debriable: false, status: "N/A" }); } }, onerror: () => { resolve({ debriable: false, status: "N/A" }); }, }); } } catch (error) { resolve({ debriable: false, status: "Upload failed" }); } }, onerror: () => { clearInterval(intervalId); resolve({ debriable: false, status: "Upload failed" }); }, }); }); } isTorrentDebridable(hash) .then((result) => { if (result.debriable) { statusElement.innerHTML = `Statut du torrent : <svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 448 512" style="vertical-align: middle; margin-right: 5px;"><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>Torrent débridable via hash.`; } else { statusElement.innerHTML = `Statut du torrent : <svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512" style="vertical-align: middle; margin-right: 5px;"><path d="M376.6 84.5c11.3-13.6 9.5-33.8-4.1-45.1s-33.8-9.5-45.1 4.1L192 206 56.6 43.5C45.3 29.9 25.1 28.1 11.5 39.4S-3.9 70.9 7.4 84.5L150.3 256 7.4 427.5c-11.3 13.6-9.5 33.8 4.1 45.1s33.8 9.5 45.1-4.1L192 306 327.4 468.5c11.3 13.6 31.5 15.4 45.1 4.1s15.4-31.5 4.1-45.1L233.7 256 376.6 84.5z"/></svg>${result.status}`; } }) .catch((error) => { statusElement.textContent = "Une erreur s'est produite lors de la vérification du torrent."; console.error("Une erreur s'est produite lors de la vérification du torrent.", error); }); } function copyTorrentHash(event) { event.preventDefault(); const torrentLink = this.getAttribute('href'); GM.xmlHttpRequest({ method: "GET", url: torrentLink, onload: function(response) { //console.log(response.responseText); const parser = new DOMParser(); const temp = parser.parseFromString(response.responseText, "text/html"); const hash = temp.querySelector('#informationsContainer > div > table > tbody > tr:nth-child(5) > td:nth-child(2)').textContent.replace('Tester', '').trim(); const dummyElement = document.createElement('textarea'); dummyElement.value = hash; document.body.appendChild(dummyElement); dummyElement.select(); document.execCommand('copy'); document.body.removeChild(dummyElement); } }); this.textContent = 'Copié !'; } async function sendHashtoAllederid(event) { event.preventDefault(); function getHash(torrentLink) { return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: torrentLink, onload: function(response) { const parser = new DOMParser(); const temp = parser.parseFromString(response.responseText, "text/html"); const hash_ygg = temp.querySelector('#informationsContainer > div > table > tbody > tr:nth-child(5) > td:nth-child(2)').textContent.replace('Tester', '').trim(); resolve(hash_ygg); }, onerror: function(error) { reject(error); } }); }); } function isTorrentDebridable(magnetHash, event) { const nondeb = `Non débridable`; return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/upload?agent=ScriptYGGHash&apikey=${Alldebrid_API}&magnets[]=${magnetHash}`, onload: (uploadResponse) => { clearInterval(intervalId); try { const uploadData = JSON.parse(uploadResponse.responseText); const magnetId = uploadData?.data?.magnets[0]?.id || null; if (!magnetId) { resolve({ debriable: false, status: "Upload failed" }); } else { GM.xmlHttpRequest({ method: "GET", url: `https://api.alldebrid.com/v4/magnet/status?agent=ScriptYGGHash&apikey=${Alldebrid_API}`, onload: (statusResponse) => { try { const torrentData = JSON.parse(statusResponse.responseText); const magnets = torrentData.data.magnets; const matchingMagnet = magnets.find((magnet) => magnet.id === magnetId); if (matchingMagnet) { const torrentStatus = matchingMagnet.status || "N/A"; console.log(matchingMagnet); if ( (torrentStatus === "In Queue" && matchingMagnet.filename === "noname" || matchingMagnet.filename === matchingMagnet.hash) || (torrentStatus === "Uploading" && matchingMagnet.filename === "noname" || matchingMagnet.filename === matchingMagnet.hash) || (torrentStatus === "Downloading" && matchingMagnet.filename === "noname" || matchingMagnet.filename === matchingMagnet.hash) || (torrentStatus === "N/A" && matchingMagnet.filename === "noname" || matchingMagnet.filename === matchingMagnet.hash) ) { resolve({ debriable: false, status: nondeb }); } else { resolve({ debriable: true, status: `Débridable` }); } } else { resolve({ debriable: false, status: "N/A" }); } } catch (error) { resolve({ debriable: false, status: "N/A" }); } }, onerror: () => { resolve({ debriable: false, status: "N/A" }); }, }); } } catch (error) { resolve({ debriable: false, status: "Upload failed" }); } }, onerror: () => { resolve({ debriable: false, status: "Upload failed" }); }, }); }); } const torrentLink = this.getAttribute('href'); console.log(torrentLink) let intervalId; if (Alldebrid_API != "") { isPremium((userIsPremium) => { if (userIsPremium) { getHash(torrentLink) .then((hashh) => { this.textContent = "Vérification en cours"; intervalId = setInterval(() => { this.textContent += "."; }, 1000); isTorrentDebridable(hashh) .then((result) => { clearInterval(intervalId); if (result.debriable) { this.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 448 512" style="vertical-align: middle; margin-right: 5px;"><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>${result.status}`; } else { this.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512" style="vertical-align: middle; margin-right: 5px;"><path d="M376.6 84.5c11.3-13.6 9.5-33.8-4.1-45.1s-33.8-9.5-45.1 4.1L192 206 56.6 43.5C45.3 29.9 25.1 28.1 11.5 39.4S-3.9 70.9 7.4 84.5L150.3 256 7.4 427.5c-11.3 13.6-9.5 33.8 4.1 45.1s33.8 9.5 45.1-4.1L192 306 327.4 468.5c11.3 13.6 31.5 15.4 45.1 4.1s15.4-31.5 4.1-45.1L233.7 256 376.6 84.5z"/></svg>Non débridable`; } }) .catch((error) => { clearInterval(intervalId); this.textContent = "Erreur"; console.error("Une erreur s'est produite lors de la vérification du torrent.", error); }); }) .catch((error) => { console.error('Une erreur s\'est produite :', error); }); } else { alert("L'utilisateur de cette API n'est pas premium."); } }); } else { this.textContent = 'API non renseignée'; cfg.open(); } } if (location.pathname.includes('/engine/search') || location.pathname.includes('/top') || location.pathname.includes('/engine/mostseededs')) { for (let i = 0; i < 30; i++) { const functionName = `start_hash_${i}`; window[functionName] = function() { const tableId = `DataTables_Table_${i}`; const table = document.getElementById(tableId); if (table) { const torrentLinks = table.querySelectorAll('tbody tr td:nth-child(2) a'); torrentLinks.forEach(function(link) { const copyButton = document.createElement('a'); copyButton.setAttribute('href', link.href); const imgElement0 = document.createElement('img'); imgElement0.setAttribute('src', 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6YglfyfbNmrFWRZSkwUegLc_YRW6zWDGR1D6uPCuxSYHEUvRzPYpIQy27E2BREn22C5I&usqp=CAU'); imgElement0.setAttribute('alt', 'Copy Hash'); imgElement0.style.width = '20px'; imgElement0.style.height = '20px'; copyButton.appendChild(imgElement0); copyButton.style.marginLeft = '10px'; copyButton.addEventListener('click', copyTorrentHash); link.parentNode.appendChild(copyButton); const sendButton = document.createElement('a'); sendButton.setAttribute('href', link.href); const imgElement = document.createElement('img'); imgElement.setAttribute('src', 'https://cdn-icons-png.flaticon.com/512/561/561226.png'); imgElement.setAttribute('alt', 'Send Alldebrid'); imgElement.style.width = '20px'; imgElement.style.height = '20px'; sendButton.appendChild(imgElement); sendButton.style.marginLeft = '10px'; sendButton.addEventListener('click', sendHashtoAllederid); link.parentNode.appendChild(sendButton); }); }; } setTimeout(window[functionName], 1000); } } else if(location.pathname.includes('/torrents/exclus')) { function exclus() { const tableId = `table`; const table = document.getElementsByClassName(tableId)[0]; if (table) { const torrentLinks = table.querySelectorAll('tbody tr td:nth-child(2) a'); torrentLinks.forEach(function(link) { const copyButton = document.createElement('a'); copyButton.setAttribute('href', link.href); const imgElement0 = document.createElement('img'); imgElement0.setAttribute('src', 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT6YglfyfbNmrFWRZSkwUegLc_YRW6zWDGR1D6uPCuxSYHEUvRzPYpIQy27E2BREn22C5I&usqp=CAU'); imgElement0.setAttribute('alt', 'Copy Hash'); imgElement0.style.width = '20px'; imgElement0.style.height = '20px'; copyButton.appendChild(imgElement0); copyButton.style.marginLeft = '10px'; copyButton.addEventListener('click', copyTorrentHash); link.parentNode.appendChild(copyButton); const sendButton = document.createElement('a'); sendButton.setAttribute('href', link.href); const imgElement = document.createElement('img'); imgElement.setAttribute('src', 'https://cdn-icons-png.flaticon.com/512/561/561226.png'); imgElement.setAttribute('alt', 'Send Alldebrid'); imgElement.style.width = '20px'; imgElement.style.height = '20px'; sendButton.appendChild(imgElement); sendButton.style.marginLeft = '10px'; sendButton.addEventListener('click', sendHashtoAllederid); link.parentNode.appendChild(sendButton); }); }; } setTimeout(exclus, 1000); }; }); // POUR OPTIONS function MonkeyConfig() { var cfg = this, /* Data object passed to the constructor */ data, /* Configuration parameters (data.parameters or data.params) */ params, /* Current values of configuration parameters */ values = {}, /* Identifier used to store/retrieve configuration */ storageKey, /* Is the configuration dialog displayed? */ displayed, /* Currently displayed window/layer */ openWin, openLayer, /* DOM element wrapping the configuration form */ container, /* Darkened overlay used in the layer display mode */ overlay; /** * Initialize configuration * * @param newData New data object */ function init(newData) { data = newData; if (data) { params = data.parameters || data.params; if (data.buttons === undefined) /* Set default buttons */ data.buttons = [ 'save', 'defaults', 'cancel' ]; if (data.title === undefined) /* * If GM_getMetadata is available, get the name of the script * and use it in the dialog title */ if (typeof GM_getMetadata == 'function') { var scriptName = GM_getMetadata('name'); data.title = scriptName + ' Configuration'; } else data.title = 'Configuration'; } /* Make a safe version of title to be used as stored value identifier */ var safeTitle = data && data.title ? data.title.replace(/[^a-zA-Z0-9]/g, '_') : ''; storageKey = '_MonkeyConfig_' + safeTitle + '_cfg'; var storedValues; /* Load stored values (if present) */ if (GM_getValue(storageKey)) storedValues = JSON.parse(GM_getValue(storageKey)); for (var name in params) { /* If there's a value defined in the passed data object, use it */ if (params[name]['value'] !== undefined) set(name, params[name].value); /* Check if there's a stored value for this parameter */ else if (storedValues && storedValues[name] !== undefined) set(name, storedValues[name]); /* Otherwise, set the default value (if defined) */ else if (params[name]['default'] !== undefined) set(name, params[name]['default']); else set(name, ''); } if (data.menuCommand) { /* Add an item to the User Script Commands menu */ var caption = data.menuCommand !== true ? data.menuCommand : data.title; GM_registerMenuCommand(caption, function () { cfg.open(); }); } /* Expose public methods */ cfg.open = open; cfg.close = close; cfg.get = get; cfg.set = function (name, value) { set(name, value); update(); }; } /** * Get the value of a configuration parameter * * @param name Name of the configuration parameter * @returns Value of the configuration parameter */ function get(name) { return values[name]; } /** * Set the value of a configuration parameter * * @param name Name of the configuration parameter * @param value New value of the configuration parameter */ function set(name, value) { values[name] = value; } /** * Reset configuration parameters to default values */ function setDefaults() { for (var name in params) { if (typeof params[name]['default'] !== 'undefined') { set(name, params[name]['default']); } } } /** * Render the configuration dialog */ function render() { var html = '<div class="__MonkeyConfig_container">' + '<h1>' + data.title + '</h1>' + '<table>'; for (var name in params) { html += MonkeyConfig.formatters['tr'](name, params[name]);} html += '<tr><td colspan="2" class="__MonkeyConfig_buttons">' + '<table><tr>'; /* Render buttons */ for (var button in data.buttons) { html += '<td>'; switch (data.buttons[button]) { case 'cancel': html += '<button type="button" ' + 'id="__MonkeyConfig_button_cancel">' + '<img src="data:image/png;base64,' + MonkeyConfig.res.icons.cancel + '" /> ' + 'Annuler</button>'; break; case 'defaults': html += '<button type="button" ' + 'id="__MonkeyConfig_button_defaults">' + '<img src="data:image/png;base64,' + MonkeyConfig.res.icons.arrow_undo + '" /> ' + 'Par Défaut</button>'; break; case 'save': html += '<button type="button" ' + 'id="__MonkeyConfig_button_save">' + '<img src="data:image/png;base64,' + MonkeyConfig.res.icons.tick + '" /> ' + 'Sauvegarder</button>'; break; } html += '</td>'; } html += '</tr></table></td></tr>'; html += "</table><div>"; return html; } /** * Update the fields in the dialog to reflect current values */ function update() { /* Do nothing if the dialog is not currently displayed */ if (!displayed) return; for (var name in params) { var value = values[name]; switch (params[name].type) { case 'checkbox': var elem = container.querySelector('[name="' + name + '"]'); elem.checked = !!value; break; case 'custom': params[name].set(value, container .querySelector('#__MonkeyConfig_parent_' + name)); break; case 'number': case 'text': var elem = container.querySelector('[name="' + name + '"]'); elem.value = value; break; case 'select': var elem = container.querySelector('[name="' + name + '"]'); if (elem.tagName.toLowerCase() == 'input') { if (elem.type && elem.type == 'radio') { /* Single selection with radio buttons */ elem = container.querySelector( '[name="' + name + '"][value="' + value + '"]'); elem.checked = true; } else if (elem.type && elem.type == 'checkbox') { /* Multiple selection with checkboxes */ var checkboxes = container.querySelectorAll( 'input[name="' + name + '"]'); for (var i = 0; i < checkboxes.length; i++) checkboxes[i].checked = (value.indexOf(checkboxes[i].value) > -1); } } else if (elem.tagName.toLowerCase() == 'select') if (elem.multiple) { /* Multiple selection element */ var options = container.querySelectorAll( 'select[name="' + name + '"] option'); for (var i = 0; i < options.length; i++) options[i].selected = (value.indexOf(options[i].value) > -1); } else /* Single selection element */ elem.value = value; break; } } } /** * Save button click event handler */ function saveClick() { for (name in params) { switch (params[name].type) { case 'checkbox': var elem = container.querySelector('[name="' + name + '"]'); values[name] = elem.checked; break; case 'custom': values[name] = params[name].get(container .querySelector('#__MonkeyConfig_parent_' + name)); break; case 'number': case 'text': var elem = container.querySelector('[name="' + name + '"]'); values[name] = elem.value; break; case 'select': var elem = container.querySelector('[name="' + name + '"]'); if (elem.tagName.toLowerCase() == 'input') { if (elem.type && elem.type == 'radio') /* Single selection with radio buttons */ values[name] = container.querySelector( '[name="' + name + '"]:checked').value; else if (elem.type && elem.type == 'checkbox') { /* Multiple selection with checkboxes */ values[name] = []; var inputs = container.querySelectorAll( 'input[name="' + name + '"]'); for (var i = 0; i < inputs.length; i++) if (inputs[i].checked) values[name].push(inputs[i].value); } } else if (elem.tagName.toLowerCase() == 'select' && elem.multiple) { /* Multiple selection element */ values[name] = []; var options = container.querySelectorAll( 'select[name="' + name + '"] option'); for (var i = 0; i < options.length; i++) if (options[i].selected) values[name].push(options[i].value); } else values[name] = elem.value; break; } } GM_setValue(storageKey, JSON.stringify(values)); close(); location.reload(true); if (data.onSave) data.onSave(values); } /** * Cancel button click event handler */ function cancelClick() { close(); } /** * Set Defaults button click event handler */ function defaultsClick() { setDefaults(); update(); } /** * Open configuration dialog * * @param mode * Display mode ("iframe", "layer", or "window", defaults to * "iframe") * @param options * Display mode options */ function open(mode, options) { function openDone() { /* Attach button event handlers */ var button; if (button = container.querySelector('#__MonkeyConfig_button_save')) button.addEventListener('click', saveClick, true); if (button = container.querySelector('#__MonkeyConfig_button_cancel')) button.addEventListener('click', cancelClick, true); if (button = container.querySelector('#__MonkeyConfig_button_defaults')) button.addEventListener('click', defaultsClick, true); displayed = true; update(); } switch (mode) { case 'window': var windowFeatures = { location: 'no', status: 'no', left: window.screenX, top: window.screenY, width: 100, height: 100 }; /* Additional features may be specified as an option */ if (options && options.windowFeatures) for (var name in options.windowFeatures) windowFeatures[name] = options.windowFeatures[name]; var featuresArray = []; for (var name in windowFeatures) featuresArray.push(name + '=' + windowFeatures[name]); var win = window.open('', data.title, featuresArray.join(',')); /* Find head and body (then call the blood spatter analyst) */ var head = win.document.getElementsByTagName('head')[0], body = win.document.getElementsByTagName('body')[0]; head.innerHTML = '<title>' + data.title + '</title>' + '<style type="text/css">' + MonkeyConfig.res.stylesheets.main + '</style>'; body.className = '__MonkeyConfig_window'; /* Place the rendered configuration dialog inside the window body */ body.innerHTML = render(); /* Find the container (CBAN-3489) */ container = win.document.querySelector('.__MonkeyConfig_container'); /* Resize window to the dimensions of the container div */ win.innerWidth = container.clientWidth; win.resizeBy(0, -win.innerHeight + container.clientHeight); /* Place the window centered relative to the parent */ win.moveBy(Math.round((window.outerWidth - win.outerWidth) / 2), Math.round((window.outerHeight - win.outerHeight) / 2)); openWin = win; openDone(); break; case 'layer': if (!MonkeyConfig.styleAdded) { GM_addStyle(MonkeyConfig.res.stylesheets.main); MonkeyConfig.styleAdded = true; } var body = document.querySelector('body'); /* Create the layer element */ openLayer = document.createElement('div'); openLayer.className = '__MonkeyConfig_layer'; /* Create the overlay */ overlay = document.createElement('div'); overlay.className = '__MonkeyConfig_overlay'; overlay.style.left = 0; overlay.style.top = 0; overlay.style.width = window.innerWidth + 'px'; overlay.style.height = window.innerHeight + 'px'; overlay.style.zIndex = 9999; body.appendChild(overlay); body.appendChild(openLayer); /* * Place the rendered configuration dialog inside the layer element */ openLayer.innerHTML = render(); /* Position the layer in the center of the viewport */ openLayer.style.left = Math.round((window.innerWidth - openLayer.clientWidth) / 2) + 'px'; openLayer.style.top = Math.round((window.innerHeight - openLayer.clientHeight) / 2) + 'px'; openLayer.style.zIndex = 9999; container = document.querySelector('.__MonkeyConfig_container'); openDone(); break; case 'iframe': default: if (!MonkeyConfig.styleAdded) { GM_addStyle(MonkeyConfig.res.stylesheets.main); MonkeyConfig.styleAdded = true; } var body = document.querySelector('body'); var iframe = document.createElement('iframe'); /* Create the layer element */ openLayer = document.createElement('div'); openLayer.className = '__MonkeyConfig_layer'; /* Create the overlay */ overlay = document.createElement('div'); overlay.className = '__MonkeyConfig_overlay'; overlay.style.left = 0; overlay.style.top = 0; overlay.style.width = window.innerWidth + 'px'; overlay.style.height = window.innerHeight + 'px'; overlay.style.zIndex = 9999; iframe.id = '__MonkeyConfig_frame'; /* * Make the iframe transparent so that it remains invisible until * the document inside it is ready */ iframe.style.opacity = 0; iframe.src = 'about:blank'; /* Make the iframe seamless with no border and no scrollbars */ if (undefined !== iframe.frameborder) iframe.frameBorder = '0'; if (undefined !== iframe.scrolling) iframe.scrolling = 'no'; if (undefined !== iframe.seamless) iframe.seamless = true; /* Do the rest in the load event handler */ iframe.addEventListener('load', function () { iframe.contentDocument.body.innerHTML = render(); iframe.style.opacity = 1; /* Append the style to the head */ var head = iframe.contentDocument.querySelector('head'), style = iframe.contentDocument.createElement('style'); style.setAttribute('type', 'text/css'); style.appendChild(iframe.contentDocument.createTextNode( MonkeyConfig.res.stylesheets.main)); head.appendChild(style); var body = iframe.contentDocument.querySelector('body'); body.className = '__MonkeyConfig_body'; container = iframe.contentDocument .querySelector('.__MonkeyConfig_container'); iframe.width = container.clientWidth; iframe.height = container.clientHeight; /* Position the layer in the center of the viewport */ openLayer.style.left = Math.round((window.innerWidth - openLayer.clientWidth) / 2.45) + 'px'; openLayer.style.top = Math.round((window.innerHeight - openLayer.clientHeight) / 2) + 'px'; openLayer.style.zIndex = 9999; openDone(); }, false); setTimeout(function () { iframe.width = container.clientWidth; iframe.height = container.clientHeight; /* Position the layer in the center of the viewport */ openLayer.style.left = Math.round((window.innerWidth - openLayer.clientWidth) / 2) + 'px'; openLayer.style.top = Math.round((window.innerHeight - openLayer.clientHeight) / 2) + 'px'; openLayer.style.zIndex = 9999; }, 0); body.appendChild(overlay); body.appendChild(openLayer); openLayer.appendChild(iframe); break; } } /** * Close configuration dialog */ function close() { if (openWin) { openWin.close(); openWin = undefined; } else if (openLayer) { openLayer.parentNode.removeChild(openLayer); openLayer = undefined; if (overlay) { overlay.parentNode.removeChild(overlay); overlay = undefined; } } displayed = false; } init(arguments[0]); } /** * Replace double quotes with entities so that the string can be safely used * in a HTML attribute * * @param string A string * @returns String with double quotes replaced with entities */ MonkeyConfig.esc = function (string) { return string.replace(/"/g, '"'); }; MonkeyConfig.HTML = { '_field': function (name, options, data) { var html; if (options.type && MonkeyConfig.HTML[options.type]) html = MonkeyConfig.HTML[options.type](name, options, data); else return; if (/\[FIELD\]/.test(options.html)) { html = options.html.replace(/\[FIELD\]/, html); } return html; }, '_label': function (name, options, data) { var label = options['label'] || name.substring(0, 1).toUpperCase() + name.substring(1) .replace(/_/g, ' ') .replace(/é/g, "\u002F") .replace(/0/g, "...") .replace(/1/g, "'"); return '<label for="__MonkeyConfig_field_' + name + '">' + label + '</label>'; }, 'checkbox': function (name, options, data) { return '<input id="__MonkeyConfig_field_' + name + '" type="checkbox" name="' + name + '" />'; }, 'custom': function (name, options, data) { return options.html; }, 'number': function (name, options, data) { return '<input id="__MonkeyConfig_field_' + name + '" ' + 'type="text" class="__MonkeyConfig_field_number" ' + 'name="' + name + '" />'; }, 'select': function (name, options, data) { var choices = {}, html = ''; if (options.choices.constructor == Array) { /* options.choices is an array -- build key/value pairs */ for (var i = 0; i < options.choices.length; i++) choices[options.choices[i]] = options.choices[i]; } else /* options.choices is an object -- use it as it is */ choices = options.choices; if (!options.multiple) { /* Single selection */ if (!/^radio/.test(options.variant)) { /* Select element */ html += '<select id="__MonkeyConfig_field_' + name + '" ' + 'class="__MonkeyConfig_field_select" ' + 'name="' + name + '">'; for (var value in choices) html += '<option value="' + MonkeyConfig.esc(value) + '">' + choices[value] + '</option>'; html += '</select>'; } else { /* Radio buttons */ for (var value in choices) { html += '<label><input type="radio" name="' + name + '" ' + 'value="' + MonkeyConfig.esc(value) + '" /> ' + choices[value] + '</label>' + (/ column/.test(options.variant) ? '<br />' : ''); } } } else { /* Multiple selection */ if (!/^checkbox/.test(options.variant)) { /* Checkboxes */ html += '<select id="__MonkeyConfig_field_' + name + '" ' + 'class="__MonkeyConfig_field_select" ' + 'multiple="multiple" ' + 'name="' + name + '">'; for (var value in choices) html += '<option value="' + MonkeyConfig.esc(value) + '">' + choices[value] + '</option>'; html += '</select>'; } else { /* Select element */ for (var value in choices) { html += '<label><input type="checkbox" ' + 'name="' + name + '" ' + 'value="' + MonkeyConfig.esc(value) + '" /> ' + choices[value] + '</label>' + (/ column/.test(options.variant) ? '<br />' : ''); } } } return html; }, 'text': function (name, options, data) { if (options.long) return '<textarea id="__MonkeyConfig_field_' + name + '" ' + 'class="__MonkeyConfig_field_text" ' + (!isNaN(options.long) ? 'rows="' + options.long + '" ' : '') + 'name="' + name + '"></textarea>'; else return '<input id="__MonkeyConfig_field_' + name + '" ' + 'type="text" class="__MonkeyConfig_field_text" ' + 'name="' + name + '" />'; } }; MonkeyConfig.formatters = { 'tr': function (name, options, data) { var html = '<tr>'; switch (options.type) { case 'checkbox': /* Checkboxes get special treatment */ html += '<td id="__MonkeyConfig_parent_' + name + '" colspan="2">'; html += MonkeyConfig.HTML['_field'](name, options, data) + ' '; html += MonkeyConfig.HTML['_label'](name, options, data); html += '</td>'; break; default: html += '<td>'; html += MonkeyConfig.HTML['_label'](name, options, data); html += '</td><td id="__MonkeyConfig_parent_' + name + '">'; html += MonkeyConfig.HTML['_field'](name, options, data); html += '</td>'; break; } html += '</tr>'; return html; } }; /* Has the stylesheet been added? */ MonkeyConfig.styleAdded = false; /* Resources */ MonkeyConfig.res = {}; /* Icons */ MonkeyConfig.res.icons = { 'arrow_undo': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\ U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIJSURBVDjLpVM9aJNRFD35GsRSoUKKzQ/B\ 0NJJF3EQlKrVgijSCBmC4NBFKihIcXBwEZdSHVoUwUInFUEkQ1DQ4CKiFsQsTrb5xNpgaZHw2Uog\ 5t5zn0NJNFaw0guX97hwzuPcc17IOYfNlIdNVrhxufR6xJkZjAbSQGXjNAorqixSWFDV3KPhJ+UG\ LtSQMPryrDscPwLnAHOEOQc6gkbUpIagGmApWIb/pZRX4fjj889nWiSQtgYyBZ1BTUEj6AjPa0P7\ 1nb0Jfqwa+futIheHrzRn2yRQCUK/lOQhApBJVQJChHfnkCqOwWEQ+iORJHckUyX5ksvAEyGNuJC\ +s6xCRXNHNxzKMmQ4luwgjfvZp69uvr2+IZcyJ8rjIporrxURggetnV0QET3rrPxzMNM2+n7p678\ jUTrCiWhphAjVHR9DlR0WkSzf4IHxg5MSF0zXZEuVKWKSlCBCostS8zeG7oV64wPqxInbw86lbVX\ KEQ8mkAqmUJ4SxieeVhcnANFC02C7N2h69HO2IXeWC8MDj2JnqaFNAMd8f3HKjx6+LxQRmnOz1OZ\ axKIaF1VISYwB9ARZoQaYY6o1WpYCVYxt+zDn/XzVBv/MOWXW5J44ubRyVgkelFpmF/4BJVfOVDl\ VyqLVBZI5manPjajDOdcswfG9k/3X9v3/vfZv7rFBanriIo++J/f+BMT+YWS6hXl7QAAAABJRU5E\ rkJggg==', 'cancel': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\ U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHdSURBVDjLpZNraxpBFIb3a0ggISmmNISW\ XmOboKihxpgUNGWNSpvaS6RpKL3Ry//Mh1wgf6PElaCyzq67O09nVjdVlJbSDy8Lw77PmfecMwZg\ /I/GDw3DCo8HCkZl/RlgGA0e3Yfv7+DbAfLrW+SXOvLTG+SHV/gPbuMZRnsyIDL/OASziMxkkKkU\ QTJJsLaGn8/iHz6nd+8mQv87Ahg2H9Th/BxZqxEkEgSrq/iVCvLsDK9awtvfxb2zjD2ARID+lVVl\ babTgWYTv1rFL5fBUtHbbeTJCb3EQ3ovCnRC6xAgzJtOE+ztheYIEkqbFaS3vY2zuIj77AmtYYDu\ sPy8/zuvunJkDKXM7tYWTiyGWFjAqeQnAD6+7ueNx/FLpRGAru7mcoj5ebqzszil7DggeF/DX1nB\ N82rzPqrzbRayIsLhJqMPT2N83Sdy2GApwFqRN7jFPL0tF+10cDd3MTZ2AjNUkGCoyO6y9cRxfQo\ wFUbpufr1ct4ZoHg+Dg067zduTmEbq4yi/UkYidDe+kaTcP4ObJIajksPd/eyx3c+N2rvPbMDPbU\ FPZSLKzcGjKPrbJaDsu+dQO3msfZzeGY2TCvKGYQhdSYeeJjUt21dIcjXQ7U7Kv599f4j/oF55W4\ g/2e3b8AAAAASUVORK5CYII=', 'tick': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\ U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLvZPZLkNhFIV75zjvYm7VGFNC\ qoZUJ+roKUUpjRuqp61Wq0NKDMelGGqOxBSUIBKXWtWGZxAvobr8lWjChRgSF//dv9be+9trCwAI\ /vIE/26gXmviW5bqnb8yUK028qZjPfoPWEj4Ku5HBspgAz941IXZeze8N1bottSo8BTZviVWrEh5\ 46EO03EXpuJOdG63otJbjBKHkEp/Ml6yNYYzpuezWL4s5VMtT8acCMQcb5XL3eJE8VgBlR7BeMGW\ 9Z4yT9y1CeyucuhdTGDxfftaBO7G4L+zg91UocxVmCiy51NpiP3n2treUPujL8xhOjYOzZYsQWAN\ yRYlU4Y9Br6oHd5bDh0bCpSOixJiWx71YY09J5pM/WEbzFcDmHvwwBu2wnikg+lEj4mwBe5bC5h1\ OUqcwpdC60dxegRmR06TyjCF9G9z+qM2uCJmuMJmaNZaUrCSIi6X+jJIBBYtW5Cge7cd7sgoHDfD\ aAvKQGAlRZYc6ltJlMxX03UzlaRlBdQrzSCwksLRbOpHUSb7pcsnxCCwngvM2Rm/ugUCi84fycr4\ l2t8Bb6iqTxSCgNIAAAAAElFTkSuQmCC' }; /* Stylesheets */ MonkeyConfig.res.stylesheets = { 'main': '\ body.__MonkeyConfig_window {\ appearance: window !important;\ -moz-appearance: window !important;\ background: auto;\ font-family: sans-serif !important;\ height: 100% !important;\ margin: 0 !important;\ padding: 0 !important;\ width: 100% !important;\ }\ \ div.__MonkeyConfig_container {\ display: table !important;\ font-family: sans-serif !important;\ padding: 0.3em !important;\ }\ \ body.__MonkeyConfig_window div.__MonkeyConfig_container {\ appearance: window !important;\ -moz-appearance: window !important;\ height: 100%;\ width: 100%;\ }\ \ div.__MonkeyConfig_container h1 {\ border-bottom: solid 1px #999 !important;\ font-family: sans-serif !important;\ font-size: 120% !important;\ margin: 0 !important;\ padding: 0 0 0.3em 0 !important;\ }\ \ div.__MonkeyConfig_container table {\ border-spacing: 0 !important;\ margin: 0 !important;\ }\ \ div.__MonkeyConfig_container table td {\ border: none !important;\ line-height: 100% !important;\ padding: 0.3em !important;\ text-align: left !important;\ vertical-align: top !important;\ white-space: nowrap !important;\ }\ \ div.__MonkeyConfig_container table td.__MonkeyConfig_buttons {\ padding: 0.2em 0 !important;\ }\ \ .__MonkeyConfig_field_number {\ width: 5em !important;\ }\ \ div.__MonkeyConfig_container td.__MonkeyConfig_buttons table {\ border-top: solid 1px #999 !important;\ width: 100% !important;\ }\ \ div.__MonkeyConfig_container td.__MonkeyConfig_buttons td {\ padding: 0.6em 0.3em 0.1em 0.3em !important;\ text-align: center !important;\ vertical-align: top;\ }\ \ div.__MonkeyConfig_container td.__MonkeyConfig_buttons button {\ appearance: button !important;\ -moz-appearance: button !important;\ background-position: 8px 50% !important;\ background-repeat: no-repeat !important;\ padding: 3px 8px 3px 24px !important;\ padding: 3px 8px !important;\ white-space: nowrap !important;\ }\ \ div.__MonkeyConfig_container td.__MonkeyConfig_buttons button img {\ vertical-align: middle !important;\ }\ \ div.__MonkeyConfig_layer {\ display: table !important;\ position: fixed !important;\ }\ \ div.__MonkeyConfig_layer div.__MonkeyConfig_container,\ body.__MonkeyConfig_body > div.__MonkeyConfig_container {\ background: #eee linear-gradient(180deg,\ #f8f8f8 0, #ddd 100%) !important;\ border-radius: 0.5em !important;\ box-shadow: 2px 2px 16px #000 !important;\ color: #000 !important;\ font-family: sans-serif !important;\ font-size: 11pt !important;\ padding: 1em 1em 0.4em 1em !important;\ }\ \ div.__MonkeyConfig_layer div.__MonkeyConfig_container td,\ div.__MonkeyConfig_layer div.__MonkeyConfig_container label,\ div.__MonkeyConfig_layer div.__MonkeyConfig_container input,\ div.__MonkeyConfig_layer div.__MonkeyConfig_container select,\ div.__MonkeyConfig_layer div.__MonkeyConfig_container textarea,\ div.__MonkeyConfig_layer div.__MonkeyConfig_container button {\ color: #000 !important;\ font-family: sans-serif !important;\ font-size: 11pt !important;\ line-height: 100% !important;\ margin: 0 !important;\ vertical-align: baseline !important;\ }\ \ div.__MonkeyConfig_container label {\ line-height: 120% !important;\ vertical-align: baseline !important;\ }\ \ div.__MonkeyConfig_container textarea {\ vertical-align: text-top !important;\ width: 100%;\ }\ \ div.__MonkeyConfig_layer div.__MonkeyConfig_container input[type="text"] {\ appearance: textfield !important;\ -moz-appearance: textfield !important;\ background: #fff !important;\ }\ \ div.__MonkeyConfig_layer div.__MonkeyConfig_container h1 {\ font-weight: bold !important;\ text-align: left !important;\ }\ \ div.__MonkeyConfig_layer div.__MonkeyConfig_container td.__MonkeyConfig_buttons button,\ body > div.__MonkeyConfig_container td.__MonkeyConfig_buttons button {\ appearance: button !important;\ -moz-appearance: button !important;\ background: #ccc linear-gradient(180deg,\ #ddd 0, #ccc 45%, #bbb 50%, #aaa 100%) !important;\ border-style: solid !important;\ border-width: 1px !important;\ border-radius: 0.5em !important;\ box-shadow: 0 0 1px #000 !important;\ color: #000 !important;\ font-size: 11pt !important;\ }\ \ div.__MonkeyConfig_layer div.__MonkeyConfig_container td.__MonkeyConfig_buttons button:hover,\ body > div.__MonkeyConfig_container td.__MonkeyConfig_buttons button:hover {\ background: #d2d2d2 linear-gradient(180deg,\ #e2e2e2 0, #d2d2d2 45%, #c2c2c2 50%, #b2b2b2 100%) !important;\ }\ \ div.__MonkeyConfig_overlay {\ background-color: #000 !important;\ opacity: 0.6 !important;\ position: fixed !important;\ }\ \ iframe#__MonkeyConfig_frame {\ border: none !important;\ box-shadow: 2px 2px 16px #000 !important;\ }\ \ body.__MonkeyConfig_body {\ margin: 0 !important;\ padding: 0 !important;\ }\ \ embed, iframe, object {\ max-width: 200% !important;\ width: 167% !important;\ }\ ' };