Greasy Fork is available in English.
打开网页时,查询常用的 RSS 后缀并验证是否可用,在网页右下角显示,可一键复制。添加了一些自用的规则, 如 GitHub commits 和 Twitter (Google News)
当前为
// ==UserScript==
// @name RSS 订阅链接查找器(扩展版)
// @namespace http://greasyfork.icu/users/1171320
// @version 1.05
// @description 打开网页时,查询常用的 RSS 后缀并验证是否可用,在网页右下角显示,可一键复制。添加了一些自用的规则, 如 GitHub commits 和 Twitter (Google News)
// @author Lama AI 辅助
// @match *://*/*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_setClipboard
// @license MIT
// ==/UserScript==
(function() {
'use strict';
if (window.self !== window.top) return; // 排除 iframe
const rssLinks = new Set();
const possibleRssPaths = [
'/rss',
'/feed',
'/atom.xml',
'/rss.xml',
'/feed.xml',
'/index.xml',
'/feed.atom',
'/rss.json',
'/atom',
'/index.atom',
'/index.rss'
// 可添加其他常见的 RSS 路径
];
const xmlRegex = /<\?xml.*?<rss|<feed/; // 用于检测返回内容是否为 XML/RSS/Atom
function addStyle() {
GM_addStyle(`
#rss-finder-container {
position: fixed;
bottom: 20px;
right: 20px;
background: #fdfdfd;
border: 1px solid #ccc;
padding: 10px;
max-height: 300px;
overflow-y: auto;
z-index: 9999;
}
#rss-finder-container h4{
margin:0px;
margin-bottom:5px;
}
#rss-finder-list {
list-style: none;
padding: 0;
}
#rss-finder-list li {
margin-bottom: 5px;
display: flex;
align-items: center;
font-size: 0.8em;
}
#rss-finder-list li a {
color: blue;
text-decoration: none;
margin-right: 5px;
}
#rss-finder-list li button {
font-size: 0.6em;
padding: 2px 5px;
margin-left: auto;
cursor: pointer;
}
`);
}
function findRssLinks() {
// 查找 link 标签
const linkTags = document.querySelectorAll('link[type="application/rss+xml"], link[type="application/atom+xml"]');
linkTags.forEach(link => {
if (link.href) {
addRssLink(link.href);
}
});
// 查找页面 meta 标签
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);
});
// GitHub Actions 仓库
if (window.location.hostname === 'github.com' && window.location.pathname.split('/').length === 3) {
const [user, repo] = window.location.pathname.slice(1).split('/');
addRssLink(`https://github.com/${user}.atom`);
addRssLink(`https://github.com/${user}/${repo}/commits.atom`);
addRssLink(`https://github.com/${user}/${repo}/releases.atom`);
}
// 尝试从Google News搜索Twitter
if (window.location.hostname === "twitter.com" && window.location.pathname.startsWith('/')){
const userName = window.location.pathname.slice(1)
if(userName)
addRssLink(`https://news.google.com/rss/search?q=site:twitter.com/${userName}+when:7d`)
}
// 查找特定类名的 RSS 链接
const rssSubscribeLinks = document.querySelectorAll('a.rss-subscribe');
rssSubscribeLinks.forEach(link => {
if(link.href){
addRssLink(link.href);
}
})
}
function addRssLink(url) {
if(rssLinks.has(url)) return;
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload: function(response) {
if (response.status === 200 && xmlRegex.test(response.responseText)) {
rssLinks.add(url);
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 = '<h4>可用RSS订阅:</h4><ul id="rss-finder-list"></ul>';
document.body.appendChild(container);
setTimeout(() => {
if(container) container.style.display = 'none';
}, 15000);
}
const list = container.querySelector('#rss-finder-list');
list.innerHTML = '';
rssLinks.forEach(url => {
const li = document.createElement('li');
const a = document.createElement('a');
a.href = url;
a.target = '_blank';
a.rel = 'noopener noreferrer';
a.textContent = url;
const copyButton = document.createElement('button');
copyButton.textContent = '复制';
copyButton.onclick = function() {
navigator.clipboard.writeText(url).then(() => {
console.log('复制成功:', url);
}).catch(err => {
console.error('复制失败:', err);
});
};
li.appendChild(a);
li.appendChild(copyButton);
list.appendChild(li);
});
}
addStyle();
window.onload = findRssLinks;
})();