rsshub
Version:
Make RSS Great Again!
116 lines (98 loc) • 4.47 kB
text/typescript
import { Route } from '@/types';
import cache from '@/utils/cache';
import parser from '@/utils/rss-parser';
import { load } from 'cheerio';
import utils from './utils';
import ofetch from '@/utils/ofetch';
export const route: Route = {
path: '/:site?/:channel?',
name: 'News',
maintainers: ['HenryQW', 'DIYgod', 'pseudoyu'],
handler,
example: '/bbc/world-asia',
parameters: {
site: '语言,简体或繁体中文',
channel: 'channel, default to `top stories`',
},
categories: ['traditional-media'],
description: `Provides a better reading experience (full text articles) over the official ones.
Support major channels, refer to [BBC RSS feeds](https://www.bbc.co.uk/news/10628494). Eg, \`business\` for \`https://feeds.bbci.co.uk/news/business/rss.xml\`.
- Channel contains sub-directories, such as \`https://feeds.bbci.co.uk/news/world/asia/rss.xml\`, replace \`/\` with \`-\`, \`/bbc/world-asia\`.`,
};
async function handler(ctx) {
let feed, title, link;
// 为了向下兼容,这里 site 对应的是中文网文档中的 lang,英文网文档中的 channel
// 英文网不会用到 channel
const { site, channel } = ctx.req.param();
if (site) {
switch (site.toLowerCase()) {
case 'chinese':
title = 'BBC News 中文网';
feed = await (channel ? parser.parseURL(`https://www.bbc.co.uk/zhongwen/simp/${channel}/index.xml`) : parser.parseURL('https://www.bbc.co.uk/zhongwen/simp/index.xml'));
break;
case 'traditionalchinese':
title = 'BBC News 中文網';
feed = await (channel ? parser.parseURL(`https://www.bbc.co.uk/zhongwen/trad/${channel}/index.xml`) : parser.parseURL('https://www.bbc.co.uk/zhongwen/trad/index.xml'));
link = 'https://www.bbc.com/zhongwen/trad';
break;
// default to bbc.com
default:
feed = await parser.parseURL(`https://feeds.bbci.co.uk/news/${site.split('-').join('/')}/rss.xml`);
title = `BBC News ${site}`;
link = `https://www.bbc.co.uk/news/${site.split('-').join('/')}`;
break;
}
} else {
feed = await parser.parseURL('https://feeds.bbci.co.uk/news/rss.xml');
title = 'BBC News Top Stories';
link = 'https://www.bbc.co.uk/news';
}
const items = await Promise.all(
feed.items
.filter((item) => item && item.link)
.map((item) =>
cache.tryGet(item.link, async () => {
try {
const linkURL = new URL(item.link);
if (linkURL.hostname === 'www.bbc.com') {
linkURL.hostname = 'www.bbc.co.uk';
}
const response = await ofetch(linkURL.href, {
retryStatusCodes: [403],
});
const $ = load(response);
const path = linkURL.pathname;
let description;
switch (true) {
case path.startsWith('/sport'):
description = item.content;
break;
case path.startsWith('/sounds/play'):
description = item.content;
break;
case path.startsWith('/news/live'):
description = item.content;
break;
default:
description = utils.ProcessFeed($);
}
return {
title: item.title || '',
description: description || '',
pubDate: item.pubDate || new Date().toUTCString(),
link: item.link,
};
} catch {
return {} as Record<string, any>;
}
})
)
);
return {
title,
link,
image: 'https://www.bbc.com/favicon.ico',
description: title,
item: items.filter((item) => Object.keys(item).length > 0),
};
}