rsshub
Version:
Make RSS Great Again!
93 lines (85 loc) • 3.13 kB
text/typescript
import { Route } from '@/types';
import cache from '@/utils/cache';
import { load } from 'cheerio';
import got from '@/utils/got';
import { parseDate } from '@/utils/parse-date';
import { parseItem } from './utils';
export const route: Route = {
path: '/:category_id',
categories: ['traditional-media'],
example: '/scmp/3',
parameters: { category_id: 'Category' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['scmp.com/rss/:category_id/feed'],
},
],
name: 'News',
maintainers: ['proletarius101'],
handler,
description: `See the [official RSS page](https://www.scmp.com/rss) to get the ID of each category. This route provides fulltext that the offical feed doesn't.`,
};
const getAttribs = (attribs?: { [key: string]: string }) => {
if (!attribs) {
return;
}
const obj: { [key: string]: string } = {};
for (const key in attribs) {
if (Object.hasOwn(attribs, key)) {
obj[key] = attribs[key];
}
}
return obj;
};
async function handler(ctx) {
const categoryId = ctx.req.param('category_id');
const rssUrl = `https://www.scmp.com/rss/${categoryId}/feed`;
const { data: response } = await got(rssUrl);
const $ = load(response, {
xmlMode: true,
});
const list = $('item')
.toArray()
.map((elem) => {
const item = $(elem);
const enclosure = item.find('enclosure').first();
const mediaContent = item.find(String.raw`media\:content`).toArray()[0];
const thumbnail = item.find(String.raw`media\:thumbnail`).toArray()[0];
return {
title: item.find('title').text(),
description: item.find('description').text(),
link: item.find('link').text().split('?utm_source')[0],
author: item.find('author').text(),
pubDate: parseDate(item.find('pubDate').text()),
enclosure_url: enclosure?.attr('url'),
enclosure_length: enclosure?.attr('length'),
enclosure_type: enclosure?.attr('type'),
media: {
content: mediaContent ? getAttribs(mediaContent.attribs) : {},
thumbnail: thumbnail?.attribs ? getAttribs(thumbnail.attribs) : undefined,
},
};
});
const items = await Promise.all(list.map((item) => cache.tryGet(item.link, () => parseItem(item))));
ctx.set('json', {
items,
});
return {
title: $('channel > title').text(),
link: $('channel > link').text(),
description: $('channel > description').text(),
item: items,
language: 'en-hk',
icon: 'https://assets.i-scmp.com/static/img/icons/scmp-icon-256x256.png',
logo: 'https://customerservice.scmp.com/img/logo_scmp@2x.png',
image: $('channel > image > url').text(),
};
}