rsshub helper

Make copy rsshub link easy.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         rsshub helper
// @namespace    http://tampermonkey.net/
// @description  Make copy rsshub link easy.
// @author       xiaxuchen
// @match        https://rsshub.netlify.app/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
// @grant GM_xmlhttpRequest
// @grant GM_download
// @license MIT
// @version 2024-10-01-v2
// @connect https://rsshub.rssforever.com/
// @connect https://rsshub.feeded.xyz/
// @connect https://hub.slarker.me/
// @connect https://rsshub.liumingye.cn/
// @connect https://rsshub-instance.zeabur.app/
// @connect https://rss.fatpandac.com/
// @connect https://rsshub.pseudoyu.com/
// @connect https://rsshub.friesport.ac.cn/
// @connect https://rsshub.friesport.ac.cn/us
// @connect https://rsshub.atgw.io/
// @connect https://rsshub.rss.tips/
// @connect https://rsshub.mubibai.com/
// @connect https://rsshub.ktachibana.party/
// @connect https://rsshub.woodland.cafe/
// @connect https://rsshub.aierliz.xyz/
// @connect *
// ==/UserScript==

(function() {
    'use strict';
    const ORIGIN_HOST = 'https://rsshub.app/';
    const INSTANCE_PAGE = 'https://rsshub.netlify.app/zh/instances';
    const KEY_RETURN_URL = 'returnUrl';
    const KEY_INSTANCES = 'instanceList';
    // 尝试从localStorage中获取已经填充的列表
    let list = JSON.parse(localStorage.getItem(KEY_INSTANCES)) || [];
    function checkList() {
        if (location.href.startsWith(INSTANCE_PAGE)) {
            console.log("In instance page, skip check list and prepare to refresh list");
            return;
        }
        // 检查列表是否为空
        if (list.length === 0) {
            console.log("Instance list is empty and go to instance page to acquire.")
            // 保存当前页面的URL
            const currentUrl = window.location.href;

            // 将当前页面的URL存储在localStorage中
            localStorage.setItem(KEY_RETURN_URL, currentUrl);

            // 跳转到获取实例信息的页面
            window.location.href = INSTANCE_PAGE;
        } else {
            // 如果列表不为空,直接使用列表
            console.log('List is already filled:', list);
        }
    }

    function saveInstances() {
        if (!location.href.startsWith(INSTANCE_PAGE)) {
            console.log("Not instance page, skip instance save");
            return;
        }
        list = [];
        // 获取ID为'public'的元素
        const publicElement = document.getElementById('public');
        if (publicElement) {
            // 获取ID为'public'的元素下的所有表格
            const table = publicElement.nextElementSibling;
            // 获取表格中的所有行
            const rows = table.getElementsByTagName('tr');

            // 遍历每行
            for (let row of rows) {
                // 获取行中的第一个单元格
                const firstCell = row.getElementsByTagName('td')[0];
                if (firstCell) {
                    const cellA = firstCell.getElementsByTagName('a')[0];
                    list.push(cellA.href);
                }
            }
            console.log(`${list.length} instances found: ${list.join(",")}`);
            localStorage.setItem(KEY_INSTANCES, JSON.stringify(list));
            const returnUrl = localStorage.getItem(KEY_RETURN_URL);
            if (returnUrl) {
                console.log(`ReturnUrl found and prepare to return`);
                localStorage.removeItem(KEY_RETURN_URL);
                location.href = returnUrl;
            }
        } else {
            console.error("Element with ID 'public' not found.");
        }

    }
    function getInstanceUrl(url, host) {
        return url.replace(ORIGIN_HOST, host);
    }

    function checkReq(url) {
        let p = new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url,
                onload: function(response) {
                    // 解析响应数据
                    if (response.status === 200) {
                        console.log(`Request success: ${url}`);
                        resolve(url);
                    } else {
                        console.error(`Request failed: ${url}`);
                        reject(`Request failed: ${url}`);
                    }
                },
                onerror: function(error) {
                    reject(error);
                }
            });
        });
        return p;
    }
    async function getUpUrl(url) {
        console.log("Get up url.");
        return Promise.any(list.map(host => getInstanceUrl(url, host)).map(item => checkReq(item)));
    }
    async function writeToClipboard(text) {
        try {
            await navigator.clipboard.writeText(text);
            console.log('Text successfully copied to clipboard:', text);
        } catch (err) {
            console.error('Failed to write to clipboard:', err);
        }
    }
    function init() {
        // 尝试从localStorage中获取已经填充的列表
        list = JSON.parse(localStorage.getItem(KEY_INSTANCES)) || [];
        checkList();
        saveInstances();
    }
    // 等待页面加载完成
    window.addEventListener('load', async () => {
        init();
        // 添加复制事件监听器
        document.addEventListener('copy', async function(event) {
            init();
            if (list.length == 0) {
                return;
            }
            // 获取选中的文本
            const selection = window.getSelection().toString().trim();
            if (!selection.startsWith(ORIGIN_HOST)) {
                return;
            }
            const path = prompt("拦截复制,请确认需要获取镜像的path(可修改):", selection.slice(ORIGIN_HOST.length));
            if (path == null) {
                return;
            }
             // 阻止默认的复制行为
            event.preventDefault();
            try {
                const upUrl = await getUpUrl(ORIGIN_HOST + path);
                // 将修改后的文本设置到剪贴板
                if (event.clipboardData) {
                    await writeToClipboard(upUrl);
                    console.log(`Original text: ${selection}`);
                    console.log(`Modified text: ${upUrl}`);
                    alert(`链接已写入剪切板,${upUrl}`);
                }
            } catch (e) {
                alert("所有镜像都无法访问该地址.");
                return;
            }
        });

    });
})();