MAL Images Backup

Backups all images on forum topics, blogs and all images on anime/manga lists CSS styles.

安装此脚本?
作者推荐脚本

您可能也喜欢Paste Images - MAL

安装此脚本
  1. // ==UserScript==
  2. // @name MAL Images Backup
  3. // @namespace MALImgsBackup
  4. // @description Backups all images on forum topics, blogs and all images on anime/manga lists CSS styles.
  5. // @version 5
  6. // @match https://myanimelist.net/blog/*
  7. // @match https://myanimelist.net/animelist/*
  8. // @match https://myanimelist.net/mangalist/*
  9. // @match https://myanimelist.net/forum/?topicid=*
  10. // @icon https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://myanimelist.net&size=64
  11. // @connect i.imgur.com
  12. // @connect media.giphy.com
  13. // @connect media1.tenor.com
  14. // @connect thumbs.gfycat.com
  15. // @connect cdn.myanimelist.net
  16. // @connect image.myanimelist.net
  17. // @grant GM_registerMenuCommand
  18. // @grant GM.xmlHttpRequest
  19. // @run-at document-end
  20. // ==/UserScript==
  21.  
  22. GM_registerMenuCommand("Backup HTML/CSS", Backup); //Adds an option to the menu
  23. async function Backup() { //Creates a new Backup function
  24. const imagePromises = []; //Creates a new array
  25. if (location.pathname.match('list') !== null) //If the user is on a manga/anime list
  26. { //Starts the if condition
  27. var component; //Creates a new variable
  28. var NotCustom = document.querySelector("style:nth-child(2)").innerText; //Creates a new variable
  29. var Custom = document.querySelector("#custom-css") === null ? '' : document.querySelector("#custom-css").innerText; //Creates a new variable
  30.  
  31. if ((Custom + NotCustom).match(/http.+?(?=(?:"|'|`)?\))/gm) === null) //If the css has no image links
  32. { //Starts the if condition
  33. alert(location.pathname.split('/')[2] + ' CSS codes has no images!'); //Show a message
  34. return; //Stop the script
  35. } //Finishes the if condition
  36. const HasLinks = Custom.match(/http.+?(?=(?:"|'|`)?\))/gm) !== null; //Creates a new variable
  37.  
  38. (Custom + NotCustom).match(/http.+?(?=(?:"|'|`)?\))/gm).forEach(URL => { //For each image URL in the CSS code
  39. const promise = new Promise((resolve) => { //Convert URL to DataURI using a Promise
  40. GM.xmlHttpRequest({ //Starts the xmlHttpRequest
  41. method: "GET",
  42. url: URL,
  43. responseType: "blob",
  44. onload: async (response) => {
  45. const reader = new FileReader();
  46. reader.onload = () => resolve(reader.result);
  47. reader.readAsDataURL(response.response);
  48. } //Finishes the onload
  49. }); //Finishes the xmlHttpRequest
  50. }); //Finishes the promise const
  51. imagePromises.push(promise); //Add the promise to the array
  52. promise.then((dataURI) => { //After the promise resolves, replace URL with DataURI in the CSS code
  53. Custom = Custom.replace(URL, dataURI); //Change all image links on the variable to DataURI
  54. NotCustom = NotCustom.replace(URL, dataURI); //Change all image links on the variable to DataURI
  55. HasLinks ? component = Custom : component = NotCustom; //If the user is on a modern list style and it has a custom css with images
  56. }); //Finishes the dataURI const
  57. }); //Finishes the forEach loop
  58. await Promise.all(imagePromises); //Wait for all image URLs to be fetched and their corresponding data URIs to be generated
  59.  
  60. document.body.insertAdjacentHTML('afterbegin', `<a id='dwnldLnk' download="${location.pathname.split('/')[2]}${Custom === '' ? ' Classic Style' : ' Modern Style'}.css" href="data:text/css;charset=utf-8,${encodeURIComponent(component)}"></a>`); //Generate the download button
  61. document.getElementById('dwnldLnk').click(); //Download the css
  62. } //Finishes the if condition
  63. else //If the user is on a forum or blog page
  64. { //Starts the else condition
  65. document.querySelectorAll(".message-text > img, .userimg").forEach(function(URL) { //ForEach image URL on the page
  66. const imagePromise = new Promise((resolve) => GM.xmlHttpRequest({ //Starts the xmlHttpRequest
  67. method: "GET",
  68. url: URL.src,
  69. responseType: "blob",
  70. onload: async (response) => {
  71. const dataURI = await new Promise((resolve) => {
  72. const reader = new FileReader();
  73. reader.onload = () => resolve(reader.result);
  74. reader.readAsDataURL(response.response);
  75. });
  76. dataURI !== 'data:' ? URL.src = dataURI : ''; //Change the url link with the data URI
  77. resolve(); //Resolve the promise once the data URI is generated
  78. } //Finishes the onload
  79. })); //Finishes the xmlHttpRequest
  80. imagePromises.push(imagePromise); //Add the promise to the array
  81. }); //Finishes the forEach loop
  82. await Promise.all(imagePromises); //Wait for all image URLs to be fetched and their corresponding data URIs to be generated
  83. document.body.insertAdjacentHTML('afterbegin', `<a id='dwnldLnk' download="https myanimelist.net ${location.href.split(/t\//)[1].replaceAll(/[/?]/gm, ' ').replaceAll(/ /gm, ' ')}.html" href="data:text/html;charset=utf-8,${encodeURIComponent(document.documentElement.outerHTML)}"></a>`); //Generate the download button
  84. document.getElementById('dwnldLnk').click(); //Download the website html
  85. } //Finishes the else condition
  86. } //Finishes the Backup function

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址