// ==UserScript== // @name Save Pixiv Pictures to Eagle // @name:zh 下载Pixiv图片到Eagle // @namespace https://github.com/miracleXL // @icon https://www.pixiv.net/favicon.ico // @version 0.2.5 // @description Collect pictures in pixiv to eagle. // @description:zh 在Pixiv上添加可以导入图片到Eagle的下载按钮 // @author miracleXL // @match https://www.pixiv.net/artworks/* // @connect localhost // @connect www.pixiv.net // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @downloadURL none // ==/UserScript== (function(){ 'use strict'; if (location.href.indexOf("pixiv.net") === -1) { console.log("This script only works on pixiv.net."); return; } // Eagle API 服务器位置 const EAGLE_SERVER_URL = "http://localhost:41595"; const EAGLE_IMPORT_API_URL = `${EAGLE_SERVER_URL}/api/item/addFromURL`; const EAGLE_IMPORT_API_URLS = `${EAGLE_SERVER_URL}/api/item/addFromURLs`; const EAGLE_CREATE_FOLDER_API_URL = `${EAGLE_SERVER_URL}/api/folder/create`; const EAGLE_GET_FOLDERS_API_URL = `${EAGLE_SERVER_URL}/api/folder/list`; //Pixiv页面中的标签和标签翻译 const TAG_CLASS = "gtm-new-work-tag-event-click"; const TAG_TRANS_CLASS = "gtm-new-work-translate-tag-event-click"; const HEADERS = { "referer": "https://www.pixiv.net/", "sec-fetch-dest": "image", "sec-fetch-mode": "no-cors", "sec-fetch-site": "cross-site", }; // 每秒尝试加载一次 let loadMain = setInterval(main, 1000); function main(){ window.clearInterval(loadMain); let divs_section = document.getElementsByClassName("sc-181ts2x-0 jPZrYy")[0]; if(divs_section === undefined) return; //暂时无法保存动图,如果是动图则什么都不做 if(document.getElementsByClassName("tu09d3-1 MNNrM").length !== 0){ console.log("无法保存动图!"); return; } let image = document.getElementsByClassName("sc-1qpw8k9-3 ckeRFU")[0]; let mode = image ? "image" : "manga" ; addButtons(mode,divs_section); document.getElementsByClassName("sc-1yvhotl-2 hGipVQ")[0].onchange = main; } function download(data){ GM_xmlhttpRequest({ url: EAGLE_IMPORT_API_URL, method: "POST", data: JSON.stringify(data), onload: function(response) { if(response.statusText !== "OK"){ console.log("请检查eagle是否打开!"); alert("下载失败!") } } }); } async function downloadAll(data){ GM_xmlhttpRequest({ url: EAGLE_IMPORT_API_URLS, method: "POST", data: JSON.stringify(data), onload: function(response) { if(response.statusText !== "OK"){ alert("请检查eagle是否打开!"); console.log("下载失败!") } } }); } // 获取文件夹id async function getFolderId(author){ let folders = await getFolders(); let dlFolder; if(folders){ for(let folder of folders){ if(folder.name === "画师"){ for(let f of folder.children){ if(f.name === author) dlFolder = f; } } if(folder.name === author){ dlFolder = folder; } } if(dlFolder === undefined) dlFolder = await creatFolder(author); } else{ console.log("获取文件夹信息失败!"); alert("下载失败!"); return; } return dlFolder.id; } // 获取文件夹 function getFolders(){ return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: EAGLE_GET_FOLDERS_API_URL, method: "GET", redirect:'follow', onload: function(response) { if(response.status !== 200){ reject(); } resolve(JSON.parse(response.response).data); } }); }) } // 创建文件夹 function creatFolder(folderName){ return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: EAGLE_CREATE_FOLDER_API_URL, method: "POST", data: JSON.stringify({ folderName: folderName }), onload: function(response) { var result = JSON.parse(response.response); if (result.status === "success" && result.data && result.data.id) { return resolve(result.data); } else{ return reject(); } } }) }) } function getImageData(){ let images = document.getElementsByClassName("sc-1qpw8k9-3 ckeRFU")[0];// 单图 images = images ? images : document.getElementsByClassName("sc-1qpw8k9-3 lmFZOm")[0];//多图 //获取标题 let name = document.getElementsByClassName("sc-1u8nu73-3 feoVvS")[0]; if(name === undefined){ name = ""; }else{ name = name.textContent; } //获取描述(Eagle2.0版本以下因bug无法生效) let annotation = document.getElementById("expandable-paragraph-0"); if(annotation){annotation = annotation.textContent;} else{annotation = "";} //把pixiv标签和标签翻译添加进eagle标签 let tags = []; let firstTag = document.getElementsByClassName("nqp4a5-0")[0]; if(firstTag !== undefined){ tags.push(firstTag.textContent); } document.getElementsByClassName(TAG_CLASS).forEach(item => {tags.push(item.text);}); document.getElementsByClassName(TAG_TRANS_CLASS).forEach(item => {tags.push(item.text);}); let data = { "url": images.href, "name": name, "website": document.URL, "tags": tags, "headers": HEADERS } let author = document.getElementsByClassName("sc-10gpz4q-5 bUnVlH")[0].textContent.split("@")[0]; // 删除多余后缀,为避免误伤,同时使用多种符号不作处理 let patt = / *[@@◆■◇☆].+/; let test = author.match(patt); if(test && test.length === 1){ author = author.replace(test[0],""); } return [data,author]; }; function getImagesData(){ let images = document.getElementsByClassName("sc-1qpw8k9-3 ckeRFU");//单图 images = images[0] ? images : document.getElementsByClassName("sc-1qpw8k9-3 lmFZOm");//多图 let data = {"items":[]} //获取标题 let name = document.getElementsByClassName("sc-1u8nu73-3 feoVvS")[0]; if(name === undefined){ name = ""; }else{ name = name.textContent; } //获取描述 let annotation = document.getElementById("expandable-paragraph-0"); if(annotation){annotation = annotation.textContent;} else{annotation = "";} //把pixiv标签和标签翻译添加进eagle标签 let tags = []; let firstTag = document.getElementsByClassName("nqp4a5-0")[0]; if(firstTag !== undefined){ tags.push(firstTag.textContent); } document.getElementsByClassName(TAG_CLASS).forEach(item => {tags.push(item.text);}); document.getElementsByClassName(TAG_TRANS_CLASS).forEach(item => {tags.push(item.text);}); let count = 0; images.forEach(url => { if(url === undefined) return; data.items.push({ "url": url.href, "name": name + `_${count}`, "website": document.URL, "annotation": annotation, "tags": tags, "headers": HEADERS }); count++; }); console.log(`准备开始下载,共计${count}张图`) // 获取作者名 let author = document.getElementsByClassName("sc-10gpz4q-5 bUnVlH")[0].textContent; // 删除多余后缀,为避免误伤,同时使用多种符号不作处理 let patt = / *[@@◆■◇☆].+/; let test = author.match(patt); if(test && test.length === 1){ author = author.replace(test[0],""); } return [data,author]; }; function changeStyle(button){ button.className = "_1vHxmVH _35vRH4a"; } //在收藏按钮旁边添加下载按钮 function addButtons(mode,buttonPos){ let button = document.createElement('div'); button.setAttribute('class', 'sc-181ts2x-01'); button.setAttribute('style', 'margin-right: 23px;'); button.innerHTML = ''; if(buttonPos !== undefined){ buttonPos.appendChild(button); } //绑定点击按钮时下载事件 button.addEventListener("click", async function(){ //下载同时自动点赞+收藏 try{ document.getElementsByClassName("_35vRH4a")[0].click(); document.getElementsByClassName("kgq5hw-0 iPGEIN gtm-main-bookmark")[0].click(); }catch(e){} let [data, author] = getImagesData(); let dlFolderId = await getFolderId(author); if(dlFolderId === undefined){ console.log("创建文件夹失败!尝试直接下载……") } else{ data.folderId = dlFolderId; } downloadAll(data); changeStyle(button); }); // 若为多图添加复选框和下载选择按键……计划中是这样的 if(mode === "manga"){ let button2 = document.createElement('div'); button2.setAttribute('class', 'sc-181ts2x-01'); button2.setAttribute('style', 'margin-right: 23px;'); button2.innerHTML = ''; if(buttonPos) buttonPos.appendChild(button2); button2.addEventListener("click", async function(){ let [data, author] = getImageData(); let dlFolderId = await getFolderId(author); if(dlFolderId === undefined){ console.log("创建文件夹失败!尝试直接下载……") } else{ data.folderId = dlFolderId; } download(data); changeStyle(button2); }) } }; })();