GreasyFork: download script button

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

Versión del día 22/1/2022. Echa un vistazo a la versión más reciente.

  1. // ==UserScript==
  2. // @name GreasyFork: download script button
  3. // @description If you have a script manager and you want to download some script without installing it, this script will help
  4. // @author Konf
  5. // @version 1.2.3
  6. // @namespace https://greatest.deepsurf.us/users/424058
  7. // @icon https://greatest.deepsurf.us/packs/media/images/blacklogo16-5421a97c75656cecbe2befcec0778a96.png
  8. // @icon64 https://greatest.deepsurf.us/packs/media/images/blacklogo96-b2384000fca45aa17e45eb417cbcbb59.png
  9. // @include /^http(s|):\/\/(sleaz|greas)yfork\.org\/[a-zA-Z_-]*\/scripts\/\d.*$/
  10. // @compatible Chrome
  11. // @compatible Opera
  12. // @compatible Firefox
  13. // @run-at document-end
  14. // @grant GM_addStyle
  15. // @noframes
  16. // ==/UserScript==
  17.  
  18. /* jshint esversion: 6 */
  19. /* eslint-disable no-multi-spaces */
  20.  
  21. (function() {
  22. 'use strict';
  23.  
  24. const langStrings = (function() {
  25. const userLang = location.pathname.split('/')[1];
  26. const langStringsList = {
  27. 'en': {
  28. Dl: 'Download without installing',
  29. failedDl: 'Failed to download the script. ' +
  30. 'More info might be in the browser console'
  31. },
  32. 'zh-CN': {
  33. Dl: '下载此脚本',
  34. failedDl: '无法下载此脚本'
  35. },
  36. 'ru': {
  37. Dl: 'Скачать не устанавливая',
  38. failedDl: 'Не удалось скачать скрипт. ' +
  39. 'Больше информации может быть в консоли браузера'
  40. }
  41. };
  42.  
  43. return function(id) {
  44. const userStrings = langStringsList[userLang];
  45. const enStrings = langStringsList.en;
  46.  
  47. return (userStrings || enStrings)[id] || enStrings[id];
  48. }
  49. }());
  50.  
  51. // https://img.icons8.com/pastel-glyph/64/ffffff/download.png
  52. // array because tampermonkey can't roll up a string in the code editor
  53. const downloadIcon = ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE',
  54. 'AAAABACAYAAACqaXHeAAAABmJLR0QA/wD/AP+gvaeTAAABgUlEQVR4nO3ZTU6DUAAE4HnE',
  55. 'k+jWG3TrHVwY3XoEt23cGleamtRtTbyPS3sCV0bXjptHRAIEsM/hZ76kCZRHGaZAGwDMzM',
  56. 'zMbJ6CasMkMwBncXYbQvhSZZEgecEf56ocmWrDAA4L00eqEMoCBsEFqAOouQB1ADUXoA6g',
  57. '5gLUAdRcgDqAmgtQB1BzAeoAakkLIHlN8pPkDcnWd59IBpK3cd1VyoxJkfwo3PV5KJZAcl',
  58. 'lYtiy8H+LY3HvKjKlPgU1h+hLAuulIiMvWcWzVZ4xL/Dbv+Nsjyax8BMSx96Wxm3jzdLwa',
  59. 'SliVCpjezucqzmuSfKuZJkvXi0moORKqTOebL2tRwnR3PtdQwvR3PldRgmznlc8GA4DTOP',
  60. 'scQqAqy6x1+X8+6Ke5yfNxIE9z6/TN1+XCM4inuQ165ZvHz04DF6AOoOYC1AHUXIA6gNpB',
  61. 'z/UWJK/2muTvFn1W6lvASXyNXpdTYJcsxf69th3Y5QjYAiCA485x/tcLgCd1CDMzMzMbum',
  62. '8+xtkWw6QCvwAAAABJRU5ErkJggg=='].join('');
  63.  
  64. const b = document.createElement('button'); // downloadBtn
  65. const bIcon = document.createElement('div');
  66. const bParent = document.body.querySelector('div#install-area');
  67. const bNeighbour = document.body.querySelector('a.install-help-link');
  68. const installBtn = document.body.querySelector('a.install-link');
  69.  
  70. if (!bParent || !bNeighbour || !installBtn) return;
  71.  
  72. GM_addStyle([`
  73. .tm-dsb-downloadBtn {
  74. width: 44px;
  75. height: 38px;
  76. position: relative;
  77. padding: 0;
  78. vertical-align: bottom;
  79. cursor: pointer;
  80. border: none;
  81. outline: none;
  82. background: #0F750F;
  83. transition: box-shadow 0.2s;
  84. }
  85.  
  86. .tm-dsb-downloadBtn:hover,
  87. .tm-dsb-downloadBtn:focus {
  88. box-shadow: 0 8px 16px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%);
  89. }
  90.  
  91.  
  92. .tm-dsb-downloadBtn__icon {
  93. position: absolute;
  94. }
  95.  
  96. .tm-dsb-downloadBtn__icon--download {
  97. width: 34px;
  98. height: 34px;
  99. top: 2px;
  100. left: 5px;
  101. background: url(${downloadIcon});
  102. background-size: contain;
  103. }
  104.  
  105. .tm-dsb-downloadBtn__icon--loading,
  106. .tm-dsb-downloadBtn__icon--loading:after {
  107. border-radius: 50%;
  108. width: 16px;
  109. height: 16px;
  110. }
  111.  
  112. .tm-dsb-downloadBtn__icon--loading {
  113. top: 6px;
  114. left: 9px;
  115. border-top: 5px solid rgba(255, 255, 255, 0.2);
  116. border-right: 5px solid rgba(255, 255, 255, 0.2);
  117. border-bottom: 5px solid rgba(255, 255, 255, 0.2);
  118. border-left: 5px solid #ffffff;
  119. transform: translateZ(0);
  120. animation: loading 1.1s infinite linear;
  121. }
  122.  
  123. @keyframes loading {
  124. 0% {
  125. transform: rotate(0deg);
  126. }
  127. 100% {
  128. transform: rotate(360deg);
  129. }
  130. }
  131. `][0]);
  132.  
  133. b.title = langStrings('Dl');
  134. b.className = 'tm-dsb-downloadBtn';
  135. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--download';
  136. bNeighbour.style.position = 'relative'; // shadow bugfix
  137. bParent.insertBefore(b, bNeighbour);
  138. b.appendChild(bIcon);
  139.  
  140. let fetchingDelay = false;
  141.  
  142. b.addEventListener('click', () => {
  143. setTimeout(() => {
  144. if (b === document.activeElement) b.blur();
  145. }, 250);
  146.  
  147. if (fetchingDelay) return;
  148. fetchingDelay = true;
  149. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--loading';
  150.  
  151. fetch(installBtn.href)
  152. .then(res => res.blob())
  153. .then(blob => {
  154. const url = window.URL.createObjectURL(blob);
  155. const a = document.createElement('a');
  156.  
  157. a.href = url;
  158. a.download = `${installBtn.dataset.scriptName || Date.now()}.user.js`;
  159. document.body.appendChild(a); // needed due to firefox bug
  160. a.click();
  161. a.remove();
  162.  
  163. setTimeout(closeFetchUX, 300);
  164. window.URL.revokeObjectURL(url);
  165. })
  166. .catch(e => {
  167. setTimeout(closeFetchUX, 300);
  168. alert(`${langStrings('failedDl')}: \n${e}`);
  169. });
  170. });
  171.  
  172.  
  173. // utils -------------------------------------------------------------
  174.  
  175. function closeFetchUX() {
  176. fetchingDelay = false;
  177. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--download';
  178. }
  179.  
  180. // --------------------------------------------------------------------
  181.  
  182. })();