返回首頁 

GreasyFork: download script button

If you have a script manager and you want to download some script without installing it, this script will help

< Обсуждения: GreasyFork: download script button

Отзыв: Хороший — скрипт работает как нужно

Hello,

With the latest version 2.1.4 of your script, I always get this error message to download a userscript or a userstyle like the screenshots show :-(

image

image

image

Thank you for your answer.

Google Chrome Browser with Tampermonkey and Violentmonkey

I'll check it out. Is there are any messenger I can reach you to debug the problem faster?

Nevermind. It seems like the problem is general, I also have it. It's because of changes on the website... I'll see what I can do

Uhmm... I did nothing and it works for me again. I'm confused

Incredible, I just tested again and it's always the same on my side 😲

Do you use discord or something where I can text you? As long as I can't reproduce the problem on my side, I can't fix it

Yes by e-mail, because I don't have a social network.

Ok let's stick with this place for now. I need some screenshots or recording that is showing what is the reason of the error. I need something like this: https://streamable.com/fj29le

It's my video where I'm just offline trying to download something. It would be great if you can make something similar and upload it using the same video share service or maybe some better one because this is kinda shit, loses video quality

Show the exact things I'm showing on the video

I've made some changes, but I have no idea if they would have any impact or not. Test this:

// ==UserScript==// @name          GreasyFork: download script button// @description   If you have a script manager and you want to download some script without installing it, this script will help// @author        Konf// @version       2.1.5a// @namespace     https://greasyfork.org/users/424058// @icon          https://greasyfork.org/vite/assets/blacklogo96-e0c2c761.png// @match         https://greasyfork.org/*/scripts/*// @match         https://sleazyfork.org/*/scripts/*// @connect       update.greasyfork.org// @compatible    Chrome// @compatible    Opera// @compatible    Firefox// @run-at        document-end// @grant         GM_addStyle// @grant         GM_xmlhttpRequest// @noframes// ==/UserScript==/* jshint esversion: 8 */(function() {'use strict';const i18n = {download: 'download',downloadWithoutInstalling: 'downloadWithoutInstalling',failedToDownload: 'failedToDownload',};const translate = (function() {const userLang = location.pathname.split('/')[1];const strings = {'en': {[i18n.download]: 'Download ⇩',[i18n.downloadWithoutInstalling]: 'Download without installing',[i18n.failedToDownload]:'Failed to download the script. There is might be more info in the browser console',},'ru': {[i18n.download]: 'Скачать ⇩',[i18n.downloadWithoutInstalling]: 'Скачать не устанавливая',[i18n.failedToDownload]:'Не удалось скачать скрипт. Больше информации может быть в консоли браузера',},'zh-CN': {[i18n.download]: '下载 ⇩',[i18n.downloadWithoutInstalling]: '下载此脚本',[i18n.failedToDownload]: '无法下载此脚本',},};return id => (strings[userLang] || strings.en)[id] || strings.en[id];}());const installBtns = document.querySelectorAll('a.install-link');const installArea = document.querySelector('div#install-area');const installHelpLinks = document.querySelectorAll('a.install-help-link');const suggestion = document.querySelector('div#script-feedback-suggestion');const libraryRequire = document.querySelector('div#script-content > p > code');// if a script/style is detectedif (installArea &&(installBtns.length > 0) &&(installBtns.length === installHelpLinks.length)) {for (let i = 0; i < installBtns.length; i++) {mountScriptDownloadButton(installBtns[i], installArea, installHelpLinks[i]);}}// or maybe a libraryelse if (suggestion && libraryRequire) {mountLibraryDownloadButton(suggestion, libraryRequire);}function mountScriptDownloadButton(installBtn,installArea,installHelpLink,) {if (!installBtn.href) throw new Error('script href is not found');// https://img.icons8.com/pastel-glyph/64/ffffff/download.png// array to fold the string in a code editorconst downloadIconBase64 = ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaX','HeAAAABmJLR0QA/wD/AP+gvaeTAAABgUlEQVR4nO3ZTU6DUAAE4HnEk+jWG3TrHV','wY3XoEt23cGleamtRtTbyPS3sCV0b###tHRAIEsM/hZ76kCZRHGaZAGwDMzMzMbJ','6CasMkMwBncXYbQvhSZZEgecEf56ocmWrDAA4L00eqEMoCBsEFqAOouQB1ADUXoA','6g5gLUAdRcgDqAmgtQB1BzAeoAakkLIHlN8pPkDcnWd59IBpK3cd1VyoxJkfwo3P','V5KJZAcllYtiy8H+LY3HvKjKlPgU1h+hLAuulIiMvWcWzVZ4xL/Dbv+Nsjyax8BM','Sx96Wxm3jzdLwaSliVCpjezucqzmuSfKuZJkvXi0moORKqTOebL2tRwnR3PtdQwv','R3PldRgmznlc8GA4DTOPscQqAqy6x1+X8+6Ke5yfNxIE9z6/TN1+XCM4inuQ165Z','vHz04DF6AOoOYC1AHUXIA6gNpBz/UWJK/2muTvFn1W6lvASXyNXpdTYJcsxf69th','3Y5QjYAiCA485x/tcL###1CDMzMzMbum8+xtkWw6QCvwAAAABJRU5ErkJggg==',].join('');GM_addStyle([`.GF-DSB__script-download-button {position: relative;padding: 8px 22px;cursor: pointer;border: none;background: #0F750F;transition: box-shadow 0.2s;}.GF-DSB__script-download-button:hover,.GF-DSB__script-download-button:focus {box-shadow: 0 8px 16px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%);}.GF-DSB__script-download-icon {position: absolute;}.GF-DSB__script-download-icon--download {width: 30px;height: 30px;top: 4px;left: 7px;}.GF-DSB__script-download-icon--loading,.GF-DSB__script-download-icon--loading:after {border-radius: 50%;width: 16px;height: 16px;}.GF-DSB__script-download-icon--loading {top: 8px;left: 11px;border-top: 3px solid rgba(255, 255, 255, 0.2);border-right: 3px solid rgba(255, 255, 255, 0.2);border-bottom: 3px solid rgba(255, 255, 255, 0.2);border-left: 3px solid #ffffff;transform: translateZ(0);object-position: -99999px;animation: GF-DSB__script-download-loading-icon 1.1s infinite linear;}@keyframes GF-DSB__script-download-loading-icon {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}}`][0]);const b = document.createElement('a');const bIcon = document.createElement('img');b.href = '#';b.title = translate(i18n.downloadWithoutInstalling);b.draggable = false;b.className = 'GF-DSB__script-download-button';bIcon.src = downloadIconBase64;bIcon.draggable = false;bIcon.className ='GF-DSB__script-download-icon GF-DSB__script-download-icon--download';installHelpLink.style.position = 'relative'; // shadows bugfixb.appendChild(bIcon);installArea.insertBefore(b, installHelpLink);// against doubleclickslet isFetchingAllowed = true;async function clicksHandler(ev) {ev.preventDefault();setTimeout(() => b === document.activeElement && b.blur(), 250);if (isFetchingAllowed === false) return;isFetchingAllowed = false;bIcon.className ='GF-DSB__script-download-icon GF-DSB__script-download-icon--loading';try {await downloadScript({fileExt: `.user.${installBtn.dataset.installFormat || 'txt'}`,href: installBtn.href,name: installBtn.dataset.scriptName,});} catch (e) {console.error(e);alert(`${translate(i18n.failedToDownload)}: \n${e}`);} finally {setTimeout(() => {isFetchingAllowed = true;bIcon.className ='GF-DSB__script-download-icon GF-DSB__script-download-icon--download';}, 300);}}b.addEventListener('click', clicksHandler);b.addEventListener('auxclick', e => e.button === 1 && clicksHandler(e));}function mountLibraryDownloadButton(suggestion, libraryRequire) {const [libraryHref,libraryName,] = libraryRequire.innerText.match(/\/\/ @require (https:\/\/.+\/scripts\/\d+\/\d+\/(.*)\.js)/).slice(1);// this probably is completely useless but whateverif (!libraryHref) throw new Error('library href is not found');GM_addStyle([`.GF-DSB__library-download-button {transition: box-shadow 0.2s;}.GF-DSB__library-download-button--loading {animation: GF-DSB__loading-text 1s infinite linear;}@keyframes GF-DSB__loading-text {50% {opacity: 0.4;}}`][0]);const b = document.createElement('a');b.href = '#';b.draggable = false;b.innerText = translate(i18n.download);b.className = 'GF-DSB__library-download-button';suggestion.appendChild(b);// against doubleclickslet isFetchingAllowed = true;async function clicksHandler(ev) {ev.preventDefault();setTimeout(() => b === document.activeElement && b.blur(), 250);if (isFetchingAllowed === false) return;isFetchingAllowed = false;b.className ='GF-DSB__library-download-button GF-DSB__library-download-button--loading';try {await downloadScript({fileExt: '.js',href: libraryHref,name: libraryName,});} catch (e) {console.error(e);alert(`${translate(i18n.failedToDownload)}: \n${e}`);} finally {setTimeout(() => {isFetchingAllowed = true;b.className = 'GF-DSB__library-download-button';}, 300);}}b.addEventListener('click', clicksHandler);b.addEventListener('auxclick', e => e.button === 1 && clicksHandler(e));}// utils --------------------------------------------------------------------async function downloadScript({fileExt = '.txt',href,name = Date.now(),} = {}) {if (!href) throw new Error('href is missing');const r###lt = await GM.xmlHttpRequest({ url: href });if (r###lt.status !== 200) {throw new Error(`Bad response: ${r###lt.status}`);}const blob = new Blob([r###lt.response], { type: 'text/plain' });const url = window.URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = `${name}${fileExt}`;document.body.appendChild(a); // is needed due to firefox buga.click();a.remove();window.URL.revokeObjectURL(url);}}());

Hello,

Sorry for my late reply.

Unfortunately, there are the problems in this version 2.1.5a on my side :-(

image

image

Was that Tampermonkey? If it was not, could you try it? Also what is the Chrome version?

This Tampermonkey version 5 for Google Chrome -> https://chromewebstore.google.com/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo
As I'm running Windows 8.1, Google Chrome forced me to stay on their version 109 :-(

KonfАвтор
Создано: 19.12.2023
Изменено: 19.12.2023

version 109

Ok, I'll check this out a bit later. I'll make one more script version to test

However the versions 1.2.3 and 2.0.0 work always very well :-)

Got it. I'll get this 109 and would fix the script latest version for it

This is so weird that I don't have any of these errors on 109 as well. I guess I'll just try something in blind

Can you tell the exact version? Somewhere in 3-dot menu then About or something like that

chrome://settings/helpI have 109.0.5414.0 for example

The Version 109.0.5414.168 (Build officiel) (64 bits)

KonfАвтор
Создано: 19.12.2023
Изменено: 19.12.2023

Try this. If this works, I'll release it then, and you would need to reinstall it from the script page in order to be able to receive a next updates automatically

// ==UserScript==// @name          GreasyFork: download script button// @description   If you have a script manager and you want to download some script without installing it, this script will help// @author        Konf// @version       2.1.5b// @namespace     https://greasyfork.org/users/424058// @icon          https://greasyfork.org/vite/assets/blacklogo96-e0c2c761.png// @match         https://greasyfork.org/*/scripts/*// @match         https://sleazyfork.org/*/scripts/*// @compatible    Chrome// @compatible    Opera// @compatible    Firefox// @run-at        document-end// @grant         GM_addStyle// @noframes// ==/UserScript==/* jshint esversion: 8 */(function() {'use strict';const i18n = {download: 'download',downloadWithoutInstalling: 'downloadWithoutInstalling',failedToDownload: 'failedToDownload',};const translate = (function() {const userLang = location.pathname.split('/')[1];const strings = {'en': {[i18n.download]: 'Download ⇩',[i18n.downloadWithoutInstalling]: 'Download without installing',[i18n.failedToDownload]:'Failed to download the script. There is might be more info in the browser console',},'ru': {[i18n.download]: 'Скачать ⇩',[i18n.downloadWithoutInstalling]: 'Скачать не устанавливая',[i18n.failedToDownload]:'Не удалось скачать скрипт. Больше информации может быть в консоли браузера',},'zh-CN': {[i18n.download]: '下载 ⇩',[i18n.downloadWithoutInstalling]: '下载此脚本',[i18n.failedToDownload]: '无法下载此脚本',},};return id => (strings[userLang] || strings.en)[id] || strings.en[id];}());const installBtns = document.querySelectorAll('a.install-link');const installArea = document.querySelector('div#install-area');const installHelpLinks = document.querySelectorAll('a.install-help-link');const suggestion = document.querySelector('div#script-feedback-suggestion');const libraryRequire = document.querySelector('div#script-content > p > code');// if a script/style is detectedif (installArea &&(installBtns.length > 0) &&(installBtns.length === installHelpLinks.length)) {for (let i = 0; i < installBtns.length; i++) {mountScriptDownloadButton(installBtns[i], installArea, installHelpLinks[i]);}}// or maybe a libraryelse if (suggestion && libraryRequire) {mountLibraryDownloadButton(suggestion, libraryRequire);}function mountScriptDownloadButton(installBtn,installArea,installHelpLink,) {if (!installBtn.href) throw new Error('script href is not found');// https://img.icons8.com/pastel-glyph/64/ffffff/download.png// array to fold the string in a code editorconst downloadIconBase64 = ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaX','HeAAAABmJLR0QA/wD/AP+gvaeTAAABgUlEQVR4nO3ZTU6DUAAE4HnEk+jWG3TrHV','wY3XoEt23cGleamtRtTbyPS3sCV0b###tHRAIEsM/hZ76kCZRHGaZAGwDMzMzMbJ','6CasMkMwBncXYbQvhSZZEgecEf56ocmWrDAA4L00eqEMoCBsEFqAOouQB1ADUXoA','6g5gLUAdRcgDqAmgtQB1BzAeoAakkLIHlN8pPkDcnWd59IBpK3cd1VyoxJkfwo3P','V5KJZAcllYtiy8H+LY3HvKjKlPgU1h+hLAuulIiMvWcWzVZ4xL/Dbv+Nsjyax8BM','Sx96Wxm3jzdLwaSliVCpjezucqzmuSfKuZJkvXi0moORKqTOebL2tRwnR3PtdQwv','R3PldRgmznlc8GA4DTOPscQqAqy6x1+X8+6Ke5yfNxIE9z6/TN1+XCM4inuQ165Z','vHz04DF6AOoOYC1AHUXIA6gNpBz/UWJK/2muTvFn1W6lvASXyNXpdTYJcsxf69th','3Y5QjYAiCA485x/tcL###1CDMzMzMbum8+xtkWw6QCvwAAAABJRU5ErkJggg==',].join('');GM_addStyle([`.GF-DSB__script-download-button {position: relative;padding: 8px 22px;cursor: pointer;border: none;background: #0F750F;transition: box-shadow 0.2s;}.GF-DSB__script-download-button:hover,.GF-DSB__script-download-button:focus {box-shadow: 0 8px 16px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%);}.GF-DSB__script-download-icon {position: absolute;}.GF-DSB__script-download-icon--download {width: 30px;height: 30px;top: 4px;left: 7px;}.GF-DSB__script-download-icon--loading,.GF-DSB__script-download-icon--loading:after {border-radius: 50%;width: 16px;height: 16px;}.GF-DSB__script-download-icon--loading {top: 8px;left: 11px;border-top: 3px solid rgba(255, 255, 255, 0.2);border-right: 3px solid rgba(255, 255, 255, 0.2);border-bottom: 3px solid rgba(255, 255, 255, 0.2);border-left: 3px solid #ffffff;transform: translateZ(0);object-position: -99999px;animation: GF-DSB__script-download-loading-icon 1.1s infinite linear;}@keyframes GF-DSB__script-download-loading-icon {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}}`][0]);const b = document.createElement('a');const bIcon = document.createElement('img');b.href = '#';b.title = translate(i18n.downloadWithoutInstalling);b.draggable = false;b.className = 'GF-DSB__script-download-button';bIcon.src = downloadIconBase64;bIcon.draggable = false;bIcon.className ='GF-DSB__script-download-icon GF-DSB__script-download-icon--download';installHelpLink.style.position = 'relative'; // shadows bugfixb.appendChild(bIcon);installArea.insertBefore(b, installHelpLink);// against doubleclickslet isFetchingAllowed = true;async function clicksHandler(ev) {ev.preventDefault();setTimeout(() => b === document.activeElement && b.blur(), 250);if (isFetchingAllowed === false) return;isFetchingAllowed = false;bIcon.className ='GF-DSB__script-download-icon GF-DSB__script-download-icon--loading';try {await downloadScript({fileExt: `.user.${installBtn.dataset.installFormat || 'txt'}`,href: installBtn.href,name: installBtn.dataset.scriptName,});} catch (e) {console.error(e);alert(`${translate(i18n.failedToDownload)}: \n${e}`);} finally {setTimeout(() => {isFetchingAllowed = true;bIcon.className ='GF-DSB__script-download-icon GF-DSB__script-download-icon--download';}, 300);}}b.addEventListener('click', clicksHandler);b.addEventListener('auxclick', e => e.button === 1 && clicksHandler(e));}function mountLibraryDownloadButton(suggestion, libraryRequire) {const [libraryHref,libraryName,] = libraryRequire.innerText.match(/\/\/ @require (https:\/\/.+\/scripts\/\d+\/\d+\/(.*)\.js)/).slice(1);// this probably is completely useless but whateverif (!libraryHref) throw new Error('library href is not found');GM_addStyle([`.GF-DSB__library-download-button {transition: box-shadow 0.2s;}.GF-DSB__library-download-button--loading {animation: GF-DSB__loading-text 1s infinite linear;}@keyframes GF-DSB__loading-text {50% {opacity: 0.4;}}`][0]);const b = document.createElement('a');b.href = '#';b.draggable = false;b.innerText = translate(i18n.download);b.className = 'GF-DSB__library-download-button';suggestion.appendChild(b);// against doubleclickslet isFetchingAllowed = true;async function clicksHandler(ev) {ev.preventDefault();setTimeout(() => b === document.activeElement && b.blur(), 250);if (isFetchingAllowed === false) return;isFetchingAllowed = false;b.className ='GF-DSB__library-download-button GF-DSB__library-download-button--loading';try {await downloadScript({fileExt: '.js',href: libraryHref,name: libraryName,});} catch (e) {console.error(e);alert(`${translate(i18n.failedToDownload)}: \n${e}`);} finally {setTimeout(() => {isFetchingAllowed = true;b.className = 'GF-DSB__library-download-button';}, 300);}}b.addEventListener('click', clicksHandler);b.addEventListener('auxclick', e => e.button === 1 && clicksHandler(e));}// utils --------------------------------------------------------------------// Is needed because you can't fetch a new format script link// due to different domain cors restriction...function convertScriptHrefToAnOldFormat(href) {const regex = /https:\/\/update\.(\w+\.org)\/scripts\/(\d+)\/(\d+\/)?(.+)/;const match = href.match(regex);if (!match) throw new Error("can't convert href to an old format");const domain = match[1];const scriptId = match[2];const version = match[3] ? `?version=${match[3]}` : '';const scriptName = match[4];return `https://${domain}/scripts/${scriptId}/code/${scriptName}${version}`;}async function downloadScript({fileExt = '.txt',href,name = Date.now(),} = {}) {if (!href) throw new Error('Script href is missing');const fetchErrors = [];let url;// Consider first attempt as a main one. Second one is// needed just for some unknown edge case scenarios. See link:// https://greasyfork.org/scripts/420872/discussions/216921for (const scriptHref of [convertScriptHrefToAnOldFormat(href),href,]) {try {const response = await fetch(scriptHref);if (response.status !== 200) {throw new Error(`Bad response: ${response.status}`);}url = window.URL.createObjectURL(await response.blob());} catch (e) {fetchErrors.push(e);}}if (!url) {fetchErrors.forEach(e => console.error(e));throw new Error('Failed to fetch. See console');}const a = document.createElement('a');a.href = url;a.download = `${name}${fileExt}`;document.body.appendChild(a); // is needed due to firefox buga.click();a.remove();window.URL.revokeObjectURL(url);}}());

Finally it works very well with this version 2.1.5b, here's the proof in a screenshot :-)

image

In additon, do you think that it's also possible to add the version number directly to the backup please ?

-> Remove YouTube Movie Purchase 1.0.1.user.js instead of Remove YouTube Movie Purchase.user.js

-> Remove YouTube Movie Purchase 1.0.1.user.css instead of Remove YouTube Movie Purchase.user.css

This way it's direct and you don't have to do it manually every time because it saves time...

Yeah, makes sense. I'll see how this could be done

2.2.6 has been released. Thanks for your help

Very good, your script is really much better and efficace now and I hope it helps everyone including you.

Thank you very much for your time, work, understanding and kindness ;-)

