// ==UserScript== // @name 导入 Pinterest 图片到 Eagle // @description 自动滚动 Pinterest 页面,并将 Pinterest 内容导入至 Eagle App // @author Augus Chen // @namespace https://eagle.cool/ // @homepageURL https://eagle.cool/ // @supportURL https://docs-cn.eagle.cool/ // @icon https://cn.eagle.cool/favicon.png // @license MIT // @include * // @grant GM_xmlhttpRequest // @run-at context-menu // @date 06/16/2020 // @modified 06/16/2020 // @version 0.0.1 // @downloadURL none // ==/UserScript== (function() { // Eagle API 服务器位置 const EAGLE_SERVER_URL = "http://localhost:41595"; const EAGLE_IMPORT_API_URL = `${EAGLE_SERVER_URL}/api/item/addFromURLs`; const EAGLE_CREATE_FOLDER_API_URL = `${EAGLE_SERVER_URL}/api/folder/create`; // Pinterest 当前图片、链接命名规则 const SELECTOR_IMAGE = "[data-grid-item] a img[srcset]"; const SELECTOR_LINK = "[data-grid-item] a"; var startTime = Date.now(); // 开始滚动时间 var scrollInterval; // 无限滚动,直到底部 var lastScrollPos; // 上一次滚轴位置 var retryCount = 0; // 目前重试次数 var scrollDelay = 500; // 滚动页面延迟 var retryThreshold = 4; // 无法滚动页面重试次数,当超过次数,表示到底部了 var pageInfo = { imageCount: 0, imageSet: {}, folderId: "" }; // 创建文件夹 var createFolder = function(folderName, callback) { GM_xmlhttpRequest({ url: EAGLE_CREATE_FOLDER_API_URL, method: "POST", data: JSON.stringify({ folderName: folderName }), onload: function(response) { try { var result = JSON.parse(response.response); if (result.status === "success" && result.data && result.data.id) { callback(undefined, result.data); } else { callback(true); } } catch (err) { callback(true); } } }); }; // 滚动至页面顶端 var scarollToTop = function() { window.scrollTo(0, 0); lastScrollPos = window.scrollY; }; // 滚动至页面底端 var scarollToBottom = function() { window.scrollTo(0, document.body.scrollHeight); // window.scrollTo(0, window.innerHeight); lastScrollPos = window.scrollY; }; // 取得当前画面所有图片链接 var getImgs = function() { var imgs = []; var imgElements = Array.from(document.querySelectorAll(SELECTOR_IMAGE)); // 避免重复添加 imgElements = imgElements.filter(function(elem) { var src = elem.src; if (!pageInfo.imageSet[src]) { pageInfo.imageSet[src] = true; return true; } return false; }); var getLink = function(img) { var links = Array.from(document.querySelectorAll(SELECTOR_LINK)); links.filter(function(link) { return link.contains(img); }); if (links && links[0] && links[0].href) { return absolutePath(links[0].href); } return ""; }; imgs = imgElements.map(function(elem, index) { pageInfo.imageCount++; return { name: elem.alt || "", url: getHighestResImg(elem) || elem.src, // 取得最大分辨率 website: getLink(elem), // 取得图片链接 modificationTime: startTime - pageInfo.imageCount // 强制设置时间,确保在 Eagle 顺序与 Pinterest 相同 } }); return imgs; }; // 滚动页面并取得图片信息,发送至 Eagle App var fetchImages = function() { var currentScrollPos = window.scrollY; scarollToBottom(); // 到底了 if (lastScrollPos === currentScrollPos) { retryCount++; if (retryCount >= retryThreshold) { clearInterval(scrollInterval); } } // 还有内容 else { retryCount = 0; var images = getImgs(); addImagesToEagle(images); } } // 将图片添加至 Eagle var addImagesToEagle = function(images) { GM_xmlhttpRequest({ url: EAGLE_IMPORT_API_URL, method: "POST", data: JSON.stringify({ items: images, folderId: pageInfo.folderId }), onload: function(response) {} }); } function absolutePath(href) { if (href && href.indexOf(" ") > -1) { href = href.trim().split(" ")[0]; } var link = document.createElement("a"); link.href = href; return link.href; } function getHighestResImg(element) { if (element.getAttribute('srcset')) { let highResImgUrl = ''; let maxRes = 0; let imgWidth, urlWidthArr; element.getAttribute('srcset').split(',').forEach((item) => { urlWidthArr = item.trim().split(' '); imgWidth = parseInt(urlWidthArr[1]); if (imgWidth > maxRes) { maxRes = imgWidth; highResImgUrl = urlWidthArr[0]; } }); return highResImgUrl; } else { return element.getAttribute('src'); } } // 脚本开始 scarollToTop(); // 创建本次保存使用文件夹 var folderName = document.querySelector("h1") && document.querySelector("h1").innerText || "Pinterest"; createFolder(folderName, function(err, folder) { if (folder) { // 持续滚动列表,直到列表没有更多内容 pageInfo.folderId = folder.id; scrollInterval = setInterval(fetchImages, 1000); } else { alert("An error has occurred or the Eagle app is not open."); } }); })();