Files
RSSHub/lib/v2/leetcode/dailyquestion-solution-en.js
Albert Cai 0896c39c31 fix: leetcode.com题解展示 (#10515)
* fix: leetcode.com题解展示

* fix: dynamic uuid

* fix: spacing
2022-08-18 10:31:16 +11:00

214 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const got = require('@/utils/got');
const showdown = require('showdown');
const { parseDate } = require('@/utils/parse-date');
const timezone = require('@/utils/timezone');
const path = require('path');
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;
if (article.content === null) {
article.content = 'Sorry, the solution of this question may be locked.';
}
const converter = new showdown.Converter();
// 图片处理
const parsePngSlide = async (s) => {
const pattern = /!\?!(.+)!\?!/;
if (!pattern.test(s)) {
return s;
}
const matched = s.match(new RegExp(pattern, 'g'));
const fn = async (m) => {
const relaurl = m.match(pattern)[1].split(':')[0];
const fullurl = path.resolve('/' + questionUrl + 'solution/', relaurl).slice(1);
const pngList = (
await got({
url: fullurl,
method: 'get',
headers,
})
).data.timeline;
return pngList.map((v) => `![pic](${path.resolve(`/problems/${questionTitle}/solution/`, v.image)})`).join('\n');
};
const strs = await Promise.all(matched.map((v) => fn(v)));
for (let i = 0; i < matched.length; i++) {
s = s.replace(matched[i], strs[i]);
}
return s;
};
// iframe代码框处理
const parseIframe = async (s) => {
const pattern = new RegExp('<iframe.*? src=".*?playground/(.*?)/shared".*</iframe>');
if (!pattern.test(s)) {
return s;
}
const matched = s.match(new RegExp(pattern, 'g'));
const fn = async (m) => {
const uuid = m.match(pattern)[1];
const code = (
await got({
method: 'post',
url,
json: {
operationName: 'fetchPlayground',
query: `query fetchPlayground {
playground(uuid: "${uuid}") {
testcaseInput
name
isUserOwner
isLive
showRunCode
showOpenInPlayground
selectedLangSlug
isShared
__typename
}
allPlaygroundCodes(uuid: "${uuid}") {
code
langSlug
__typename
}
}`,
variables: {},
},
headers,
})
).data.data.allPlaygroundCodes;
return code.map((c) => `###${c.langSlug}\n\r \`\`\`${c.langSlug}\n ${c.code}\n\`\`\``).join('\n\r');
};
const strs = await Promise.all(matched.map((v) => fn(v)));
for (let i = 0; i < matched.length; i++) {
s = s.replace(matched[i], strs[i]);
}
return s;
};
const handleText = async (s) => {
// 处理代码iframe嵌入问题
s = await parseIframe(s);
// 处理图片展示问题
s = await parsePngSlide(s);
return s;
};
article.content = await handleText(article.content);
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(article.content),
pubDate: timezone(parseDate(data.activeDailyCodingChallengeQuestion.date), +8),
author: 'leetcode',
},
],
};
};