GreasyFork: download script button

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

2021-01-29 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

  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. // @namespace https://greatest.deepsurf.us/users/424058
  5. // @version 1.0.0
  6. // @author Konf
  7. // @match https://greatest.deepsurf.us
  8. // @include /^http(s|):\/\/greatest.deepsurf.us\/[a-zA-Z_-]*\/scripts\/\d.*$/
  9. // @run-at document-end
  10. // @resource iconDownload https://img.icons8.com/pastel-glyph/64/ffffff/download.png
  11. // @compatible Chrome
  12. // @compatible Opera
  13. // @compatible Firefox
  14. // @grant GM_getResourceUrl
  15. // @grant GM.getResourceUrl
  16. // @noframes
  17. // ==/UserScript==
  18.  
  19. /* jshint esversion: 6 */
  20. /* eslint-disable no-multi-spaces */
  21.  
  22. (function() {
  23. 'use strict';
  24.  
  25. const userLang = location.pathname.split('/')[1];
  26. const langStringsList = {
  27. en: {
  28. Dl: 'Download without installing',
  29. unableDl: 'Unable to download the script'
  30. },
  31. ru: {
  32. Dl: 'Скачать не устанавливая',
  33. unableDl: 'Не удалось скачать скрипт'
  34. }
  35. };
  36. const langStrings = langStringsList[userLang] || langStringsList.en;
  37.  
  38. (GM.getResourceUrl || GM_getResourceUrl)('iconDownload')
  39. .then(downloadIconUrl => {
  40. addCSS(`
  41. .tm-dsb-downloadBtn {
  42. width: 43px;
  43. height: 38px;
  44. position: relative;
  45. padding: 0;
  46. vertical-align: bottom;
  47. cursor: pointer;
  48. border: none;
  49. outline: none;
  50. background: #0F750F;
  51. transition: box-shadow 0.2s;
  52. }
  53.  
  54. .tm-dsb-downloadBtn:hover,
  55. .tm-dsb-downloadBtn:focus {
  56. box-shadow: 0 8px 16px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%);
  57. }
  58.  
  59.  
  60. .tm-dsb-downloadBtn__icon {
  61. position: absolute;
  62. }
  63.  
  64. .tm-dsb-downloadBtn__icon--download {
  65. width: 35px;
  66. height: 35px;
  67. top: 1px;
  68. left: 4px;
  69. background: url(${downloadIconUrl});
  70. background-size: contain;
  71. }
  72.  
  73. .tm-dsb-downloadBtn__icon--loading,
  74. .tm-dsb-downloadBtn__icon--loading:after {
  75. border-radius: 50%;
  76. width: 16px;
  77. height: 16px;
  78. }
  79.  
  80. .tm-dsb-downloadBtn__icon--loading {
  81. top: 6px;
  82. left: 8px;
  83. text-indent: -9999em;
  84. border-top: 5px solid rgba(255, 255, 255, 0.2);
  85. border-right: 5px solid rgba(255, 255, 255, 0.2);
  86. border-bottom: 5px solid rgba(255, 255, 255, 0.2);
  87. border-left: 5px solid #ffffff;
  88. -webkit-transform: translateZ(0);
  89. -ms-transform: translateZ(0);
  90. transform: translateZ(0);
  91. -webkit-animation: loading 1.1s infinite linear;
  92. animation: loading 1.1s infinite linear;
  93. }
  94.  
  95. @-webkit-keyframes loading {
  96. 0% {
  97. -webkit-transform: rotate(0deg);
  98. transform: rotate(0deg);
  99. }
  100. 100% {
  101. -webkit-transform: rotate(360deg);
  102. transform: rotate(360deg);
  103. }
  104. }
  105.  
  106. @keyframes loading {
  107. 0% {
  108. -webkit-transform: rotate(0deg);
  109. transform: rotate(0deg);
  110. }
  111. 100% {
  112. -webkit-transform: rotate(360deg);
  113. transform: rotate(360deg);
  114. }
  115. }
  116. `);
  117. });
  118.  
  119. const b = document.createElement('button'); // downloadBtn
  120. const bIcon = document.createElement('div');
  121. const bParent = document.body.querySelector('div#install-area');
  122. const bNeighbour = document.body.querySelector('a.install-help-link');
  123. const installBtn = document.body.querySelector('a.install-link');
  124.  
  125. b.title = langStrings.Dl;
  126. b.className = 'tm-dsb-downloadBtn';
  127. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--download';
  128. bParent.insertBefore(b, bNeighbour);
  129. b.appendChild(bIcon);
  130.  
  131. let fetchingDelay = false;
  132.  
  133. b.addEventListener('click', () => {
  134. setTimeout(() => {
  135. if (b === document.activeElement) document.activeElement.blur();
  136. }, 750);
  137.  
  138. if (fetchingDelay) return;
  139. fetchingDelay = true;
  140. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--loading';
  141.  
  142. fetch(installBtn.href)
  143. .then(res => res.blob())
  144. .then(blob => {
  145. const url = window.URL.createObjectURL(blob);
  146. const a = document.createElement('a');
  147.  
  148. a.href = url;
  149. a.download = `${installBtn.dataset.scriptName}.user.js`;
  150. document.body.appendChild(a); // needed due to firefox bug
  151. a.click();
  152. a.remove();
  153.  
  154. setTimeout(closeFetchUX, 300);
  155. window.URL.revokeObjectURL(url);
  156. })
  157. .catch(e => {
  158. setTimeout(closeFetchUX, 300);
  159. alert(`${langStrings.unableDl}: \n${e}`);
  160. });
  161. });
  162.  
  163.  
  164. // utils -------------------------------------------------------------
  165.  
  166. function closeFetchUX() {
  167. fetchingDelay = false;
  168. bIcon.className = 'tm-dsb-downloadBtn__icon tm-dsb-downloadBtn__icon--download';
  169. }
  170.  
  171. function addCSS(cssCode) {
  172. const styleEl = document.createElement("style");
  173. styleEl.type = "text/css";
  174.  
  175. if (styleEl.styleSheet) {
  176. styleEl.styleSheet.cssText = cssCode;
  177. } else {
  178. styleEl.appendChild(document.createTextNode(cssCode));
  179. }
  180.  
  181. document.getElementsByTagName("head")[0].appendChild(styleEl);
  182.  
  183. return styleEl;
  184. }
  185.  
  186. // --------------------------------------------------------------------
  187.  
  188. })();