Desu Image Downloader

Download images with original filenames on desuarchive.org, archive.palanq.win, and add download button to direct image pages

当前为 2024-08-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Desu Image Downloader
  3. // @version 1.20
  4. // @description Download images with original filenames on desuarchive.org, archive.palanq.win, and add download button to direct image pages
  5. // @author Anonimas
  6. // @match https://desuarchive.org/*
  7. // @match https://desu-usergeneratedcontent.xyz/*
  8. // @match https://archive.palanq.win/*
  9. // @match https://archive-media.palanq.win/*
  10. // @grant GM_download
  11. // @grant GM_addStyle
  12. // @namespace https://greasyfork.org/users/1342214
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. GM_addStyle(`
  19. #download-button {
  20. position: fixed;
  21. bottom: 20px;
  22. right: 20px;
  23. background-color: rgba(0, 0, 0, 0.5);
  24. color: white;
  25. border: none;
  26. border-radius: 5px;
  27. padding: 10px 20px;
  28. cursor: pointer;
  29. font-size: 16px;
  30. transition: background-color 0.3s;
  31. text-decoration: none;
  32. font-family: Arial, sans-serif;
  33. }
  34. #download-button:hover {
  35. background-color: rgba(0, 0, 0, 0.7);
  36. }
  37. `);
  38.  
  39. function getFullFilename(element) {
  40. return element.getAttribute('title') || element.textContent.trim();
  41. }
  42.  
  43. function appendFilenameToUrl(url, filename) {
  44. return `${url}?filename=${encodeURIComponent(filename)}`;
  45. }
  46.  
  47. function downloadImage(imageUrl, originalFilename) {
  48. if (imageUrl && originalFilename) {
  49. GM_download({
  50. url: imageUrl,
  51. name: originalFilename,
  52. onload: () => {},
  53. onerror: (error) => console.error('Download error:', error)
  54. });
  55. }
  56. }
  57.  
  58. function handleImageClick(event) {
  59. event.preventDefault();
  60. const imageLink = event.target.closest('a[href*="//desu-usergeneratedcontent.xyz/"], a[href*="//archive-media.palanq.win/"]');
  61. if (!imageLink) return;
  62.  
  63. const imageUrl = imageLink.href;
  64. let filenameElement = imageLink.closest('div.post_file, article.thread, article.post')?.querySelector('a.post_file_filename');
  65. if (!filenameElement) return;
  66.  
  67. const originalFilename = getFullFilename(filenameElement);
  68.  
  69. const newUrl = appendFilenameToUrl(imageUrl, originalFilename);
  70. window.open(newUrl, '_blank');
  71. }
  72.  
  73. function addDownloadButtonToImagePage() {
  74. if (window.location.hostname === 'desu-usergeneratedcontent.xyz' || window.location.hostname === 'archive-media.palanq.win') {
  75. const button = document.createElement('a');
  76. button.id = 'download-button';
  77. button.textContent = 'Download';
  78.  
  79. const imageUrl = window.location.href;
  80.  
  81. const urlParams = new URLSearchParams(window.location.search);
  82. const originalFilename = urlParams.get('filename') || extractFilenameFromUrl(imageUrl);
  83.  
  84. button.href = imageUrl;
  85. button.download = originalFilename;
  86.  
  87. document.body.appendChild(button);
  88. }
  89. }
  90.  
  91. function extractFilenameFromUrl(url) {
  92. return url.substring(url.lastIndexOf('/') + 1);
  93. }
  94.  
  95. if (window.location.hostname === 'desuarchive.org' || window.location.hostname === 'archive.palanq.win') {
  96. document.querySelectorAll('a.post_file_filename').forEach(link => {
  97. link.addEventListener('click', event => {
  98. event.preventDefault();
  99. const imageUrl = link.closest('a').href;
  100. const originalFilename = getFullFilename(link);
  101. downloadImage(imageUrl, originalFilename);
  102. });
  103. });
  104.  
  105. document.querySelectorAll('a[href*="//desu-usergeneratedcontent.xyz/"] i.icon-download-alt, a[href*="//archive-media.palanq.win/"] i.icon-download-alt').forEach(button => {
  106. button.closest('a').addEventListener('click', event => {
  107. event.preventDefault();
  108. const imageUrl = button.closest('a').href;
  109. let filenameElement = button.closest('div.post_file, article.thread, article.post')?.querySelector('a.post_file_filename');
  110. if (!filenameElement) return;
  111.  
  112. const originalFilename = getFullFilename(filenameElement);
  113. downloadImage(imageUrl, originalFilename);
  114. });
  115. });
  116.  
  117. document.querySelectorAll('a[href*="//desu-usergeneratedcontent.xyz/"] img, a[href*="//archive-media.palanq.win/"] img').forEach(image => {
  118. image.closest('a').addEventListener('click', handleImageClick);
  119. });
  120. }
  121.  
  122. addDownloadButtonToImagePage();
  123. })();