// ==UserScript== // @name RSS 订阅链接查找器(扩展版) // @namespace https://greasyfork.org/users/1171320 // @version 1.08 // @description 打开网页时,查询常用的 RSS 后缀并验证是否可用,在网页右下角显示,可一键复制。除常见网站、博客, 添加 BiliBili、GitHub、Twitter // @author yzcjd // @author2 ChatGPT4 辅助 // @match *://*/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; if (window.self !== window.top) return; // 排除 iframe const rssLinks = new Map(); const possibleRssPaths = [ '/rss', '/feed', '/atom.xml', '/rss.xml', '/feed.xml', '/index.xml', '/feed.atom', '/rss.json', '/atom', '/index.atom', '/index.rss' ]; const xmlRegex = /<\?xml.*? { if (link.href) addRssLink(link.href, '页面内RSS'); }); const metaTags = document.querySelectorAll('meta[type="application/rss+xml"], meta[type="application/atom+xml"]'); metaTags.forEach(meta => { if (meta.content) addRssLink(meta.content, '页面内RSS'); }); possibleRssPaths.forEach(path => { const guessedUrl = window.location.origin + path; addRssLink(guessedUrl, '常规猜测'); }); if (window.location.hostname === 'github.com') { const parts = window.location.pathname.split('/').filter(Boolean); if (parts.length === 1) { addRssLink(`https://github.com/${parts[0]}.atom`, 'GitHub 用户动态'); } else if (parts.length === 2) { addRssLink(`https://github.com/${parts[0]}/${parts[1]}/commits.atom`, 'GitHub 提交记录'); addRssLink(`https://github.com/${parts[0]}/${parts[1]}/releases.atom`, 'GitHub 发布记录'); } } if (window.location.hostname === 'twitter.com') { const username = window.location.pathname.slice(1); if (username) { addRssLink(`https://news.google.com/rss/search?q=site:twitter.com/${username}+when:7d`, 'Twitter (7天更新)'); } } if (window.location.hostname === 'space.bilibili.com') { const uidMatch = window.location.pathname.match(/^\/(\d+)/); if (uidMatch) { const uid = uidMatch[1]; addRssLink(`https://rsshub.app/bilibili/user/article/${uid}`, 'Bilibili 专栏文章'); addRssLink(`https://rsshub.app/bilibili/user/video/${uid}`, 'Bilibili 投稿视频'); } } const rssSubscribeLinks = document.querySelectorAll('a.rss-subscribe'); rssSubscribeLinks.forEach(link => { if (link.href) addRssLink(link.href, '订阅链接'); }); } function addRssLink(url, label = '') { if (rssLinks.has(url)) return; GM_xmlhttpRequest({ method: 'GET', url: url, onload: function(response) { if (response.status === 200 && xmlRegex.test(response.responseText)) { rssLinks.set(url, label); updateRssList(); } }, onerror: function(error) { console.log(`加载失败: ${url}`, error); } }); } function updateRssList() { let container = document.getElementById('rss-finder-container'); if (!container) { container = document.createElement('div'); container.id = 'rss-finder-container'; container.innerHTML = '

可用 RSS 订阅:

'; document.body.appendChild(container); setTimeout(() => { if (container) container.style.display = 'none'; }, 15000); } const list = container.querySelector('#rss-finder-list'); list.innerHTML = ''; rssLinks.forEach((label, url) => { const li = document.createElement('li'); const a = document.createElement('a'); a.href = url; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.textContent = label ? `[${label}] ${url}` : url; const copyButton = document.createElement('button'); copyButton.textContent = 'copy'; copyButton.style.transition = 'all 0.3s ease'; copyButton.style.fontSize = '0.8em'; copyButton.style.color = '#666'; copyButton.onclick = function() { GM_setClipboard(url); copyButton.textContent = 'success'; copyButton.style.color = 'green'; copyButton.style.fontSize = '1em'; copyButton.style.transform = 'scale(1.2)'; setTimeout(() => { copyButton.textContent = 'copy'; copyButton.style.color = '#666'; copyButton.style.fontSize = '0.8em'; copyButton.style.transform = 'scale(1)'; }, 3000); }; li.appendChild(a); li.appendChild(copyButton); list.appendChild(li); }); } addStyle(); findRssLinks(); })();