Frenschan Thread Image Downloader

Downloads all images individually in a frenschan thread with original filenames (by default).

当前为 2022-05-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Frenschan Thread Image Downloader
  3. // @namespace Violentmonkey Scripts
  4. // @match https://www.frenschan.com/*/res/*.html
  5. // @match https://www.frenschan.org/*/res/*.html
  6. // @grant GM_download
  7. // @grant GM_registerMenuCommand
  8. // @version 1.1
  9. // @license The Unlicense
  10. // @author ImpatientImport
  11. // @description Downloads all images individually in a frenschan thread with original filenames (by default).
  12. // ==/UserScript==
  13.  
  14. /* EDIT ABOVE THIS LINE */
  15.  
  16. // User preferences
  17.  
  18. var download_limit = 3000; // speed in milliseconds to delay
  19.  
  20. /* EDIT BELOW THIS LINE */
  21.  
  22.  
  23. function sleep(ms) {
  24. return new Promise(resolve => setTimeout(resolve, ms));
  25. }
  26.  
  27. (function() {
  28. 'use strict';
  29. // Constants for later reference
  30. const top_of_thread = document.getElementsByClassName("intro")[0];
  31. const thread_URL = document.URL;
  32. const tinyboard_site = thread_URL.toString().split('/')[2];
  33. const url_path = new URL(thread_URL).pathname;
  34. const url_path_split = url_path.toString().split('/')
  35. const thread_board = url_path_split[1];
  36. const thread_num = url_path_split[3].split(".")[0];
  37. const json_url = "https://"+ tinyboard_site + "/"+ thread_board +"/res/"+ thread_num + ".json"; // important
  38. var media_arr=[], media_fnames=[];
  39. // Gets the JSON file for the Tinyboard thread
  40. async function get_archive_thread() {
  41. const site_response = await fetch(json_url);
  42. const JSON_file = await site_response.json();
  43. console.log(JSON_file); // debug
  44. retrieve_media(JSON_file);
  45. download_images();
  46. }
  47. // Retrieves media from the thread (in JSON format)
  48. function retrieve_media(thread_obj) {
  49. const posts_exist = thread_obj.posts != undefined;
  50.  
  51. if (posts_exist) {
  52. const thread_posts = thread_obj.posts;
  53. //const post_nums = Object.keys(thread_posts);
  54. const posts_length = thread_posts.length;
  55. for (let i = 0; i < posts_length; i++) {
  56. if(thread_posts[i].tim != null && thread_posts[i].ext != "deleted"){
  57. media_arr.push("https://" + tinyboard_site + "/" + thread_board + "/src/" + thread_posts[i].tim + thread_posts[i].ext );
  58. media_fnames.push(thread_posts[i].filename + thread_posts[i].ext);
  59. }
  60. }
  61. }
  62. }
  63. async function download_images(){
  64.  
  65. for (var i=0; i<media_arr.length; i++){
  66.  
  67. await sleep(download_limit);
  68. console.log(media_arr[i]);
  69.  
  70. GM_download(media_arr[i], media_fnames[i]) // downloads images
  71. }
  72. }
  73. GM_registerMenuCommand("Download all thread images individually", get_archive_thread);
  74. var indiv_dl_btn;
  75. var indiv_dlbtn_elem;
  76. indiv_dl_btn = document.createElement('a');
  77. indiv_dl_btn.id = "indiv_btn";
  78. indiv_dl_btn.innerText = "[Download Images]";
  79. top_of_thread.append(indiv_dl_btn);
  80. indiv_dlbtn_elem = document.getElementById("indiv_btn");
  81. indiv_dl_btn.addEventListener("click", get_archive_thread);
  82. })();