mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-04 19:59:54 +08:00
feat(radar): leetcode radar
This commit is contained in:
@@ -1308,7 +1308,7 @@ router.get('/aisixiang/thinktank/:name/:type?', lazyloadRouteHandler('./routes/a
|
|||||||
// router.get('/hackernews/:section/:type?', lazyloadRouteHandler('./routes/hackernews/story'));
|
// router.get('/hackernews/:section/:type?', lazyloadRouteHandler('./routes/hackernews/story'));
|
||||||
|
|
||||||
// LeetCode
|
// LeetCode
|
||||||
router.get('/leetcode/articles', lazyloadRouteHandler('./routes/leetcode/articles'));
|
// router.get('/leetcode/articles', lazyloadRouteHandler('./routes/leetcode/articles'));
|
||||||
router.get('/leetcode/submission/us/:user', lazyloadRouteHandler('./routes/leetcode/check-us'));
|
router.get('/leetcode/submission/us/:user', lazyloadRouteHandler('./routes/leetcode/check-us'));
|
||||||
router.get('/leetcode/submission/cn/:user', lazyloadRouteHandler('./routes/leetcode/check-cn'));
|
router.get('/leetcode/submission/cn/:user', lazyloadRouteHandler('./routes/leetcode/check-cn'));
|
||||||
|
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
const got = require('@/utils/got');
|
|
||||||
const cheerio = require('cheerio');
|
|
||||||
const url = require('url');
|
|
||||||
const showdown = require('showdown');
|
|
||||||
|
|
||||||
const host = 'https://leetcode.com';
|
|
||||||
|
|
||||||
module.exports = async (ctx) => {
|
|
||||||
const link = url.resolve(host, '/articles');
|
|
||||||
const response = await got.get(link);
|
|
||||||
const $ = cheerio.load(response.data);
|
|
||||||
|
|
||||||
const list = $('a.list-group-item')
|
|
||||||
.slice(0, 10)
|
|
||||||
.filter((i, e) => $(e).find('h4.media-heading i').length === 0)
|
|
||||||
.map(function () {
|
|
||||||
const info = {
|
|
||||||
title: $(this).find('h4.media-heading').text().trim(),
|
|
||||||
author: $(this).find('.text-500').text(),
|
|
||||||
link: $(this).attr('href'),
|
|
||||||
date: $(this).find('p.pull-right.media-date strong').text().trim(),
|
|
||||||
};
|
|
||||||
return info;
|
|
||||||
})
|
|
||||||
.get();
|
|
||||||
|
|
||||||
const out = await Promise.all(
|
|
||||||
list.map(async (info) => {
|
|
||||||
const itemUrl = url.resolve(host, info.link);
|
|
||||||
const titelSlug = info.link.split('/')[2];
|
|
||||||
|
|
||||||
const cache = await ctx.cache.get(itemUrl);
|
|
||||||
if (cache) {
|
|
||||||
return Promise.resolve(JSON.parse(cache));
|
|
||||||
}
|
|
||||||
|
|
||||||
const questionData = await got
|
|
||||||
.post(url.resolve(host, '/graphql'), {
|
|
||||||
json: { operationName: 'questionData', variables: { titleSlug: titelSlug }, query: 'query questionData($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n content\n }\n}\n' },
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
|
|
||||||
const questionNote = await got
|
|
||||||
.post(url.resolve(host, '/graphql'), {
|
|
||||||
json: {
|
|
||||||
operationName: 'QuestionNote',
|
|
||||||
variables: { titleSlug: titelSlug },
|
|
||||||
query: 'query QuestionNote($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n solution {\n content\n }\n }\n}\n',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
|
|
||||||
const converter = new showdown.Converter();
|
|
||||||
const solution = converter.makeHtml(questionNote.data.question.solution.content);
|
|
||||||
|
|
||||||
const description = questionData.data.question.content.trim() + solution;
|
|
||||||
|
|
||||||
const single = {
|
|
||||||
title: info.title,
|
|
||||||
author: info.author,
|
|
||||||
link: itemUrl,
|
|
||||||
description,
|
|
||||||
pubDate: new Date(info.date).toUTCString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
|
||||||
return Promise.resolve(single);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.state.data = {
|
|
||||||
title: 'LeetCode Articles',
|
|
||||||
description: 'LeetCode Articles, the only official solutions you will find.',
|
|
||||||
link,
|
|
||||||
item: out,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
80
lib/v2/leetcode/articles.js
Normal file
80
lib/v2/leetcode/articles.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
const got = require('@/utils/got');
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
const { parseDate } = require('@/utils/parse-date');
|
||||||
|
const showdown = require('showdown');
|
||||||
|
|
||||||
|
const host = 'https://leetcode.com';
|
||||||
|
const gqlEndpoint = `${host}/graphql`;
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const link = new URL('/articles/', host).href;
|
||||||
|
const response = await got(link);
|
||||||
|
const $ = cheerio.load(response.data);
|
||||||
|
|
||||||
|
const list = $('a.list-group-item')
|
||||||
|
.filter((i, e) => $(e).find('h4.media-heading i').length === 0)
|
||||||
|
.map(function () {
|
||||||
|
const info = {
|
||||||
|
title: $(this).find('h4.media-heading').text().trim(),
|
||||||
|
author: $(this).find('.text-500').text(),
|
||||||
|
link: new URL($(this).attr('href'), host).href,
|
||||||
|
pubDate: $(this).find('p.pull-right.media-date strong').text().trim(),
|
||||||
|
};
|
||||||
|
return info;
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
const out = await Promise.all(
|
||||||
|
list.map((info) =>
|
||||||
|
ctx.cache.tryGet(info.link, async () => {
|
||||||
|
const titleSlug = info.link.split('/')[4];
|
||||||
|
|
||||||
|
const questionData = await got
|
||||||
|
.post(gqlEndpoint, {
|
||||||
|
json: {
|
||||||
|
operationName: 'questionData',
|
||||||
|
variables: { titleSlug },
|
||||||
|
query: `query questionData($titleSlug: String!) {
|
||||||
|
question(titleSlug: $titleSlug) {
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.json();
|
||||||
|
|
||||||
|
const questionNote = await got
|
||||||
|
.post(gqlEndpoint, {
|
||||||
|
json: {
|
||||||
|
operationName: 'QuestionNote',
|
||||||
|
variables: { titleSlug },
|
||||||
|
query: `query QuestionNote($titleSlug: String!) {
|
||||||
|
question(titleSlug: $titleSlug) {
|
||||||
|
solution {
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.json();
|
||||||
|
|
||||||
|
const converter = new showdown.Converter();
|
||||||
|
const solution = converter.makeHtml(questionNote.data.question.solution.content);
|
||||||
|
|
||||||
|
info.description = questionData.data.question.content.trim() + solution;
|
||||||
|
info.pubDate = parseDate(info.pubDate);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: $('head title').text(),
|
||||||
|
description: $('meta[property="og:description"]').attr('content'),
|
||||||
|
image: 'https://assets.leetcode.com/static_assets/public/icons/favicon-192x192.png',
|
||||||
|
link,
|
||||||
|
item: out,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
'/dailyquestion/en': ['NavePnow'],
|
'/articles': ['LogicJake'],
|
||||||
'/dailyquestion/cn': ['NavePnow'],
|
'/dailyquestion/:lang': ['NavePnow'],
|
||||||
|
'/submission/:country/:user': ['NathanDai'],
|
||||||
};
|
};
|
||||||
|
|||||||
50
lib/v2/leetcode/radar.js
Normal file
50
lib/v2/leetcode/radar.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
module.exports = {
|
||||||
|
'leetcode.com': {
|
||||||
|
_name: 'LeetCode',
|
||||||
|
'.': [
|
||||||
|
{
|
||||||
|
title: '文章',
|
||||||
|
docs: 'https://docs.rsshub.app/programming.html#leetcode',
|
||||||
|
source: ['/articles'],
|
||||||
|
target: '/leetcode/articles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '打卡',
|
||||||
|
docs: 'https://docs.rsshub.app/programming.html#leetcode',
|
||||||
|
source: ['/:user'],
|
||||||
|
target: (params) => {
|
||||||
|
if (params.user !== 'articles') {
|
||||||
|
return `/leetcode/submission/us/:user`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '每日一题',
|
||||||
|
docs: 'https://docs.rsshub.app/programming.html#leetcode',
|
||||||
|
source: ['/'],
|
||||||
|
target: '/leetcode/dailyquestion/en',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'leetcode.cn': {
|
||||||
|
_name: 'LeetCode',
|
||||||
|
'.': [
|
||||||
|
{
|
||||||
|
title: '打卡',
|
||||||
|
docs: 'https://docs.rsshub.app/programming.html#leetcode',
|
||||||
|
source: ['/:user'],
|
||||||
|
target: (params) => {
|
||||||
|
if (params.user !== 'articles') {
|
||||||
|
return `/leetcode/submission/cn/:user`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '每日一题',
|
||||||
|
docs: 'https://docs.rsshub.app/programming.html#leetcode',
|
||||||
|
source: ['/'],
|
||||||
|
target: '/leetcode/dailyquestion/cn',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
module.exports = function (router) {
|
module.exports = function (router) {
|
||||||
router.get('/dailyquestion/en', require('./dailyquestion-en'));
|
router.get('/articles', require('./articles'));
|
||||||
router.get('/dailyquestion/cn', require('./dailyquestion-cn'));
|
router.get('/dailyquestion/cn', require('./dailyquestion-cn'));
|
||||||
|
router.get('/dailyquestion/en', require('./dailyquestion-en'));
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user