feat(route): add sitemap transform (#13297)

* feat(route): add sitemap transform

* chore: resolve lint errors

* chore: change router order

* chore: apply the suggestion (xml2js -> cheerio)

* chore: fix errors

* chore: add maintainer

* fix: sticks to sitemap protocol

---------
This commit is contained in:
Derrick Hwechul Cho 2023-09-15 05:29:58 -07:00 committed by GitHub
parent 2cc8a58304
commit 92a376d691
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 0 deletions

View File

@ -3,4 +3,5 @@ module.exports = {
'/rsshub/sponsors': ['DIYgod'],
'/transform/html/:url/:routeParams': ['ttttmr'],
'/transform/json/:url/:routeParams': ['ttttmr'],
'/transform/sitemap/:url/:routeParams?': ['flrngel'],
};

View File

@ -3,4 +3,5 @@ module.exports = (router) => {
router.get('/sponsors', require('./sponsors'));
router.get('/transform/html/:url/:routeParams', require('./transform/html'));
router.get('/transform/json/:url/:routeParams', require('./transform/json'));
router.get('/transform/sitemap/:url/:routeParams?', require('./transform/sitemap'));
};

View File

@ -0,0 +1,52 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const config = require('@/config').value;
module.exports = async (ctx) => {
if (!config.feature.allow_user_supply_unsafe_domain) {
ctx.throw(403, `This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
}
const { url } = ctx.params;
const response = await got({
method: 'get',
url,
});
const routeParams = new URLSearchParams(ctx.params.routeParams);
const $ = cheerio.load(response.data, { xmlMode: true });
const rssTitle = routeParams.get('title') ? routeParams.get('title') : ($('urlset url').length && $('urlset url').first().find('loc').text() ? $('urlset url').first().find('loc').text() : 'Sitemap');
let items;
const urls = $('urlset url').toArray();
if (urls && urls.length) {
items = urls.map((item) => {
try {
const title = $(item).find('loc').text() || '';
const link = $(item).find('loc').text() || '';
const description = $(item).find('loc').text() || '';
const pubDate = $(item).find('lastmod').text() || undefined;
return {
title,
link,
description,
pubDate,
};
} catch (e) {
return null;
}
})
.filter(Boolean);
}
else {
items = [];
}
ctx.state.data = {
title: rssTitle,
link: url,
description: `Proxy ${url}`,
item: items,
};
};

View File

@ -646,6 +646,25 @@ Parsing of `routeParams` parameter:
</Route>
### Sitemap {#transformation-sitemap}
Specify options (in the format of query string) in parameter `routeParams` parameter to extract data from Sitemap. (Follows Sitemap Protocol 0.9)
| Key | Meaning | Accepted Values | Default |
|-----------------|----------------------------------------------------------------|-----------------|------------------------|
| `title` | The title of the RSS | `string` | Extract from `<title>` |
<Route author="flrngel" example="/rsshub/transform/xml/https%3A%2F%2Fwww.sitemaps.org%2Fsitemap.xml/" path="/rsshub/transform/html/:url/:routeParams?" paramsDesc={['`encodeURIComponent`ed URL address', 'Transformation rules, requires URL encode']} selfhost="1">
Parameters parsing in the above example:
| Parameter | Value |
|---------------|-------------------------------------------|
| `url` | `https://www.sitemaps.org/sitemap.xml` |
| `routeParams` | `title=Example` |
</Route>
## TSSstatus (iOS downgrade channel) {#tssstatus-ios-downgrade-channel}
### Status {#tssstatus-ios-downgrade-channel-status}