Fanbox Batch Downloader

Batch Download on creator, not post

当前为 2019-12-22 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Fanbox Batch Downloader
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.21
  5. // @description Batch Download on creator, not post
  6. // @author https://github.com/amarillys
  7. // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.2.2/jszip.min.js
  8. // @match https://www.pixiv.net/fanbox/creator/*
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_download
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. const fetchOptions = {
  19. credentials: 'include',
  20. headers: { Accept: 'application/json, text/plain, */*' }
  21. }
  22.  
  23. window.onload = () => {
  24. let baseBtn = document.querySelector('[href="/fanbox/notification"]')
  25. let className = baseBtn.parentNode.className
  26. let parent = baseBtn.parentNode.parentNode
  27. let downloadBtn = document.createElement('div')
  28. downloadBtn.className = className
  29. downloadBtn.innerHTML = `
  30. <a href="javascript:void(0)">
  31. <div id="amarillys-download-progress"
  32. style="line-height: 32px;width: 100px;height: 32px;background-color: rgba(232, 12, 2, 0.96);;border-radius: 8px;color: #FFF;text-align: center;">
  33. Download/下载
  34. </div>
  35. </a>`
  36. downloadBtn.addEventListener('click', () => { console.log('startDownloading'); downloadByFanboxId(parseInt(document.URL.split('/')[5])); })
  37. parent.appendChild(downloadBtn)
  38. }
  39.  
  40. function gmRequireImage(url) {
  41. return new Promise((resolve, reject) => {
  42. GM_xmlhttpRequest({
  43. method: 'GET',
  44. url,
  45. responseType: 'blob',
  46. onload: res => {
  47. resolve(res.response)
  48. }
  49. })
  50. })
  51. }
  52.  
  53. async function downloadByFanboxId(creatorId) {
  54. let textDiv = document.querySelector('#amarillys-download-progress')
  55. textDiv.innerHTML = ` ...... `
  56. let creatorInfo = await getAllPostsByFanboxId(creatorId)
  57.  
  58. let zip = new JSZip()
  59. let amount = 0
  60. let processed = 0
  61. let waittime = 0
  62. zip.file('cover.jpg', await gmRequireImage(creatorInfo.cover), { compression: "STORE" })
  63. for (let i = 0, p = creatorInfo.posts; i < p.length; ++i) {
  64. let folder = `${p[i].title}-${p[i].id}`
  65. if (!p[i].body) continue
  66. let images = p[i].body.images
  67. if (!images) continue
  68. for (let j = 0; j < images.length; ++j) {
  69. let extension = images[j].extension === 'jpeg' ? 'jpg' : 'png'
  70. amount++
  71. textDiv.innerHTML = ` ${ processed } / ${ amount } `
  72. gmRequireImage(images[j].originalUrl).then(blob => {
  73. zip.folder(folder).file(`${folder}_${j}.${extension}`, blob, { compression: "STORE" })
  74. waittime--
  75. processed++
  76. textDiv.innerHTML = ` ${ processed } / ${ amount } `
  77. console.log(` Progress: ${ processed } / ${ amount }`)
  78. })
  79. }
  80. }
  81. // generate zip to download
  82. let timer = setInterval(() => {
  83. waittime++
  84. if (amount === processed || waittime > 10) {
  85. zip.generateAsync({ type: 'blob' }).then(zipBlob => saveBlob(zipBlob, `${creatorId}.zip`))
  86. clearInterval(timer)
  87. }
  88. }, 1000)
  89. }
  90.  
  91. async function getAllPostsByFanboxId(creatorId) {
  92. let fristUrl = `https://www.pixiv.net/ajax/fanbox/creator?userId=${ creatorId }`
  93. let creatorInfo = {
  94. cover: null,
  95. posts: []
  96. }
  97. let firstData = await (await fetch(fristUrl, fetchOptions)).json()
  98. let body = firstData.body
  99. creatorInfo.cover = body.creator.coverImageUrl
  100. creatorInfo.posts.push(...body.post.items)
  101. let nextPageUrl = body.post.nextUrl
  102. while (nextPageUrl) {
  103. let nextData = await (await fetch(nextPageUrl, fetchOptions)).json()
  104. creatorInfo.posts.push(...nextData.body.items)
  105. nextPageUrl = nextData.body.nextUrl
  106. }
  107. return creatorInfo
  108. }
  109.  
  110. function saveBlob(blob, fileName) {
  111. let downloadDom = document.createElement('a')
  112. downloadDom.id = 'fuck'
  113. document.body.appendChild(downloadDom)
  114. downloadDom.style = `display: none`
  115. let url = window.URL.createObjectURL(blob)
  116. downloadDom.href = url
  117. downloadDom.download = fileName
  118. downloadDom.click()
  119. window.URL.revokeObjectURL(url)
  120. }
  121.  
  122. })();