mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-28 03:28:35 +08:00
feat(route): 增加leetcode每日一题题解 (#10499)
* feat(route): 增加leetcode每日一题题解 * fix: leetcode每日一题题解 * fix: leetcode每日一题题解
This commit is contained in:
@@ -309,6 +309,10 @@ Subscribe to the updates (threads and submission) from a paritcular Hacker News
|
||||
|
||||
<RouteEn author="NavePnow" example="/leetcode/dailyquestion/en" path="/leetcode/dailyquestion/:lang" :paramsDesc="['site, Chines(cn) and Engligh(en)']"/>
|
||||
|
||||
### Daily Question Solution
|
||||
|
||||
<RouteEn author="woaidouya123" example="/leetcode/dailyquestion/solution/en" path="/leetcode/dailyquestion/solution/:lang" :paramsDesc="['site, Chines(cn) and Engligh(en)']"/>
|
||||
|
||||
## Linux Patchwork
|
||||
|
||||
### Patch Comments
|
||||
|
||||
@@ -459,6 +459,10 @@ GitHub 官方也提供了一些 RSS:
|
||||
|
||||
<Route author="NavePnow" example="/leetcode/dailyquestion/en" path="/leetcode/dailyquestion/:lang" :paramsDesc="['站点,中文(cn)和英文(en)']"/>
|
||||
|
||||
### 每日一题题解
|
||||
|
||||
<Route author="woaidouya123" example="/leetcode/dailyquestion/solution/cn" path="/leetcode/dailyquestion/solution/:lang" :paramsDesc="['站点,中文(cn)和英文(en)']"/>
|
||||
|
||||
## LinkedKeeper
|
||||
|
||||
### 博文
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
const got = require('@/utils/got');
|
||||
const showdown = require('showdown');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
module.exports = async (ctx) => {
|
||||
const baseurl = `https://leetcode.cn`;
|
||||
const url = `${baseurl}/graphql/`;
|
||||
const headers = {
|
||||
'content-type': 'application/json',
|
||||
};
|
||||
const emoji = {
|
||||
Medium: '🟡',
|
||||
Easy: '🟢',
|
||||
Hard: '🔴',
|
||||
};
|
||||
// 获取每日一题
|
||||
const data = (
|
||||
await got({
|
||||
method: 'post',
|
||||
url,
|
||||
json: {
|
||||
operationName: 'questionOfToday',
|
||||
query: `query questionOfToday {
|
||||
todayRecord {
|
||||
date
|
||||
userStatus
|
||||
question {
|
||||
questionId
|
||||
frontendQuestionId: questionFrontendId
|
||||
difficulty
|
||||
title
|
||||
titleCn: translatedTitle
|
||||
titleSlug
|
||||
}
|
||||
}
|
||||
}`,
|
||||
variables: {},
|
||||
},
|
||||
headers,
|
||||
})
|
||||
).data.data;
|
||||
const questionTitle = data.todayRecord[0].question.titleSlug;
|
||||
const questionUrl = `${baseurl}/problems/${questionTitle}/`;
|
||||
|
||||
// 获取题目内容
|
||||
const question = (
|
||||
await got({
|
||||
method: 'post',
|
||||
url,
|
||||
json: {
|
||||
operationName: 'questionData',
|
||||
query: `query questionData($titleSlug: String!) {
|
||||
question(titleSlug: $titleSlug) {
|
||||
questionId
|
||||
questionFrontendId
|
||||
categoryTitle
|
||||
boundTopicId
|
||||
title
|
||||
titleSlug
|
||||
content
|
||||
translatedTitle
|
||||
translatedContent
|
||||
isPaidOnly
|
||||
difficulty
|
||||
likes
|
||||
}
|
||||
}`,
|
||||
variables: {
|
||||
titleSlug: questionTitle,
|
||||
},
|
||||
},
|
||||
headers,
|
||||
})
|
||||
).data.data.question;
|
||||
const diffEmoji = emoji[question.difficulty] || '';
|
||||
// 获取题解(点赞前3)
|
||||
const articles = (
|
||||
await got({
|
||||
method: 'post',
|
||||
url,
|
||||
json: {
|
||||
operationName: 'questionSolutionArticles',
|
||||
query: `query questionSolutionArticles($questionSlug: String!, $skip: Int, $first: Int, $orderBy: SolutionArticleOrderBy, $userInput: String, $tagSlugs: [String!]) {
|
||||
questionSolutionArticles(questionSlug: $questionSlug, skip: $skip, first: $first, orderBy: $orderBy, userInput: $userInput, tagSlugs: $tagSlugs) {
|
||||
totalNum
|
||||
edges {
|
||||
node {
|
||||
...solutionArticle
|
||||
__typename
|
||||
}
|
||||
__typename
|
||||
}
|
||||
__typename
|
||||
}
|
||||
}
|
||||
fragment solutionArticle on SolutionArticleNode {
|
||||
uuid
|
||||
title
|
||||
slug
|
||||
createdAt
|
||||
thumbnail
|
||||
author {
|
||||
username
|
||||
}
|
||||
summary
|
||||
}`,
|
||||
variables: {
|
||||
questionSlug: questionTitle,
|
||||
first: 3,
|
||||
skip: 0,
|
||||
orderBy: 'MOST_UPVOTE',
|
||||
},
|
||||
},
|
||||
headers,
|
||||
})
|
||||
).data.data.questionSolutionArticles.edges;
|
||||
// 获取题解内容
|
||||
const articleContent = (
|
||||
await Promise.all(
|
||||
articles.map((art) =>
|
||||
got({
|
||||
method: 'post',
|
||||
url,
|
||||
json: {
|
||||
operationName: 'solutionDetailArticle',
|
||||
query: `query solutionDetailArticle($slug: String!, $orderBy: SolutionArticleOrderBy!) {
|
||||
solutionArticle(slug: $slug, orderBy: $orderBy) {
|
||||
...solutionArticle
|
||||
content
|
||||
question {
|
||||
questionTitleSlug
|
||||
__typename
|
||||
}
|
||||
}
|
||||
}
|
||||
fragment solutionArticle on SolutionArticleNode {
|
||||
uuid
|
||||
title
|
||||
slug
|
||||
createdAt
|
||||
thumbnail
|
||||
author {
|
||||
username
|
||||
}
|
||||
summary
|
||||
}`,
|
||||
variables: {
|
||||
slug: art.node.slug,
|
||||
orderBy: 'DEFAULT',
|
||||
},
|
||||
},
|
||||
headers,
|
||||
})
|
||||
)
|
||||
)
|
||||
).map((v) => v.data.data.solutionArticle);
|
||||
const converter = new showdown.Converter();
|
||||
const handleText = (s) => {
|
||||
// 处理多语言代码展示问题
|
||||
s = s.replace(/(```)([a-zA-Z0-9-+#]+)\s*?(\[.*?\])?\n/g, '\r\n###$2\r\n$1$2\r\n');
|
||||
return s;
|
||||
};
|
||||
ctx.state.data = {
|
||||
title: 'LeetCode 每日一题题解',
|
||||
description: 'LeetCode 每日一题题解',
|
||||
link: questionUrl,
|
||||
item: [
|
||||
{
|
||||
title: `每日一题-${question.translatedTitle}${diffEmoji}`,
|
||||
link: questionUrl,
|
||||
description: question.translatedContent,
|
||||
pubDate: timezone(parseDate(data.todayRecord[0].date), +8),
|
||||
},
|
||||
...articleContent.map((art, i) => ({
|
||||
title: art.title,
|
||||
link: `${questionUrl}/solution/${art.slug}`,
|
||||
description: converter.makeHtml(handleText(art.content)),
|
||||
pubDate: timezone(parseDate(articles[i].node.createdAt), +8),
|
||||
author: art.author.username,
|
||||
})),
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,135 @@
|
||||
const got = require('@/utils/got');
|
||||
const showdown = require('showdown');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
module.exports = async (ctx) => {
|
||||
const baseurl = `https://leetcode.com`;
|
||||
const url = `${baseurl}/graphql/`;
|
||||
const headers = {
|
||||
'content-type': 'application/json',
|
||||
};
|
||||
const emoji = {
|
||||
Medium: '🟡',
|
||||
Easy: '🟢',
|
||||
Hard: '🔴',
|
||||
};
|
||||
// 获取每日一题
|
||||
const data = (
|
||||
await got({
|
||||
method: 'post',
|
||||
url,
|
||||
json: {
|
||||
operationName: 'questionOfToday',
|
||||
query: `query questionOfToday {
|
||||
activeDailyCodingChallengeQuestion {
|
||||
date
|
||||
link
|
||||
question {
|
||||
frontendQuestionId: questionFrontendId
|
||||
titleSlug
|
||||
}
|
||||
}
|
||||
}`,
|
||||
variables: {},
|
||||
},
|
||||
headers,
|
||||
})
|
||||
).data.data;
|
||||
const questionTitle = data.activeDailyCodingChallengeQuestion.question.titleSlug;
|
||||
const questionUrl = `${baseurl}/problems/${questionTitle}/`;
|
||||
|
||||
// 获取题目内容
|
||||
const question = (
|
||||
await got({
|
||||
method: 'post',
|
||||
url,
|
||||
json: {
|
||||
operationName: 'questionData',
|
||||
query: `query questionData($titleSlug: String!) {
|
||||
question(titleSlug: $titleSlug) {
|
||||
questionId
|
||||
questionFrontendId
|
||||
categoryTitle
|
||||
boundTopicId
|
||||
title
|
||||
titleSlug
|
||||
content
|
||||
translatedTitle
|
||||
translatedContent
|
||||
isPaidOnly
|
||||
difficulty
|
||||
likes
|
||||
}
|
||||
}`,
|
||||
variables: {
|
||||
titleSlug: questionTitle,
|
||||
},
|
||||
},
|
||||
headers,
|
||||
})
|
||||
).data.data.question;
|
||||
const diffEmoji = emoji[question.difficulty] || '';
|
||||
// 获取题解(en网站仅一个题解)
|
||||
const article = (
|
||||
await got({
|
||||
method: 'post',
|
||||
url,
|
||||
json: {
|
||||
operationName: 'QuestionNote',
|
||||
query: `query QuestionNote($titleSlug: String!) {
|
||||
question(titleSlug: $titleSlug) {
|
||||
questionId
|
||||
article
|
||||
solution {
|
||||
id
|
||||
content
|
||||
contentTypeId
|
||||
canSeeDetail
|
||||
paidOnly
|
||||
hasVideoSolution
|
||||
paidOnlyVideo
|
||||
rating {
|
||||
id
|
||||
count
|
||||
average
|
||||
userRating {
|
||||
score
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
variables: {
|
||||
titleSlug: questionTitle,
|
||||
},
|
||||
},
|
||||
headers,
|
||||
})
|
||||
).data.data.question.solution;
|
||||
const converter = new showdown.Converter();
|
||||
const handleText = (s) => {
|
||||
// 处理多语言代码展示问题
|
||||
s = s.replace(/(```)([a-zA-Z0-9-+#]+)\s*?(\[.*?\])?\n/g, '\r\n###$2\r\n$1$2\r\n');
|
||||
return s;
|
||||
};
|
||||
ctx.state.data = {
|
||||
title: 'LeetCode DailyQuestion Solution',
|
||||
description: 'LeetCode DailyQuestion Solution',
|
||||
link: questionUrl,
|
||||
item: [
|
||||
{
|
||||
title: `DailyQuestion-${question.title}${diffEmoji}`,
|
||||
link: questionUrl,
|
||||
description: question.content,
|
||||
pubDate: timezone(parseDate(data.activeDailyCodingChallengeQuestion.date), +8),
|
||||
},
|
||||
{
|
||||
title: `Solution-${question.title}`,
|
||||
link: `${questionUrl}solution/`,
|
||||
description: converter.makeHtml(handleText(article.content)),
|
||||
pubDate: timezone(parseDate(data.activeDailyCodingChallengeQuestion.date), +8),
|
||||
author: 'leetcode',
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
module.exports = {
|
||||
'/articles': ['LogicJake'],
|
||||
'/dailyquestion/:lang': ['NavePnow'],
|
||||
'/dailyquestion/solution/:lang': ['woaidouya123'],
|
||||
'/submission/:country/:user': ['NathanDai'],
|
||||
};
|
||||
|
||||
@@ -24,6 +24,12 @@ module.exports = {
|
||||
source: ['/'],
|
||||
target: '/leetcode/dailyquestion/en',
|
||||
},
|
||||
{
|
||||
title: '每日一题题解',
|
||||
docs: 'https://docs.rsshub.app/programming.html#leetcode',
|
||||
source: ['/'],
|
||||
target: '/leetcode/dailyquestion/solution/en',
|
||||
},
|
||||
],
|
||||
},
|
||||
'leetcode.cn': {
|
||||
@@ -45,6 +51,12 @@ module.exports = {
|
||||
source: ['/'],
|
||||
target: '/leetcode/dailyquestion/cn',
|
||||
},
|
||||
{
|
||||
title: '每日一题题解',
|
||||
docs: 'https://docs.rsshub.app/programming.html#leetcode',
|
||||
source: ['/'],
|
||||
target: '/leetcode/dailyquestion/solution/cn',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,4 +2,6 @@ module.exports = function (router) {
|
||||
router.get('/articles', require('./articles'));
|
||||
router.get('/dailyquestion/cn', require('./dailyquestion-cn'));
|
||||
router.get('/dailyquestion/en', require('./dailyquestion-en'));
|
||||
router.get('/dailyquestion/solution/cn', require('./dailyquestion-solution-cn'));
|
||||
router.get('/dailyquestion/solution/en', require('./dailyquestion-solution-en'));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user