批量导入 Pixiv 图片到 Eagle

请确保你的网路环境可以正常访问 Pixiv,如果设备网路无法访问,此脚本将无法正常运作。在 Pixiv 页面启动脚本,此脚本会自动将页面中所有图片转换成大图(包含链接、名称),添加至 Eagle App。

  1. // ==UserScript==
  2. // @name Save Pixiv images to Eagle (modified by GreasyWeebs)
  3. // @name:zh 批量导入 Pixiv 图片到 Eagle
  4. // @name:zh-CN 批量导入 Pixiv 图片到 Eagle
  5. // @name:zh-TW 批次導入 Pixiv 圖片到 Eagle
  6.  
  7. // @description Launch a script on Pixiv that automatically converts all images on the page into large images (with links, names) to be added to the Eagle App. manual: go to the artist page and then press alt+L
  8. // @description:zh 请确保你的网路环境可以正常访问 Pixiv,如果设备网路无法访问,此脚本将无法正常运作。在 Pixiv 页面启动脚本,此脚本会自动将页面中所有图片转换成大图(包含链接、名称),添加至 Eagle App。
  9. // @description:zh-CN 请确保你的网路环境可以正常访问 Pixiv,如果设备网路无法访问,此脚本将无法正常运作。在 Pixiv 页面启动脚本,此脚本会自动将页面中所有图片转换成大图(包含链接、名称),添加至 Eagle App。
  10. // @description:zh-TW 在 Pixiv 畫版頁面啓動腳本,此腳本會自動將頁面中所有圖片轉換成大圖(包含鏈接、名稱),添加至 Eagle App。
  11.  
  12. // @author base code by pickuse2013 & modified by GreasyWeebs
  13. // @namespace https://pickuse2013.github.io/
  14. // @homepageURL https://github.com/pickuse2013/pixiv-to-eagle
  15. // @supportURL https://github.com/pickuse2013/pixiv-to-eagle
  16. // @icon https://www.pixiv.net/favicon.ico
  17. // @license MIT License
  18.  
  19. // @match https://www.pixiv.net/*
  20. // @grant GM_xmlhttpRequest
  21. // @grant GM_addStyle
  22. // @run-at document-start
  23.  
  24. // @require https://code.jquery.com/jquery-3.5.1.min.js
  25. // @require https://greasyfork.org/scripts/2199-waitforkeyelements/code/waitForKeyElements.js?version=6349
  26.  
  27. // @date 08/28/2020
  28. // @modified 09/12/2021
  29. // @version 1.2.4
  30.  
  31. // ==/UserScript==
  32. 'use strict';
  33.  
  34. (function () {
  35. console.log("plugin loaded..");
  36. // Eagle API 服务器位置
  37. var image = [];
  38. var requestsPending = 0;
  39. const EAGLE_SERVER_URL = "http://localhost:41595";
  40. const EAGLE_IMPORT_API_URL = `${EAGLE_SERVER_URL}/api/item/addFromURL`;
  41. const EAGLE_CREATE_FOLDER_API_URL = `${EAGLE_SERVER_URL}/api/folder/create`;
  42.  
  43. // Pixiv 当前图片、链接命名规则
  44. const SELECTOR_IMAGE = "section ul li a img[class]";
  45. const SELECTOR_DIALOG = "div#save-to-eagle-dialog div#queue";
  46. const PENDING_DIALOG = "div#save-to-eagle-dialog div#download";
  47.  
  48. // 是否要使用Pixiv的tags
  49. const SUPPORT_TAGS = false;
  50.  
  51. let DOWNLOAD_COUNTER = 0;
  52. let TOTAL_COUNTER = 0;
  53. let FINISH = false;
  54.  
  55. // 创建文件夹
  56. var createFolder = function (folderName, callback) {
  57. GM_xmlhttpRequest({
  58. url: EAGLE_CREATE_FOLDER_API_URL,
  59. method: "POST",
  60. data: JSON.stringify({
  61. folderName: folderName
  62. }),
  63. onload: function (response) {
  64. try {
  65. var result = JSON.parse(response.response);
  66. if (result.status === "success" && result.data && result.data.id) {
  67. callback(undefined, result.data);
  68. } else {
  69. callback(true);
  70. }
  71. } catch (err) {
  72. callback(true);
  73. }
  74. }
  75. });
  76. };
  77.  
  78. function addImageToEagle(data) {
  79. GM_xmlhttpRequest({
  80. url: EAGLE_IMPORT_API_URL,
  81. method: "POST",
  82. data: JSON.stringify(data),
  83. onload: function (response) {
  84. ajaxFinished();
  85. }
  86. });
  87. }
  88.  
  89. function updateDialog()
  90. {
  91. $(SELECTOR_DIALOG).html(`Total File: ${DOWNLOAD_COUNTER} files.`);
  92.  
  93. if(FINISH == true)
  94. {
  95. $(SELECTOR_DIALOG).html(`${DOWNLOAD_COUNTER} Files Queued!`);
  96. }
  97. }
  98.  
  99. function ajaxStarted() {
  100. requestsPending++;
  101. $(PENDING_DIALOG).html(`Download Progress: ${requestsPending}`);
  102. }
  103. function ajaxFinished() {
  104. requestsPending--;
  105. $(PENDING_DIALOG).html(`Download Progress: ${requestsPending}`);
  106. if(requestsPending == 0 && FINISH == true){
  107. $(PENDING_DIALOG).html(`Download Completed!`);
  108. setTimeout(function(){
  109. $(SELECTOR_DIALOG).remove();
  110. $(PENDING_DIALOG).remove();
  111. }, 1000);
  112. }
  113. }
  114.  
  115. function getImages(folder) {
  116. DOWNLOAD_COUNTER = 0;
  117. TOTAL_COUNTER = 0;
  118. $(SELECTOR_IMAGE).each(function (i, e) {
  119. let index = i;
  120. let IMAGE_LINK_URL = $(e).closest('a')[0].href;
  121. let IMAGE_AMOUNT = 1;
  122. let IMAGE_AMOUNT_P = $(e).closest("a").find("div:first span")['prevObject'][0].innerText.split('R-18\n');
  123. if(IMAGE_AMOUNT_P.length == 2){
  124. IMAGE_AMOUNT = IMAGE_AMOUNT_P[1] * 1;
  125. }else if(IMAGE_AMOUNT_P.length == 1){
  126. if(IMAGE_AMOUNT_P[0] == "R-18"){
  127. IMAGE_AMOUNT = 1;
  128. }else if(IMAGE_AMOUNT_P[0] == ""){
  129. IMAGE_AMOUNT = 1;
  130. }else{
  131. var r18g_filter = IMAGE_AMOUNT_P[0].split('R-18G\n');
  132. if(r18g_filter.length == 2){
  133. IMAGE_AMOUNT = r18g_filter[1] * 1;
  134. }else if(r18g_filter.length == 1){
  135. if(r18g_filter[0] == "R-18G"){
  136. IMAGE_AMOUNT = 1;
  137. }else if(r18g_filter[0] == ""){
  138. IMAGE_AMOUNT = 1;
  139. }else{
  140. IMAGE_AMOUNT = IMAGE_AMOUNT_P[0] * 1;
  141. }
  142. }
  143. }
  144. }
  145.  
  146. TOTAL_COUNTER += IMAGE_AMOUNT;
  147.  
  148. updateDialog();
  149.  
  150. $.get(IMAGE_LINK_URL, function (html) {
  151. var parser = new DOMParser();
  152. var doc = parser.parseFromString(html, "text/html");
  153. var preloadData = doc.querySelectorAll('meta#meta-preload-data')[0];
  154.  
  155. let content = JSON.parse(preloadData.content);
  156.  
  157. let IMAGE_ID = Object.keys(content.illust)[0];
  158. let IMAGE_URL = content.illust[IMAGE_ID].urls.original;
  159. let IMAGE_TYPE = content.illust[IMAGE_ID].urls.original.split(".").pop();
  160. let IMAGE_TITLE = content.illust[IMAGE_ID].title
  161. let IMAGE_DESCRIPTION = content.illust[IMAGE_ID].alt;
  162. let IMAGE_WEBSITE = content.illust[IMAGE_ID].extraData.meta.canonical;
  163. let IMAGE_TAGS = Object.values(content.illust[IMAGE_ID].tags.tags).map(item => item.tag);
  164.  
  165. for (let i = 0; i <= (IMAGE_AMOUNT - 1); i++) {
  166. ajaxStarted();
  167. let DOWNLOAD_IMAGE_URL = IMAGE_URL.replace("p0", "p" + i);
  168. console.log("prepare download: ", DOWNLOAD_IMAGE_URL)
  169.  
  170. let image = {
  171. "url": DOWNLOAD_IMAGE_URL,
  172. "name": IMAGE_TITLE,
  173. "website": IMAGE_WEBSITE,
  174. "annotation": IMAGE_DESCRIPTION,
  175. "folderId": folder.id,
  176. "headers": {
  177. "referer": IMAGE_WEBSITE
  178. }
  179. };
  180.  
  181. if(SUPPORT_TAGS)
  182. {
  183. image.tags = IMAGE_TAGS;
  184. }
  185.  
  186. DOWNLOAD_COUNTER++;
  187. addImageToEagle(image);
  188. console.log(index, $(SELECTOR_IMAGE).length - 1);
  189. updateDialog();
  190.  
  191. }
  192. if(index == $(SELECTOR_IMAGE).length - 1){
  193. FINISH = true;
  194. }
  195. updateDialog();
  196. });
  197. });
  198.  
  199.  
  200. }
  201.  
  202. var loaderTimerCounter = 0;
  203. var folderName;
  204. var folderData, folderLoader;
  205.  
  206. console.log("Pixiv to Eagle")
  207.  
  208. document.addEventListener('keydown', keydown);
  209.  
  210. function keydown(e) {
  211.  
  212. if (e.altKey && e.key === 'l') { // ALT+L
  213.  
  214. e.preventDefault(); // prevent default action of key
  215.  
  216. console.log("download initiated.");
  217.  
  218. $("body").append(`<div id="save-to-eagle-dialog" style=" display: block; position: fixed; width: 400px; height: 100px;margin-top:25px;margin-left:25px; text-align: left;font-size:1.5em;"><div id="queue">prepare to start ...</div></br><div id="download">Download Progress: `+requestsPending+`</div></div>`);
  219.  
  220. if (location.href.indexOf("pixiv.") === -1) {
  221. alert("This script only works on pixiv.net.");
  222. return;
  223. }
  224.  
  225. DOWNLOAD_COUNTER = 0;
  226. TOTAL_COUNTER = 0;
  227. FINISH = false;
  228.  
  229. if(folderData==null){
  230. initFolder();
  231. }else{
  232. getImages(folderData);
  233. }
  234. }
  235. }
  236.  
  237. function initFolder(){
  238. folderName = document.querySelector("h1") && document.querySelector("h1").innerText || "Pixiv";
  239. createFolder(folderName, function (err, folder) {
  240. if (folder) {
  241. folderData = folder;
  242. getImages(folderData);
  243. } else {
  244. alert("软件尚未打开,或当前软件版本不支持,需至 Eagle 官网下载,手动重新安装最新版本");
  245. }
  246. });
  247. }
  248. })();