MyDownloader

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

Tätä skriptiä ei tulisi asentaa suoraan. Se on kirjasto muita skriptejä varten sisällytettäväksi metadirektiivillä // @require https://update.greasyfork.org/scripts/515674/1500240/MyDownloader.js.

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