Hello again,

Sorry for the inconvenience, but do you think that it's possible to run your script on the web archive pages https://archive.org/ or https://web.archive.org/ also please ?
Because some scripts are suddenly removed on Greasy Fork...

For example, I wanted to install this script again, but I have just seen that it removed O_O
However, it's still in the web archive and it can be installed from there :
-> http://web.archive.org/web/20240000000000*/https://greasyfork.org/scripts/456108
-> http://web.archive.org/web/20240302053247/https://greasyfork.org/scripts/456108

In Violentmonkey, there is no option to save scripts unless I'm mistaken and it saves time to save it directly from the web archive instead of always using Tampermonkey :-)


Thank you for your answer.

I'll take a look... If it's not too complicated I'll make it

Okay, because it can really be useful for everyone :-)

I'm not sure how reliable and bugless is this, but it's done

Didn't want to spend a lot of time on it

After spending some time for testing, it's worked perfectly so far (even with the link quoted above this morning) for the archive web links which were updated after the Greasy Fork changes of November 2023 -> https://github.com/Tampermonkey/tampermonkey/issues/1904.
But for the others archive web links before that date, it doesn't work.

I wish to respect your choice, so I don't want to bother you more.

You can indicate on the info page of your script that it also works for the archive web links, because it's really very useful and it can really help everyone.

