课堂派下载助手

可用于下载被禁止的文件

  1. // ==UserScript==
  2. // @name 课堂派下载助手
  3. // @namespace https://shiquda.link/
  4. // @version 0.1.1
  5. // @description 可用于下载被禁止的文件
  6. // @author shiquda
  7. // @match *://document.ketangpai.com/*
  8. // @match *://www.ketangpai.com/#/resource_detail*
  9. // @namespace https://github.com/shiquda/shiquda_UserScript
  10. // @supportURL https://github.com/shiquda/shiquda_UserScript/issues
  11. // @grant GM_addStyle
  12. // @grant GM_addValueChangeListener
  13. // @grant GM_setValue
  14. // @grant GM_xmlhttpRequest
  15. // @license AGPL-3.0
  16. // @require https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
  17. // ==/UserScript==
  18.  
  19. (function () {
  20. 'use strict';
  21.  
  22. function loadImages() {
  23.  
  24. }
  25.  
  26. function getImageLinks() {
  27. return Array.from(document.querySelectorAll('img')).map((img) => img.src).filter((src) => src.startsWith('http'));
  28. }
  29.  
  30. function useMessageToDownloadPDF(imageLinksMessage) {
  31. const imageLinks = imageLinksMessage.imageLinks;
  32. const imgProps = imageLinksMessage.imgProps;
  33. console.log('转换为PDF接受到的links', imageLinks);
  34.  
  35. console.log('图片属性', imgProps);
  36. const pdf = new jspdf.jsPDF({
  37. orientation: "landscape",
  38. unit: "px",
  39. format: [imgProps.width, imgProps.height],
  40. hotfixes: ["px_scaling"]
  41. });
  42.  
  43. let imageDownloadCache = {};
  44. // key是链接,value是base64编码的图片
  45. for (let link of imageLinks) {
  46. imageDownloadCache[link] = null;
  47. }
  48.  
  49. let imageDownloadPromises = imageLinks.map(link => new Promise((resolve, reject) => {
  50. GM_xmlhttpRequest({
  51. method: "GET",
  52. url: link,
  53. responseType: 'arraybuffer',
  54. onload: function (response) {
  55. console.log('图片下载响应', response);
  56. const blob = new Blob([response.response], { type: 'image/jpeg' });
  57. const reader = new FileReader();
  58. reader.onload = function (e) {
  59. const base64 = e.target.result;
  60. imageDownloadCache[link] = base64;
  61. resolve(); // 图片加载完毕
  62. }
  63. reader.readAsDataURL(blob);
  64. },
  65. onerror: function (error) {
  66. reject(error); // 处理下载错误
  67. }
  68. });
  69. }));
  70.  
  71. // 当所有图片都加载完毕,再保存PDF
  72. Promise.all(imageDownloadPromises).then(() => {
  73. console.log('所有图片下载完毕');
  74. imageLinks.forEach((link, i) => {
  75. const base64 = imageDownloadCache[link];
  76. console.log('添加图片', base64);
  77. pdf.addImage(base64, 'JPEG', 0, 0, imgProps.width, imgProps.height);
  78. if (i !== imageLinks.length - 1) {
  79. pdf.addPage();
  80. }
  81. });
  82. // 提供一个默认的PDF标题,以防无法获取页面元素的文本内容
  83. const title = document.querySelector('.mgr-16') ? document.querySelector('.mgr-16').textContent : "Downloaded_Images";
  84. pdf.save(title);
  85. }).catch(error => {
  86. console.error('图片下载或添加到PDF过程中出现错误: ', error);
  87. });
  88. }
  89.  
  90.  
  91.  
  92. // 开始
  93. let pdf = new jspdf.jsPDF();
  94.  
  95. // 判断是不是iframe
  96. if (window.parent === window) {
  97. GM_addValueChangeListener('imageLinks', function (imageLinks, old_value, new_value, remote) {
  98. console.log('imageLinks changed');
  99. useMessageToDownloadPDF(new_value);
  100. })
  101. } else {
  102. // 是iframe
  103. const donwloadButton = document.createElement('button');
  104. donwloadButton.innerText = '下载为PDF';
  105. donwloadButton.style.position = 'fixed';
  106. donwloadButton.style.top = '50px';
  107. donwloadButton.style.right = '30px';
  108. donwloadButton.style.zIndex = '9999';
  109. donwloadButton.addEventListener('click', () => {
  110. loadImages();
  111. setTimeout(() => {
  112. const imageLinks = getImageLinks();
  113. const imgProps = pdf.getImageProperties(imageLinks[0]);
  114.  
  115. const imageLinksMessage = {
  116. imageLinks: imageLinks,
  117. imgProps: imgProps,
  118. time: new Date().getTime()
  119. };
  120. GM_setValue('imageLinks', imageLinksMessage);
  121. }, 500);
  122. });
  123. document.body.appendChild(donwloadButton);
  124. loadImages();
  125.  
  126. }
  127.  
  128. })();