Save Yandex Collection images to Eagle

Launch a script on Yandex Collection that automatically scrolls the page and converts all images on the page into large images (with links, names) to be added to the Eagle App.

目前为 2021-04-22 提交的版本。查看 最新版本

// ==UserScript==
// @name                Save Yandex Collection images to Eagle
// @namespace           https://eagle.cool/
// @description         Launch a script on Yandex Collection that automatically scrolls the page and converts all images on the page into large images (with links, names) to be added to the Eagle App.

// @author              Augus
// @license             MIT License

// @match               *://*/*
// @grant               GM_xmlhttpRequest
// @run-at              context-menu

// @date                04/22/2021
// @modified            04/22/2021
// @version             0.0.1

// ==/UserScript==

(function() {

    if (location.href.indexOf("yandex.") === -1) {
        alert("This script only works on yandex.com.");
        return;
    }

    let bigGridBtn = document.querySelector(".cl-tabs-scroll__item_type_tabs");
    if (bigGridBtn) bigGridBtn.click();

    // Eagle API Server
    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`;

    const SELECTOR_IMAGE = "img.cl-picture__image";
    const SELECTOR_LINK = ".cl-picture a";
    const SELECTOR_SPINNER = `.cl-button.cl-button_size_M.cl-button_type_white.cl-button_shadow.cl-board-footer__more-button`;

    var startTime = Date.now();
    var scrollInterval;        
    var lastScrollPos;         
    var retryCount = 0;        
    var scrollDelay = 250;     
    var retryThreshold = 20;   
    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, window.scrollY + 125);
        // 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));
            for (var i = 0; i < links.length; i++) {
                if (links[i].contains(img)) {
                    return absolutePath(links[i].href);
                }
            }
            return "";
        };

        var getSrc = function (img) {
            let src = img.src;
            return src.split("/s")[0] + "/optimize";
        }

        var getName = function(img) {
            var articles = Array.from(document.querySelectorAll(".cl-card-vertical-teaser_article"));
            for (var i = 0; i < articles.length; i++) {
                if (articles[i].contains(img)) {
                    return articles[i].textContent;
                }
            }
            return "";
        };

        imgs = imgElements.map(function(elem, index) {
            pageInfo.imageCount++;
            return {
                name: getName(elem) || "",
                url: getSrc(elem) || elem.src,
                website: getLink(elem),
                modificationTime: startTime - pageInfo.imageCount
            }
        });

        return imgs;
    };

    var fetchImages = function() {
        var currentScrollPos = window.scrollY;
        scarollToBottom();

        addImagesToEagle(getImgs());

        if (lastScrollPos === currentScrollPos || currentScrollPos === 0) {
            if (!document.querySelector(SELECTOR_SPINNER)) {
                retryCount++;
                console.log(retryCount)
                if (retryCount >= retryThreshold) {
                    clearInterval(scrollInterval);
                    alert(`Scan completed, a total of ${pageInfo.imageCount} images have been added to Eagle App.`);
                }
            }
            else {
                document.querySelector(SELECTOR_SPINNER).click();
            }
        }
        else {
            retryCount = 0;
            var images = getImgs();
            addImagesToEagle(images);
        }
    }

    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;
    }

    scarollToTop();

    var folderName = document.querySelector("h1") && document.querySelector("h1").innerText || "Yandex Collection";
    createFolder(folderName, function(err, folder) {
        if (folder) {
            pageInfo.folderId = folder.id;
            scrollInterval = setInterval(fetchImages, scrollDelay);
        } else {
            alert("Please open Eagle App first.");
        }
    });

})();