Thank you very much for all and good courage for the future ;-)

KonfАвтор
Создано: 29.05.2024
Изменено: 29.05.2024

Tested these two and it worked:

https://web.archive.org/web/20220617141313/https://greasyfork.org/ar/scripts/10002-cookie-clicker%E3%81%AE%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E6%A9%9F%E8%83%BD%E3%82%92%E8%87%AA%E5%8B%95%E5%8C%96

https://web.archive.org/web/20220801122250/https://greasyfork.org/bg/scripts/408643-%E5%8B%95%E7%95%AB%E7%98%8B-%E8%87%AA%E5%8B%95%E8%A7%80%E7%9C%8B%E5%BB%A3%E5%91%8A

If you can't download these it's probably because of your browser weird behavior again. I can see why this might be happening but need to test it from your side, then think how to make it using another approach.. Ugh

Yeah this one doesn't work indeed. There was a different website layout at that time. Looking into a solution

Fixed. The 2.3.0 version you've been using today has been downloading scripts with a WebArchive metadata. I think the WebArchive is, by default, appending some code to all the files it hosts. In order to get a pure file a bit different request is needed. This was fixed in 2.3.1 and all the scripts you've downloaded with 2.3.0 are might be broken and not work properly

Remember this new download from WebArchive feature has been done hastily and might not work well

But if it works now, it's good. You can't really guarantee for a long time a proper work of ANY userscript anyways

But if it works now, it's good. You can't really guarantee for a long time a proper work of ANY userscript anyways

Thank you so much again for all your work and yes I understand perfectly :-)

Ответить

Войдите, чтобы ответить.