MyDownloader

包含多种下载方法的下载库

当前为 2024-12-10 提交的版本,查看 最新版本

此脚本不应直接安装,它是供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/515674/1500228/MyDownloader.js

  1. // ==UserScript==
  2. // @name MyDownloader
  3. // @version 2024.11.4
  4. // @description 包含多种下载方法的下载库
  5. // @author You
  6. // @grant none
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @grant GM_deleteValue
  10. // @grant GM_download
  11. // @require https://update.greasyfork.org/scripts/480132/1476440/Get_all_img_Library.js
  12. // ==/UserScript==
  13.  
  14. /**
  15. * 包含多种下载方法的下载类
  16. * @example
  17. const downloader = new Downloader();
  18. downloader.Download_img(imgs);
  19. */
  20. function Downloader(){
  21. let downloading = 0;
  22. let downloaded = [];
  23. let downloadError = [];
  24. let imgs = null;
  25. let maxDownloadingCounts = 10;
  26. let timeout = null;
  27. let AllComplete = null;
  28. let OneSuccess = null;
  29. let OneError = null;
  30. let downloadType = ""
  31. /**
  32. * @example Download_img(imgs)
  33. */
  34. this.Download_img = async (imgs)=>{
  35. if(downloadType==""){
  36. await Test_downloadType(imgs.eq(0));
  37. }
  38. Set_download(imgs)
  39. console.log(downloadType);
  40. if(downloadType=="GM_download"){
  41. Donwload_img_by_GM();
  42. }else if(downloadType=="atag"){
  43. Donwload_img_by_atag();
  44. }else if(downloadType=="blob"){
  45. Donwload_img_by_blob();
  46. }else{
  47. alert("no this donwload type");
  48. }
  49. }
  50. /**
  51. * @example downloadType.value = "GM_download" || "atag" || "blob"
  52. */
  53. this.downloadType = {get value(){return downloadType;},set value(v){downloadType = v;}};
  54. /**
  55. * @example maxDownloadingCounts.value = 100
  56. */
  57. this.maxDownloadingCounts = {get value(){return maxDownloadingCounts;},set value(v){maxDownloadingCounts = v}};
  58. /**
  59. * @example timeout.value = 1000
  60. */
  61. this.timeout = {get value(){return timeout;},set value(v){timeout = v}};
  62. /**
  63. * @example OneSuccess((success_img)=>{...})
  64. */
  65. this.OneSuccess = foo=>OneSuccess = foo;
  66. /**
  67. * @example OneError((error_img)=>{...})
  68. */
  69. this.OneError = foo=>OneError = foo;
  70. /**
  71. * @example AllComplete(()=>{...})
  72. */
  73. this.AllComplete = foo=>AllComplete = foo;
  74. async function Test_downloadType(img){
  75. return new Promise((resolve)=>{
  76. let timeout = 3000;
  77. let isOk = false;
  78. GM_download({
  79. url:img[0].src,
  80. name:"test.png",
  81. onload:()=>{isOk = true;downloadType = "GM_download";resolve()},
  82. })
  83. setTimeout(()=>{
  84. if(!isOk){downloadType = "atag";}
  85. resolve()
  86. },timeout)
  87. })
  88. }
  89. function Set_download(iimgs){
  90. downloaded = [];
  91. downloading = 0;
  92. downloadError = [];
  93. imgs = iimgs;
  94. }
  95. function Donwload_img_by_GM(){
  96. if(!imgs || imgs.length == 0){alert("imgs is empty");return;}
  97. async function Download_one(i){
  98. if(i>=imgs.length){if(AllComplete){AllComplete()};return;}
  99. if(downloading>=maxDownloadingCounts){setTimeout(()=>{Download_one(i)},1000);return;}
  100. let name = '';
  101. let src = '';
  102. downloading++;
  103. try{
  104. await Check_and_get_nameAndsrc({img:imgs.eq(i),checkSrc:true})
  105. .then((m)=>{
  106. name = m.name;
  107. src = m.src;
  108. });
  109. }catch(error){
  110. console.log(error)
  111. console.log('imgsrc is error:');
  112. downloadError.push(i);
  113. downloading--;
  114. Download_one(i+1);
  115. return;
  116. }
  117. console.log(name)
  118. console.log(document.title)
  119. let timeout = false;
  120. setTimeout(() => {timeout = true;},10000);
  121. const donwimg = imgs.eq(i);
  122. GM_download({
  123. url:src,
  124. name:name,
  125. onload:function(){
  126. downloaded.push(downimg);
  127. downloading--;
  128. if(window.GAIL.showmass){
  129. window.GAIL.showmass((downloaded.length+downloadError.length)+"/"+imgs.length);
  130. }
  131. imgs.eq(i).remove();
  132. if(OneSuccess){OneSuccess(downimg);}
  133. },
  134. onerror:function(){
  135. downloading--;
  136. downloadError.push(downimg);
  137. if(OnError){OnError(downimg);}
  138. },
  139. onprogress:function(){
  140. if(timeout){return false;}
  141. }
  142. });
  143. setTimeout(function() {Download_one(i+1);}, 10);
  144. }
  145. Download_one(0);
  146. }
  147. async function Donwload_img_by_atag(nowIsImgPage) {
  148. if (!nowIsImgPage) {
  149. if(!imgs || imgs.length==0){alert("imgs is empty");return;}
  150. GM_setValue("downloadName", document.title);
  151. for (let i = 0; i < imgs.length; i++) {
  152. GM_setValue("downloadType", "start");
  153. let name;
  154. let src;
  155. await Check_and_get_nameAndsrc({img:imgs.eq(i),checkSrc:false})
  156. .then((m)=>{
  157. name = m.name;
  158. src = m.src;
  159. });
  160. GM_setValue("downloadSrc", src);
  161. const myWindow = window.open(src, '_blank');
  162. await new Promise(resolve => {
  163. const checkDownload = setInterval(() => {
  164. if (GM_getValue("downloadType") === "end") {
  165. resolve();
  166. clearInterval(checkDownload);
  167. }
  168. }, 100);
  169. });
  170. OneSuccess?.(imgs.eq(i));
  171. downloaded.push(imgs.eq(i));
  172. window?.GAIL?.showmass?.((downloaded.length+downloadError.length)+"/"+imgs.length);
  173. $(".mass_top").css({'font-size':'6vmin'});
  174. }
  175. AllComplete?.();
  176. } else {
  177. await Check_and_get_nameAndsrc({img:$("img"),checkSrc:true})
  178. .then((m)=>{
  179. let name = m.name;
  180. let src = m.src;
  181. $('<a></a>').attr({
  182. 'href': src,
  183. 'download': name,
  184. })[0].click();
  185. });
  186. await new Promise(resolve => setTimeout(resolve, 1000));
  187. GM_setValue("downloadType", "end");
  188. window.close();
  189. }
  190. }
  191. this.Listening_Download_by_atag = ()=>{
  192. const locationHref = window.location.href;
  193. const GM_downloadSrc = GM_getValue("downloadSrc");
  194. if(!GM_downloadSrc){return;}
  195. if(GM_downloadSrc == locationHref|| locationHref.indexOf(GM_downloadSrc)>=0 || GM_downloadSrc.indexOf(locationHref)>=0 ){
  196. Donwload_img_by_atag(true);
  197. }
  198. }
  199. function Donwload_img_by_blob(){
  200. if(!imgs || imgs.length==0){alert("imgs is empty");return;}
  201.  
  202. const obo = (i)=>{
  203. if(i>=imgs.length){return;}
  204. if(maxDownloadingCounts>1 && downloading >= maxDownloadingCounts){
  205. setTimeout(function() {obo(i)}, 1000);
  206. }
  207. let src = imgs.eq(i).attr('big_src');
  208. if(!src){src = imgs.eq(i).attr('src');}
  209. const checkimg = imgs.eq(i);
  210. downloading++;
  211. UrlToBlob({url:src,timeout:timeout})
  212. .then(blob=>{
  213. Check_and_get_nameAndsrc({img:checkimg}).then(args=>{
  214. const name = args.name;
  215. let a = $('<a></a>').attr({
  216. download:name,
  217. href:blob
  218. })
  219. a[0].click();
  220. downloaded.push(checkimg);
  221. downloading--;
  222. checkimg.attr('src',blob);
  223. OneSuccess?.(checkimg);
  224. })
  225. if(maxDownloadingCounts==1){
  226. obo(++i);
  227. }else{
  228. window.GAIL.showmass((downloaded.length+downloadError.length)+"/"+imgs.length);
  229. }
  230. })
  231. .catch(er=>{
  232. console.log(er);
  233. downloadError.push(imgs.eq(i));
  234. downloading--;
  235. if(maxDownloadingCounts==1){
  236. obo(++i);
  237. }else{
  238. window.GAIL.showmass((downloaded.length+downloadError.length)+"/"+imgs.length);
  239. }
  240. });
  241. if(maxDownloadingCounts>1){
  242. setTimeout(function() {obo(++i);}, 10);
  243. }
  244. }
  245. obo(0);
  246. }
  247. /**
  248. * @example Urls({url:url,timeout : 100})
  249. */
  250. async function UrlToBlob(args) {
  251. return new Promise((resolve,reject)=>{
  252. if(!args.url){reject("no url");}
  253. if(args.timeout){
  254. const timeout = setTimeout(function() {reject("fetch timeout")}, args.timeout);
  255. }
  256. fetch(args.url)
  257. .then(response => {
  258. const contentLength = response.headers.get('Content-Length');
  259. const total = parseInt(contentLength, 10);
  260. let loaded = 0;
  261. // 克隆响应以便分别读取流和获得 Blob
  262. const clonedResponse = response.clone();
  263. const reader = clonedResponse.body.getReader();
  264. // 更新进度的函数
  265. function updateProgress({ done, value }) {
  266. if (done) {
  267. return; // 如果读取完毕,直接返回
  268. }
  269. loaded += value.byteLength; // 累加已加载字节
  270. const progress = (loaded / total) * 100; // 计算进度百分比
  271. console.log(`Loading: ${progress.toFixed(2)}%`);
  272. FetchShowProgress?.(progress);
  273. // 继续读取下一块数据
  274. return reader.read().then(updateProgress);
  275. }
  276. // 开始读取流以更新进度
  277. return reader.read().then(updateProgress).then(() => {
  278. // 完成后返回原始响应的 Blob
  279. return response.blob();
  280. });
  281. })
  282. .then(blob => {
  283. const blobUrl = URL.createObjectURL(blob);
  284. resolve(blobUrl);
  285. })
  286. .catch(error => {
  287. console.error('Error caching video:', error);
  288. reject(error);
  289. });
  290. });
  291. }
  292. function FetchShowProgress(pro){
  293. if(this.maxDownloadingCounts==1 && this.imgs.length==1){
  294. window?.GAIL?.showmass(pro);
  295. $(".mass_top").css('font-size',"10vmin");
  296. }
  297. }
  298. function Check_and_get_nameAndsrc(args){
  299. return new Promise(async (resolve,reject)=>{
  300. if(!args || !args.img){return reject();}
  301. let src = args.img.attr('big_src');
  302. if(!src){src = args.img.attr('src');}
  303. if(!src){src = args.img.attr('small_src');}
  304. if(!src){reject();}
  305. //console.log("check:"+src)
  306. if(args.checkSrc){
  307. try{
  308. await check_src_is_right(src);
  309. }catch(error){
  310. reject();
  311. }
  312. }
  313. let ext = src.match(/\.jpg|\.png|\.webp|\.gif|\.bmp/g);
  314. if(!ext){ext = '.png';}else{ext = ext[0];}
  315. let name = args.img.attr('name');
  316. if(!name){name = document.title + new Date().getTime() + ext;}
  317. resolve({name:name,src:src});
  318. });
  319. }
  320. function check_src_is_right(src){
  321. return new Promise((resolve,reject)=>{
  322. let iimg = new Image();
  323. iimg.onload = function(){
  324. if(this.width*this.height*this.naturalWidth*this.naturalHeight==0){reject();}else{resolve();}
  325. }
  326. iimg.onerror = function(){reject();}
  327. iimg.src = src;
  328. setTimeout(function() {iimg.abort();reject();}, 2000);
  329. })
  330. }
  331. }
  332. $(function(){
  333. let dd = new Downloader()
  334. dd.Listening_Download_by_atag()
  335. })
  336.  
  337. window.Downloader = Downloader;