feat(route): add alternativeto.net (#13320)

* feat(route): add alternativeto.net

* Update website/docs/routes/programming.md

* Update website/docs/routes/programming.md

---------
This commit is contained in:
JimenezLi 2023-09-17 01:54:27 +08:00 committed by GitHub
parent aba9c21290
commit b9604caaef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 131 additions and 0 deletions

View File

@ -0,0 +1,4 @@
module.exports = {
'/software/:name/:routeParams?': ['JimenezLi'],
'/platform/:name/:routeParams?': ['JimenezLi'],
};

View File

@ -0,0 +1,32 @@
const { baseURL, puppeteerGet } = require('./utils');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const name = ctx.params.name;
const query = new URLSearchParams(ctx.params.routeParams);
const link = `https://alternativeto.net/platform/${name}/?${query.toString()}`;
// use Puppeteer due to the obstacle by cloudflare challenge
const html = await puppeteerGet(link, ctx.cache);
const $ = cheerio.load(html);
ctx.state.data = {
title: $('.Heading_h1___Cf5Y').text().trim(),
description: $('.intro-text').text().trim(),
link,
item: $('.AppListItem_appInfo__h9cWP')
.toArray()
.map((element) => {
const item = $(element);
const title = item.find('.Heading_h2___LwQD').text().trim();
const link = `${baseURL}${item.find('.Heading_h2___LwQD a').attr('href')}`;
const description = item.find('.AppListItem_description__wtODK').text().trim();
return {
title,
link,
description,
};
}),
};
};

View File

@ -0,0 +1,19 @@
module.exports = {
'alternativeto.net': {
_name: 'AlternativeTo',
www: [
{
title: 'Software Alternatives',
docs: 'https://docs.rsshub.app/routes/programming#alternativeto-software-alternatives',
source: '/software/:name',
target: '/software/:name',
},
{
title: 'Platform Software',
docs: 'https://docs.rsshub.app/routes/programming#alternativeto-platform-software',
source: '/platform/:name',
target: '/platform/:name',
},
],
},
};

View File

@ -0,0 +1,4 @@
module.exports = (router) => {
router.get('/software/:name/:routeParams?', require('./software'));
router.get('/platform/:name/:routeParams?', require('./platform'));
};

View File

@ -0,0 +1,32 @@
const { baseURL, puppeteerGet } = require('./utils');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const name = ctx.params.name;
const query = new URLSearchParams(ctx.params.routeParams);
const link = `https://alternativeto.net/software/${name}/?${query.toString()}`;
// use Puppeteer due to the obstacle by cloudflare challenge
const html = await puppeteerGet(link, ctx.cache);
const $ = cheerio.load(html);
ctx.state.data = {
title: $('.Heading_h1___Cf5Y').text().trim(),
description: $('.intro-text').text().trim(),
link,
item: $('.AppListItem_appInfo__h9cWP')
.toArray()
.map((element) => {
const item = $(element);
const title = item.find('.Heading_h2___LwQD').text().trim();
const link = `${baseURL}${item.find('.Heading_h2___LwQD a').attr('href')}`;
const description = item.find('.AppListItem_description__wtODK').text().trim();
return {
title,
link,
description,
};
}),
};
};

View File

@ -0,0 +1,22 @@
const baseURL = 'https://alternativeto.net';
const puppeteerGet = (url, cache) =>
cache.tryGet(url, async () => {
const browser = await require('@/utils/puppeteer')();
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', (request) => {
request.resourceType() === 'document' ? request.continue() : request.abort();
});
await page.goto(url, {
waitUntil: 'domcontentloaded',
});
const html = await page.evaluate(() => document.documentElement.innerHTML);
browser.close();
return html;
});
module.exports = {
baseURL,
puppeteerGet,
};

View File

@ -82,6 +82,24 @@ You have the option to utilize the main heading or use individual categories as
</Route>
## AlternativeTo {#alternativeto}
### Software Alternatives {#alternativeto-software-alternatives}
<Route author="JimenezLi" example="/alternativeto/software/cpp" path="/alternativeto/software/:name/:routeParams?" paramsDesc={['Software name', 'Filters of software type']} puppeteer="1" radar="1">
> routeParms can be copied from original site URL, example: `/alternativeto/software/cpp/license=opensource&platform=windows`
</Route>
### Platform Software {#alternativeto-platform-software}
<Route author="JimenezLi" example="/alternativeto/platform/firefox" path="/alternativeto/platform/:name/:routeParams?" paramsDesc={['Platform name', 'Filters of software type']} puppeteer="1" radar="1">
> routeParms can be copied from original site URL, example: `/alternativeto/platform/firefox/license=free`
</Route>
## AtCoder {#atcoder}
### Present Contests {#atcoder-present-contests}