From 6f5023c788427c3ddbd80e8bf949f79b995b0167 Mon Sep 17 00:00:00 2001 From: ccagml Date: Wed, 8 Mar 2023 18:01:39 +0800 Subject: [PATCH 1/6] update --- package-lock.json | 84 ++++++- package.json | 1 + src/rpc/actionChain/chainNode/leetcode.cn.ts | 153 ++--------- src/rpc/actionChain/chainNode/leetcode.ts | 252 ++++++------------- src/rpc/actionChain/chainNode/retry.ts | 4 - src/rpc/actionChain/chainNodeBase.ts | 13 +- src/rpc/utils/graphqlUtils.ts | 248 ++++++++++++++++++ 7 files changed, 429 insertions(+), 326 deletions(-) create mode 100644 src/rpc/utils/graphqlUtils.ts diff --git a/package-lock.json b/package-lock.json index 7147e8b..15834fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { "name": "vscode-leetcode-problem-rating", - "version": "2.14.2", + "version": "2.18.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-leetcode-problem-rating", - "version": "2.14.2", + "version": "2.18.1", "license": "MIT", "dependencies": { "ansi-styles": "3.2.1", + "axios": "^1.3.4", "cheerio": "1.0.0-rc.12", "fs-extra": "^10.0.0", "he": "1.2.0", @@ -580,6 +581,29 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, + "node_modules/axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1395,6 +1419,25 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2297,6 +2340,11 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -3478,6 +3526,28 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, + "axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -4095,6 +4165,11 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -4773,6 +4848,11 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index fd17b0d..678d885 100644 --- a/package.json +++ b/package.json @@ -1165,6 +1165,7 @@ }, "dependencies": { "ansi-styles": "3.2.1", + "axios": "^1.3.4", "cheerio": "1.0.0-rc.12", "fs-extra": "^10.0.0", "he": "1.2.0", diff --git a/src/rpc/actionChain/chainNode/leetcode.cn.ts b/src/rpc/actionChain/chainNode/leetcode.cn.ts index 8ae05e3..7991768 100644 --- a/src/rpc/actionChain/chainNode/leetcode.cn.ts +++ b/src/rpc/actionChain/chainNode/leetcode.cn.ts @@ -15,6 +15,16 @@ import { configUtils } from "../../utils/configUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { reply } from "../../utils/ReplyUtils"; +import { + getProblemsTitleCNBody, + getQuestionOfTodayCNBody, + getSolutionArticlesSlugListCNBody, + getSolutionBySlugCNBody, + getUserContestPCNBody, +} from "../../utils/graphqlUtils"; + +// import axios from "axios"; + class LeetCodeCn extends ChainNodeBase { id = 15; name = "leetcode.cn"; @@ -56,19 +66,7 @@ class LeetCodeCn extends ChainNodeBase { opts.headers.Referer = "https://leetcode.cn/api/problems/algorithms/"; opts.json = true; - opts.body = { - query: [ - "query getQuestionTranslation($lang: String) {", - " translations: allAppliedQuestionTranslations(lang: $lang) {", - " title", - " questionId", - " __typename", - " }", - "}", - ].join("\n"), - variables: {}, - operationName: "getQuestionTranslation", - }; + opts.body = getProblemsTitleCNBody(); request.post(opts, function (e, resp, body) { e = checkError(e, resp, 200); @@ -90,35 +88,7 @@ class LeetCodeCn extends ChainNodeBase { opts.headers.Referer = "https://leetcode.cn/"; opts.json = true; - opts.body = { - operationName: "questionOfToday", - variables: {}, - query: [ - "query questionOfToday {", - " todayRecord {", - " date", - " userStatus", - " question {", - " titleSlug", - " questionId", - " questionFrontendId", - // ' content', - // ' stats', - // ' likes', - // ' dislikes', - // ' codeDefinition', - // ' sampleTestCase', - // ' enableRunCode', - // ' metaData', - // ' translatedContent', - " __typename", - " }", - " __typename", - " }", - "}", - ].join("\n"), - }; - + opts.body = getQuestionOfTodayCNBody(); request.post(opts, function (e, resp, body) { e = checkError(e, resp, 200); if (e) return cb(e); @@ -138,39 +108,7 @@ class LeetCodeCn extends ChainNodeBase { opts.headers.Referer = configUtils.sys.urls.u.replace("$username", username); opts.json = true; - opts.body = { - variables: { - userSlug: username, - }, - query: [ - " query userContestRankingInfo($userSlug: String!) {", - " userContestRanking(userSlug: $userSlug) {", - " attendedContestsCount", - " rating", - " globalRanking", - " localRanking", - " globalTotalParticipants", - " localTotalParticipants", - " topPercentage", - " }", - // ' userContestRankingHistory(userSlug: $userSlug) {', - // ' attended', - // ' totalProblems', - // ' trendingDirection', - // ' finishTimeInSeconds', - // ' rating', - // ' score', - // ' ranking', - // ' contest {', - // ' title', - // ' titleCn', - // ' startTime', - // ' }', - // ' }', - " }", - ].join("\n"), - }; - + opts.body = getUserContestPCNBody(username); request.post(opts, function (e, resp, body) { e = checkError(e, resp, 200); if (e) return cb(e); @@ -183,8 +121,6 @@ class LeetCodeCn extends ChainNodeBase { getRatingOnline = (cb) => { const _request = request.defaults({ timeout: 2000, jar: true }); _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error: any, _, body: any) { - // console.log(error); - // console.log(info); cb(error, body); }); }; @@ -221,39 +157,7 @@ function getSolutionBySlug(question_slug: string, articles_slug: string, lang: s opts.headers.Referer = URL_DISCUSS.replace("$slug", question_slug).replace("$articles_slug", articles_slug); opts.json = true; - opts.body = { - operationName: "solutionDetailArticle", - variables: { slug: articles_slug, orderBy: "DEFAULT" }, - query: [ - "query solutionDetailArticle($slug: String!, $orderBy: SolutionArticleOrderBy!) {", - " solutionArticle(slug: $slug, orderBy: $orderBy) {", - " ...solutionArticle", - " content", - " question {", - " questionTitleSlug", - " __typename", - " }", - " __typename", - "}", - "}", - "fragment solutionArticle on SolutionArticleNode {", - " uuid", - " title", - " slug", - " identifier", - "author {", - " username", - " profile {", - " realName", - " __typename", - " }", - " __typename", - "}", - "byLeetcode", - "__typename", - "}", - ].join("\n"), - }; + opts.body = getSolutionBySlugCNBody(articles_slug); request.post(opts, function (_, __, body) { // let bbb = body; @@ -265,9 +169,6 @@ function getSolutionBySlug(question_slug: string, articles_slug: string, lang: s // let content = solution.content.replace(/\\n/g, "\n").replace(/\\t/g, "\t"); let content = solution.content.replace(/\\n/g, "\n"); - // content = content.replace(/\$\\textit/g, "$"); - // content = content.replace(/\$\\texttt/g, "$"); - // content = content.replace(/\$\\text/g, "$"); content = content.replace(/\\textit{/g, "{"); content = content.replace(/\\texttt{/g, "{"); content = content.replace(/\\text{/g, "{"); @@ -293,31 +194,7 @@ function getSolutionArticlesSlugList(question_slug: string, lang: string, cb) { opts.headers.Referer = URL_DISCUSS.replace("$slug", question_slug); opts.json = true; - opts.body = { - operationName: "questionSolutionArticles", - variables: { questionSlug: question_slug, first: 1, skip: 0, orderBy: "DEFAULT", tagSlugs: [lang] }, - 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", - " slug", - " byLeetcode", - " __typename", - "}", - ].join("\n"), - }; + opts.body = getSolutionArticlesSlugListCNBody(question_slug, lang); request.post(opts, function (e, _, body) { let edges = body?.data?.questionSolutionArticles?.edges || []; diff --git a/src/rpc/actionChain/chainNode/leetcode.ts b/src/rpc/actionChain/chainNode/leetcode.ts index 908da31..fd1626e 100644 --- a/src/rpc/actionChain/chainNode/leetcode.ts +++ b/src/rpc/actionChain/chainNode/leetcode.ts @@ -20,6 +20,13 @@ import { reply } from "../../utils/ReplyUtils"; import { sessionUtils } from "../../utils/sessionUtils"; import { ChainNodeBase } from "../chainNodeBase"; import { Queue } from "../../utils/queueUtils"; +import { + getAddQuestionToFavoriteBody, + getGetHelpEnBody, + getQuestionDetailBody, + getRemoveQuestionFromFavoriteBody, + getUserInfoBody, +} from "../../utils/graphqlUtils"; class LeetCode extends ChainNodeBase { id = 10; @@ -100,26 +107,7 @@ server to get the problem's description, test cases, and other information. */ opts.headers.Referer = problem.link; opts.json = true; - opts.body = { - query: [ - "query getQuestionDetail($titleSlug: String!) {", - " question(titleSlug: $titleSlug) {", - " content", - " stats", - " likes", - " dislikes", - " codeDefinition", - " sampleTestCase", - " enableRunCode", - " metaData", - " translatedContent", - " }", - "}", - ].join("\n"), - variables: { titleSlug: problem.slug }, - operationName: "getQuestionDetail", - }; - + opts.body = getQuestionDetailBody(problem.slug); request.post(opts, function (e, resp, body) { e = checkError(e, resp, 200); if (e) return cb(e); @@ -138,8 +126,6 @@ server to get the problem's description, test cases, and other information. */ problem.testcase = q.sampleTestCase; problem.testable = q.enableRunCode; problem.templateMeta = JSON.parse(q.metaData); - // @si-yao: seems below property is never used. - // problem.discuss = q.discussCategoryId; return cb(null, problem); }); @@ -325,17 +311,13 @@ server to get the problem's description, test cases, and other information. */ /* A function that is used to star a problem. */ starProblem = (problem, starred, cb) => { const user = sessionUtils.getUser(); - const operationName = starred ? "addQuestionToFavorite" : "removeQuestionFromFavorite"; const opts = makeOpts(configUtils.sys.urls.graphql); opts.headers.Origin = configUtils.sys.urls.base; opts.headers.Referer = problem.link; - opts.json = true; - opts.body = { - query: `mutation ${operationName}($favoriteIdHash: String!, $questionId: String!) {\n ${operationName}(favoriteIdHash: $favoriteIdHash, questionId: $questionId) {\n ok\n error\n favoriteIdHash\n questionId\n __typename\n }\n}\n`, - variables: { favoriteIdHash: user.hash, questionId: "" + problem.id }, - operationName: operationName, - }; + opts.body = starred + ? getAddQuestionToFavoriteBody(user.hash, problem.id) + : getRemoveQuestionFromFavoriteBody(user.hash, problem.id); // getStarProblem(user.hash, problem.id); // eslint-disable-next-line @typescript-eslint/no-unused-vars request.post(opts, function (e: any, resp: any, _) { @@ -364,11 +346,7 @@ server to get the problem's description, test cases, and other information. */ opts.headers.Origin = configUtils.sys.urls.base; opts.headers.Referer = configUtils.sys.urls.base; opts.json = true; - opts.body = { - query: ["{", " user {", " username", " isCurrentUserPremium", " }", "}"].join("\n"), - variables: {}, - }; - + opts.body = getUserInfoBody(); request.post(opts, function (e, resp, body) { e = checkError(e, resp, 200); if (e) return cb(e); @@ -378,40 +356,6 @@ server to get the problem's description, test cases, and other information. */ }); }; - /* Making a request to the server and returning the response. */ - runSession = (method: any, data: any, cb: any) => { - const opts = makeOpts(configUtils.sys.urls.session); - opts.json = true; - opts.method = method; - opts.body = data; - - request(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e && e.statusCode === 302) e = sessionUtils.errors.EXPIRED; - - return e ? cb(e) : cb(null, body.sessions); - }); - }; - - getSessions = (cb) => { - this.runSession("POST", {}, cb); - }; - - activateSession = (session, cb) => { - const data = { func: "activate", target: session.id }; - this.runSession("PUT", data, cb); - }; - - createSession = (name, cb) => { - const data = { func: "create", name: name }; - this.runSession("PUT", data, cb); - }; - - deleteSession = (session, cb) => { - const data = { target: session.id }; - this.runSession("DELETE", data, cb); - }; - /* A function that takes in a user object and a callback function. It then makes a request to the login page and gets the csrf token. It then makes a post request to the login page with the csrf token and the user's login and password. If the response status code is 302, it saves the user's session id @@ -685,39 +629,39 @@ and csrf token to the user object and saves the user object to the session. */ /* A function that gets the question of the day from leetcode. */ getQuestionOfToday = (cb) => { - const opts = makeOpts(configUtils.sys.urls.graphql); - opts.headers.Origin = configUtils.sys.urls.base; - opts.headers.Referer = "https://leetcode.com/"; - - opts.json = true; - opts.body = { - operationName: "questionOfToday", - variables: {}, - query: [ - "query questionOfToday {", - " todayRecord {", - " date", - " userStatus", - " question {", - " titleSlug", - " questionId", - " questionFrontendId", - // ' content', - // ' stats', - // ' likes', - // ' dislikes', - // ' codeDefinition', - // ' sampleTestCase', - // ' enableRunCode', - // ' metaData', - // ' translatedContent', - " __typename", - " }", - " __typename", - " }", - "}", - ].join("\n"), - }; + // const opts = makeOpts(configUtils.sys.urls.graphql); + // opts.headers.Origin = configUtils.sys.urls.base; + // opts.headers.Referer = "https://leetcode.com/"; + + // opts.json = true; + // opts.body = { + // operationName: "questionOfToday", + // variables: {}, + // query: [ + // "query questionOfToday {", + // " todayRecord {", + // " date", + // " userStatus", + // " question {", + // " titleSlug", + // " questionId", + // " questionFrontendId", + // // ' content', + // // ' stats', + // // ' likes', + // // ' dislikes', + // // ' codeDefinition', + // // ' sampleTestCase', + // // ' enableRunCode', + // // ' metaData', + // // ' translatedContent', + // " __typename", + // " }", + // " __typename", + // " }", + // "}", + // ].join("\n"), + // }; // request.post(opts, function (e, resp, body) { // e = checkError(e, resp, 200); @@ -739,39 +683,39 @@ and csrf token to the user object and saves the user object to the session. */ opts.headers.Origin = configUtils.sys.urls.base; opts.headers.Referer = configUtils.sys.urls.u.replace("$username", username); - opts.json = true; - opts.body = { - variables: { - userSlug: username, - }, - query: [ - " query userContestRankingInfo($userSlug: String!) {", - " userContestRanking(userSlug: $userSlug) {", - " attendedContestsCount", - " rating", - " globalRanking", - " localRanking", - " globalTotalParticipants", - " localTotalParticipants", - " topPercentage", - " }", - // ' userContestRankingHistory(userSlug: $userSlug) {', - // ' attended', - // ' totalProblems', - // ' trendingDirection', - // ' finishTimeInSeconds', - // ' rating', - // ' score', - // ' ranking', - // ' contest {', - // ' title', - // ' titleCn', - // ' startTime', - // ' }', - // ' }', - " }", - ].join("\n"), - }; + // opts.json = true; + // opts.body = { + // variables: { + // userSlug: username, + // }, + // query: [ + // " query userContestRankingInfo($userSlug: String!) {", + // " userContestRanking(userSlug: $userSlug) {", + // " attendedContestsCount", + // " rating", + // " globalRanking", + // " localRanking", + // " globalTotalParticipants", + // " localTotalParticipants", + // " topPercentage", + // " }", + // // ' userContestRankingHistory(userSlug: $userSlug) {', + // // ' attended', + // // ' totalProblems', + // // ' trendingDirection', + // // ' finishTimeInSeconds', + // // ' rating', + // // ' score', + // // ' ranking', + // // ' contest {', + // // ' title', + // // ' titleCn', + // // ' startTime', + // // ' }', + // // ' }', + // " }", + // ].join("\n"), + // }; // request.post(opts, function (e, resp, body) { // e = checkError(e, resp, 200); @@ -821,41 +765,7 @@ function getHelpEn(problem, lang, cb) { let opts = { url: URL_DISCUSSES, json: true, - body: { - query: [ - "query questionTopicsList($questionId: String!, $orderBy: TopicSortingOption, $skip: Int, $query: String, $first: Int!, $tags: [String!]) {", - " questionTopicsList(questionId: $questionId, orderBy: $orderBy, skip: $skip, query: $query, first: $first, tags: $tags) {", - " ...TopicsList", - " }", - "}", - "fragment TopicsList on TopicConnection {", - " totalNum", - " edges {", - " node {", - " id", - " title", - " post {", - " content", - " voteCount", - " author {", - " username", - " }", - " }", - " }", - " }", - "}", - ].join("\n"), - - operationName: "questionTopicsList", - variables: JSON.stringify({ - query: "", - first: 1, - skip: 0, - orderBy: "most_votes", - questionId: "" + problem.id, - tags: [lang], - }), - }, + body: getGetHelpEnBody(lang, problem.id), }; request(opts, function (e, resp, body) { if (e) return cb(e); @@ -871,7 +781,9 @@ function makeOpts(url) { opts.url = url; opts.headers = {}; - if (sessionUtils.isLogin()) signOpts(opts, sessionUtils.getUser()); + if (sessionUtils.isLogin()) { + signOpts(opts, sessionUtils.getUser()); + } return opts; } diff --git a/src/rpc/actionChain/chainNode/retry.ts b/src/rpc/actionChain/chainNode/retry.ts index bc90bb4..88518fe 100644 --- a/src/rpc/actionChain/chainNode/retry.ts +++ b/src/rpc/actionChain/chainNode/retry.ts @@ -27,12 +27,8 @@ class RetryPlugin extends ChainNodeBase { /* A wrapper for the API. */ init = () => { const names = [ - "activateSession", - "createSession", - "deleteSession", "getProblems", "getProblem", - "getSessions", "getSubmissions", "getSubmission", "getFavorites", diff --git a/src/rpc/actionChain/chainNodeBase.ts b/src/rpc/actionChain/chainNodeBase.ts index 4d5c8c7..4331d7d 100644 --- a/src/rpc/actionChain/chainNodeBase.ts +++ b/src/rpc/actionChain/chainNodeBase.ts @@ -44,18 +44,7 @@ export class ChainNodeBase { public getProblemsTitle(cb: Function): void { this.next.getProblemsTitle(cb); } - public createSession(a, cb: Function): void { - this.next.createSession(a, cb); - } - public getSessions(cb: Function): void { - this.next.getSessions(cb); - } - public activateSession(s, cb: Function): void { - this.next.activateSession(s, cb); - } - public deleteSession(s, cb: Function): void { - this.next.deleteSession(s, cb); - } + public updateProblem(a, b): void { this.next.updateProblem(a, b); } diff --git a/src/rpc/utils/graphqlUtils.ts b/src/rpc/utils/graphqlUtils.ts new file mode 100644 index 0000000..715d114 --- /dev/null +++ b/src/rpc/utils/graphqlUtils.ts @@ -0,0 +1,248 @@ +export function getQuestionDetailBody(titleSlug_value) { + return { + query: [ + "query getQuestionDetail($titleSlug: String!) {", + " question(titleSlug: $titleSlug) {", + " content", + " stats", + " likes", + " dislikes", + " codeDefinition", + " sampleTestCase", + " enableRunCode", + " metaData", + " translatedContent", + " }", + "}", + ].join("\n"), + variables: { titleSlug: titleSlug_value }, + operationName: "getQuestionDetail", + }; +} + +export function getAddQuestionToFavoriteBody(user_hash, problem_id) { + return { + query: [ + "mutation addQuestionToFavorite($favoriteIdHash: String!, $questionId: String!) {", + " addQuestionToFavorite(favoriteIdHash: $favoriteIdHash, questionId: $questionId) {", + " ok", + " error", + " favoriteIdHash", + " questionId", + " __typename", + " }", + "}", + ].join("\n"), + variables: { favoriteIdHash: user_hash, questionId: "" + problem_id }, + operationName: "addQuestionToFavorite", + }; +} + +export function getRemoveQuestionFromFavoriteBody(user_hash, problem_id) { + return { + query: [ + "mutation removeQuestionFromFavorite($favoriteIdHash: String!, $questionId: String!) {", + " removeQuestionFromFavorite(favoriteIdHash: $favoriteIdHash, questionId: $questionId) {", + " ok", + " error", + " favoriteIdHash", + " questionId", + " __typename", + " }", + "}", + ].join("\n"), + variables: { favoriteIdHash: user_hash, questionId: "" + problem_id }, + operationName: "removeQuestionFromFavorite", + }; +} + +export function getUserInfoBody() { + return { + query: ["{", " user {", " username", " isCurrentUserPremium", " }", "}"].join("\n"), + variables: {}, + }; +} + +export function getGetHelpEnBody(lang, problem_id) { + return { + query: [ + "query questionTopicsList($questionId: String!, $orderBy: TopicSortingOption, $skip: Int, $query: String, $first: Int!, $tags: [String!]) {", + " questionTopicsList(questionId: $questionId, orderBy: $orderBy, skip: $skip, query: $query, first: $first, tags: $tags) {", + " ...TopicsList", + " }", + "}", + "fragment TopicsList on TopicConnection {", + " totalNum", + " edges {", + " node {", + " id", + " title", + " post {", + " content", + " voteCount", + " author {", + " username", + " }", + " }", + " }", + " }", + "}", + ].join("\n"), + + operationName: "questionTopicsList", + variables: JSON.stringify({ + query: "", + first: 1, + skip: 0, + orderBy: "most_votes", + questionId: "" + problem_id, + tags: [lang], + }), + }; +} + +export function getProblemsTitleCNBody() { + return { + query: [ + "query getQuestionTranslation($lang: String) {", + " translations: allAppliedQuestionTranslations(lang: $lang) {", + " title", + " questionId", + " __typename", + " }", + "}", + ].join("\n"), + variables: {}, + operationName: "getQuestionTranslation", + }; +} + +export function getQuestionOfTodayCNBody() { + return { + operationName: "questionOfToday", + variables: {}, + query: [ + "query questionOfToday {", + " todayRecord {", + " date", + " userStatus", + " question {", + " titleSlug", + " questionId", + " questionFrontendId", + // ' content', + // ' stats', + // ' likes', + // ' dislikes', + // ' codeDefinition', + // ' sampleTestCase', + // ' enableRunCode', + // ' metaData', + // ' translatedContent', + " __typename", + " }", + " __typename", + " }", + "}", + ].join("\n"), + }; +} + +export function getUserContestPCNBody(username) { + return { + variables: { + userSlug: username, + }, + query: [ + " query userContestRankingInfo($userSlug: String!) {", + " userContestRanking(userSlug: $userSlug) {", + " attendedContestsCount", + " rating", + " globalRanking", + " localRanking", + " globalTotalParticipants", + " localTotalParticipants", + " topPercentage", + " }", + // ' userContestRankingHistory(userSlug: $userSlug) {', + // ' attended', + // ' totalProblems', + // ' trendingDirection', + // ' finishTimeInSeconds', + // ' rating', + // ' score', + // ' ranking', + // ' contest {', + // ' title', + // ' titleCn', + // ' startTime', + // ' }', + // ' }', + " }", + ].join("\n"), + }; +} + +export function getSolutionBySlugCNBody(articles_slug) { + return { + operationName: "solutionDetailArticle", + variables: { slug: articles_slug, orderBy: "DEFAULT" }, + query: [ + "query solutionDetailArticle($slug: String!, $orderBy: SolutionArticleOrderBy!) {", + " solutionArticle(slug: $slug, orderBy: $orderBy) {", + " ...solutionArticle", + " content", + " question {", + " questionTitleSlug", + " __typename", + " }", + " __typename", + "}", + "}", + "fragment solutionArticle on SolutionArticleNode {", + " uuid", + " title", + " slug", + " identifier", + "author {", + " username", + " profile {", + " realName", + " __typename", + " }", + " __typename", + "}", + "byLeetcode", + "__typename", + "}", + ].join("\n"), + }; +} + +export function getSolutionArticlesSlugListCNBody(question_slug, lang) { + return { + operationName: "questionSolutionArticles", + variables: { questionSlug: question_slug, first: 1, skip: 0, orderBy: "DEFAULT", tagSlugs: [lang] }, + 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", + " slug", + " byLeetcode", + " __typename", + "}", + ].join("\n"), + }; +} From e6c65f22aadac46e7d0ebbac13f3112b86761356 Mon Sep 17 00:00:00 2001 From: ccagml Date: Thu, 9 Mar 2023 16:58:03 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=9C=89=E7=82=B9?= =?UTF-8?q?=E9=97=AE=E9=A2=98,=E5=A5=87=E6=80=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 10 +-- package.nls.json | 2 +- package.nls.zh-cn.json | 2 +- resources/templates/codeonly.tpl | 2 +- resources/templates/detailed.tpl | 2 +- src/controller/LoginController.ts | 94 ++++++++++---------- src/controller/MainController.ts | 2 +- src/controller/TreeViewController.ts | 15 ++-- src/extension.ts | 2 +- src/model/Model.ts | 8 +- src/rpc/actionChain/chainNode/cache.ts | 6 +- src/rpc/actionChain/chainNode/core.ts | 39 +------- src/rpc/actionChain/chainNode/leetcode.cn.ts | 32 ++++--- src/rpc/actionChain/chainNode/leetcode.ts | 47 +++++++++- src/rpc/actionChain/chainNode/retry.ts | 2 +- src/rpc/actionChain/chainNodeBase.ts | 4 +- src/rpc/childMain.ts | 3 +- src/rpc/factory/api/userApi.ts | 52 ++++++----- src/rpc/utils/configUtils.ts | 7 +- src/service/BricksDataService.ts | 2 +- src/service/TreeDataService.ts | 2 +- src/utils/CliUtils.ts | 9 +- src/utils/ConfigUtils.ts | 10 +-- src/utils/OutputUtils.ts | 16 ++-- 24 files changed, 192 insertions(+), 178 deletions(-) diff --git a/package.json b/package.json index 678d885..e12eab2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-leetcode-problem-rating", "displayName": "LeetCode", "description": "%main.description%", - "version": "2.18.1", + "version": "2.18.2", "author": "ccagml", "publisher": "ccagml", "license": "MIT", @@ -28,7 +28,7 @@ "preview": true, "activationEvents": [ "onCommand:lcpr.toggleLeetCodeCn", - "onCommand:lcpr.signin", + "onCommand:lcpr.newlogin", "onCommand:lcpr.signout", "onCommand:lcpr.refreshExplorer", "onCommand:lcpr.pickOne", @@ -57,8 +57,8 @@ "icon": "$(globe)" }, { - "command": "lcpr.signin", - "title": "%main.contributes.commands.lcpr.signin.title%", + "command": "lcpr.newlogin", + "title": "%main.contributes.commands.lcpr.newlogin.title%", "category": "LeetCode", "icon": "$(sign-in)" }, @@ -355,7 +355,7 @@ "group": "navigation@0" }, { - "command": "lcpr.signin", + "command": "lcpr.newlogin", "when": "view == QuestionExplorer", "group": "navigation@1" }, diff --git a/package.nls.json b/package.nls.json index 7e92505..e3ee15c 100644 --- a/package.nls.json +++ b/package.nls.json @@ -3,7 +3,7 @@ "main.name": "vscode-leetcode-problem-rating", "main.contributes.commands.lcpr.deleteCache.title": "Delete Cache", "main.contributes.commands.lcpr.toggleLeetCodeCn.title": "Switch Endpoint", - "main.contributes.commands.lcpr.signin.title": "Sign In", + "main.contributes.commands.lcpr.newlogin.title": "Sign In", "main.contributes.commands.lcpr.signout.title": "Sign Out", "main.contributes.commands.lcpr.refreshExplorer.title": "refresh", "main.contributes.commands.lcpr.pickOne.title": "pickOne", diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json index 7c5f804..95fb9f5 100644 --- a/package.nls.zh-cn.json +++ b/package.nls.zh-cn.json @@ -3,7 +3,7 @@ "main.name": "vscode-leetcode-problem-rating", "main.contributes.commands.lcpr.deleteCache.title": "删除缓存", "main.contributes.commands.lcpr.toggleLeetCodeCn.title": "切换站点", - "main.contributes.commands.lcpr.signin.title": "登录", + "main.contributes.commands.lcpr.newlogin.title": "登录", "main.contributes.commands.lcpr.signout.title": "登出", "main.contributes.commands.lcpr.refreshExplorer.title": "刷新", "main.contributes.commands.lcpr.pickOne.title": "手气一下", diff --git a/resources/templates/codeonly.tpl b/resources/templates/codeonly.tpl index 1c8ee25..0cc46e0 100644 --- a/resources/templates/codeonly.tpl +++ b/resources/templates/codeonly.tpl @@ -1,6 +1,6 @@ <%=comment.start%> <%=comment.line%> @lc app=<%=app%> id=<%=fid%> lang=<%=lang%> -<%=comment.line%> @lcpr version=<%=LCPTCTX.version%> +<%=comment.line%> @lcpr version=<%=LCPRCTX.version%> <%=comment.line%> <%=comment.line%> [<%=fid%>] <%=name%> <%=comment.end%> diff --git a/resources/templates/detailed.tpl b/resources/templates/detailed.tpl index 8d2cd66..2ea653e 100644 --- a/resources/templates/detailed.tpl +++ b/resources/templates/detailed.tpl @@ -1,6 +1,6 @@ <%=comment.start%> <%=comment.line%> @lc app=<%=app%> id=<%=fid%> lang=<%=lang%> -<%=comment.line%> @lcpr version=<%=LCPTCTX.version%> +<%=comment.line%> @lcpr version=<%=LCPRCTX.version%> <%=comment.line%> <%=comment.line%> [<%=fid%>] <%=name%> <%=comment.line%> diff --git a/src/controller/LoginController.ts b/src/controller/LoginController.ts index 5054a0f..02d6792 100644 --- a/src/controller/LoginController.ts +++ b/src/controller/LoginController.ts @@ -10,7 +10,7 @@ import * as cp from "child_process"; import * as systemUtils from "../utils/SystemUtils"; import { executeService } from "../service/ExecuteService"; -import { OutPutType, Endpoint, IQuickItemEx, loginArgsMapping, UserStatus } from "../model/Model"; +import { OutPutType, Endpoint, IQuickItemEx, UserStatus } from "../model/Model"; import { createEnvOption } from "../utils/CliUtils"; import { logOutput, promptForOpenOutputChannel } from "../utils/OutputUtils"; import { eventService } from "../service/EventService"; @@ -23,35 +23,32 @@ import { bricksDataService } from "../service/BricksDataService"; // 登录控制器 class LoginContorller { constructor() {} - commandArg: string | undefined; + loginMethod: string; - public async getUserName(): Promise { + public async getUserName(login_info: any): Promise { let result: string = ""; await window.withProgress({ location: ProgressLocation.Notification }, async (p: Progress<{}>) => { return new Promise( async (resolve: (res: string | undefined) => void, reject: (e: Error) => void): Promise => { - if (this.commandArg == undefined) { - reject(new Error("not commandArg")); - return; - } const leetCodeBinaryPath: string = await executeService.getLeetCodeBinaryPath(); let childProc: cp.ChildProcess; if (systemUtils.useVscodeNode()) { - childProc = cp.fork(await executeService.getLeetCodeBinaryPath(), ["user", this.commandArg], { + let newargs: string[] = ["user", login_info.cmd]; + childProc = cp.fork(leetCodeBinaryPath, newargs, { silent: true, - env: createEnvOption(), + env: createEnvOption(JSON.stringify(login_info)), }); } else { if (systemUtils.useWsl()) { - childProc = cp.spawn("wsl", [executeService.node, leetCodeBinaryPath, "user", this.commandArg], { - shell: true, - }); + let newargs: string[] = [executeService.node, leetCodeBinaryPath, "user", login_info.cmd]; + childProc = cp.spawn("wsl", newargs, { shell: true, env: createEnvOption(JSON.stringify(login_info)) }); } else { - childProc = cp.spawn(executeService.node, [leetCodeBinaryPath, "user", this.commandArg], { + let newargs: string[] = [leetCodeBinaryPath, "user", login_info.cmd]; + childProc = cp.spawn(executeService.node, newargs, { shell: true, - env: createEnvOption(), + env: createEnvOption(JSON.stringify(login_info)), }); } } @@ -92,31 +89,6 @@ class LoginContorller { childProc.stderr?.on("data", (data: string | Buffer) => logOutput.append(data.toString())); childProc.on("error", reject); - - const name: string | undefined = await window.showInputBox({ - prompt: "Enter username or E-mail.", - ignoreFocusOut: true, - validateInput: (s: string): string | undefined => - s && s.trim() ? undefined : "The input must not be empty", - }); - if (!name) { - childProc.kill(); - return resolve(undefined); - } - childProc.stdin?.write(`${name}\n`); - const isByCookie: boolean = this.loginMethod === "Cookie"; - const pwd: string | undefined = await window.showInputBox({ - prompt: isByCookie ? "Enter cookie" : "Enter password.", - password: true, - ignoreFocusOut: true, - validateInput: (s: string): string | undefined => - s ? undefined : isByCookie ? "Cookie must not be empty" : "Password must not be empty", - }); - if (!pwd) { - childProc.kill(); - return resolve(undefined); - } - childProc.stdin?.write(`${pwd}\n`); p.report({ message: "正在登录中~~~~" }); } ); @@ -127,7 +99,7 @@ class LoginContorller { /* A login function. */ // 登录操作 - public async signIn(): Promise { + public async NewLogin(): Promise { const picks: Array> = []; let qpOpiton: QuickPickOptions = { title: "正在登录leetcode.com", @@ -140,6 +112,7 @@ class LoginContorller { label: "LeetCode Account", detail: "只能登录leetcode.cn", value: "LeetCode", + cmd: "-l", }); qpOpiton.title = "正在登录中文版leetcode.cn"; qpOpiton.placeHolder = "请选择登录方式 正在登录中文版leetcode.cn"; @@ -149,16 +122,19 @@ class LoginContorller { label: "Third-Party: GitHub", detail: "Use GitHub account to login", value: "GitHub", + cmd: "-g", }, { label: "Third-Party: LinkedIn", detail: "Use LinkedIn account to login", value: "LinkedIn", + cmd: "-i", }, { label: "LeetCode Cookie", detail: "Use LeetCode cookie copied from browser to login", value: "Cookie", + cmd: "-c", } ); const choice: IQuickItemEx | undefined = await window.showQuickPick(picks, qpOpiton); @@ -166,20 +142,46 @@ class LoginContorller { return; } this.loginMethod = choice.value; - this.commandArg = loginArgsMapping.get(this.loginMethod); - if (!this.commandArg) { + + if (!choice.cmd) { throw new Error(`不支持 "${this.loginMethod}" 方式登录`); + return; } + + let login_info: any = {}; + login_info.cmd = choice.cmd; + + const name: string | undefined = await window.showInputBox({ + prompt: "Enter username or E-mail.", + ignoreFocusOut: true, + validateInput: (s: string): string | undefined => (s && s.trim() ? undefined : "The input must not be empty"), + }); + if (!name) { + return; + } + login_info.name = name; + const isByCookie: boolean = this.loginMethod === "Cookie"; - const inMessage: string = isByCookie ? " 通过cookie登录" : "登录"; + const passWord: string | undefined = await window.showInputBox({ + prompt: isByCookie ? "Enter cookie" : "Enter password.", + password: true, + ignoreFocusOut: true, + validateInput: (s: string): string | undefined => + s ? undefined : isByCookie ? "Cookie must not be empty" : "Password must not be empty", + }); + if (!passWord) { + return; + } + login_info.pass = passWord; + try { - const userName: string | undefined = await this.getUserName(); + const userName: string | undefined = await this.getUserName(login_info); if (userName) { eventService.emit("statusChanged", UserStatus.SignedIn, userName); - window.showInformationMessage(`${inMessage} 成功`); + window.showInformationMessage(`登录成功`); } } catch (error) { - promptForOpenOutputChannel(`${inMessage}失败. 请看看控制台输出信息`, OutPutType.error); + promptForOpenOutputChannel(`登录失败. 请看看控制台输出信息`, OutPutType.error); } } diff --git a/src/controller/MainController.ts b/src/controller/MainController.ts index 0f02b97..53d380e 100644 --- a/src/controller/MainController.ts +++ b/src/controller/MainController.ts @@ -58,7 +58,7 @@ class MainContorller { cur_version_num *= 100; cur_version_num += Number(e); }); - logOutput.setLCPTCTX("version", cur_version_num); + logOutput.setLCPRCTX("version", cur_version_num); } // 初始化上下文 diff --git a/src/controller/TreeViewController.ts b/src/controller/TreeViewController.ts index ea810df..56b2394 100644 --- a/src/controller/TreeViewController.ts +++ b/src/controller/TreeViewController.ts @@ -527,12 +527,12 @@ class TreeViewController implements Disposable { label: `周赛期数查询`, detail: `周赛期数查询`, value: `contest`, + }, + { + label: `测试api`, + detail: `测试api`, + value: `testapi`, } - // { - // label: `测试api`, - // detail: `测试api`, - // value: `testapi`, - // } ); const choice: IQuickItemEx | undefined = await vscode.window.showQuickPick(picks, { title: "选择查询选项", @@ -628,10 +628,7 @@ class TreeViewController implements Disposable { public async testapi(): Promise { try { - let so = {}; - - const solution: string = JSON.stringify(so); - solutionService.show(solution); + executeService.getTestApi("ss"); } catch (error) { logOutput.appendLine(error.toString()); await promptForOpenOutputChannel("Failed to fetch today question. 请查看控制台信息~", OutPutType.error); diff --git a/src/extension.ts b/src/extension.ts index b5d0d2d..ff6609f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -65,7 +65,7 @@ export async function activate(context: ExtensionContext): Promise { window.createTreeView("BricksExplorer", { treeDataProvider: bricksDataService, showCollapseAll: true }), commands.registerCommand("lcpr.deleteCache", () => mainContorller.deleteCache()), commands.registerCommand("lcpr.toggleLeetCodeCn", () => treeViewController.switchEndpoint()), - commands.registerCommand("lcpr.signin", () => loginContorller.signIn()), + commands.registerCommand("lcpr.newlogin", () => loginContorller.NewLogin()), commands.registerCommand("lcpr.signout", () => loginContorller.signOut()), commands.registerCommand("lcpr.previewProblem", (node: NodeModel) => treeViewController.previewProblem(node)), commands.registerCommand("lcpr.showProblem", (node: NodeModel) => treeViewController.showProblem(node)), diff --git a/src/model/Model.ts b/src/model/Model.ts index 6adc1da..4e40d65 100644 --- a/src/model/Model.ts +++ b/src/model/Model.ts @@ -21,6 +21,7 @@ import { getDayNowM, getRemakeName } from "../utils/SystemUtils"; export interface IQuickItemEx extends QuickPickItem { value: T; + cmd?: string; } export enum UserStatus { @@ -28,13 +29,6 @@ export enum UserStatus { SignedOut = 2, } -export const loginArgsMapping: Map = new Map([ - ["LeetCode", "-l"], - ["Cookie", "-c"], - ["GitHub", "-g"], - ["LinkedIn", "-i"], -]); - export const AllProgramLanguage: string[] = [ "bash", "c", diff --git a/src/rpc/actionChain/chainNode/cache.ts b/src/rpc/actionChain/chainNode/cache.ts index 3f7d8b7..597eb8e 100644 --- a/src/rpc/actionChain/chainNode/cache.ts +++ b/src/rpc/actionChain/chainNode/cache.ts @@ -113,9 +113,9 @@ problems from the next layer. */ }; /* Logging out the user and then logging in the user. */ - login = (user, cb) => { - this.logout(user, false); - this.next.login(user, function (e, user) { + normalLogin = (login_info, cb) => { + this.logout(login_info, false); + this.next.normalLogin(login_info, function (e, user) { if (e) return cb(e); sessionUtils.saveUser(user); return cb(null, user); diff --git a/src/rpc/actionChain/chainNode/core.ts b/src/rpc/actionChain/chainNode/core.ts index 24ba0d2..1b1d67c 100644 --- a/src/rpc/actionChain/chainNode/core.ts +++ b/src/rpc/actionChain/chainNode/core.ts @@ -17,10 +17,6 @@ import { configUtils } from "../../utils/configUtils"; import { ChainNodeBase } from "../chainNodeBase"; -// function hasTag(o, tag) { -// return Array.isArray(o) && o.some((x) => x.indexOf(tag.toLowerCase()) >= 0); -// } - /* It's a class that extends the ChainNodeBase class, and it has a bunch of methods that are called by the LeetCode CLI */ class CorePlugin extends ChainNodeBase { @@ -36,18 +32,6 @@ class CorePlugin extends ChainNodeBase { this.getProblems(!opts.dontTranslate, function (e, problems) { if (e) return cb(e); - // for (let q of (opts.query || "").split("")) { - // const f = QUERY_HANDLERS[q]; - // if (!f) continue; - // problems = problems.filter((x) => f(x, q)); - // } - - // for (let t of opts.tag || []) { - // problems = problems.filter(function (x) { - // return x.category === t || hasTag(x.companies, t) || hasTag(x.tags, t); - // }); - // } - return cb(null, problems); }); }; @@ -86,7 +70,7 @@ class CorePlugin extends ChainNodeBase { const data = _.extend({}, problem); // 增加版本信息 - data.LCPTCTX = configUtils.LCPTCTX; + data.LCPRCTX = configUtils.LCPRCTX; data.allCaseList = storageUtils.getAllCase(problem.desc); // unify format before rendering @@ -144,25 +128,4 @@ class CorePlugin extends ChainNodeBase { }; } -// const isLevel = (x, q) => x.level[0].toLowerCase() === q.toLowerCase(); -// const isACed = (x) => x.state === "ac"; -// const isLocked = (x) => x.locked; -// const isStarred = (x) => x.starred; - -/* It's a dictionary that maps the query to the function that filters the problems. */ -// const QUERY_HANDLERS = { -// e: isLevel, -// E: _.negate(isLevel), -// m: isLevel, -// M: _.negate(isLevel), -// h: isLevel, -// H: _.negate(isLevel), -// l: isLocked, -// L: _.negate(isLocked), -// d: isACed, -// D: _.negate(isACed), -// s: isStarred, -// S: _.negate(isStarred), -// }; - export const corePlugin: CorePlugin = new CorePlugin(); diff --git a/src/rpc/actionChain/chainNode/leetcode.cn.ts b/src/rpc/actionChain/chainNode/leetcode.cn.ts index 7991768..6f295c3 100644 --- a/src/rpc/actionChain/chainNode/leetcode.cn.ts +++ b/src/rpc/actionChain/chainNode/leetcode.cn.ts @@ -11,6 +11,8 @@ import { ChainNodeBase } from "../chainNodeBase"; let request = require("request"); +import axios, { AxiosError, AxiosResponse } from "axios"; + import { configUtils } from "../../utils/configUtils"; import { sessionUtils } from "../../utils/sessionUtils"; @@ -119,23 +121,30 @@ class LeetCodeCn extends ChainNodeBase { /* A function that is used to get the rating of the problems. */ getRatingOnline = (cb) => { - const _request = request.defaults({ timeout: 2000, jar: true }); - _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error: any, _, body: any) { - cb(error, body); - }); + // const _request = request.defaults({ timeout: 2000, jar: true }); + // _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error: any, _, body: any) { + // cb(error, body); + // }); + + axios + .get("https://zerotrac.github.io/leetcode_problem_rating/data.json", { timeout: 2000 }) + .then(function (response: AxiosResponse) { + cb(null, response.data); + }) + .catch(function (error: AxiosError) { + let error_info: any = {}; + error_info.msg = error.message; + if (error.response) { + error_info.statusCode = error.response?.status; + } + cb(error_info); + }); }; /* A function that is used to test the api. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars getTestApi = (value: any, _) => { console.log(value); - let question_slug = "determine-color-of-a-chessboard-square"; - let lang = "cpp"; - - getSolutionArticlesSlugList(question_slug, lang, (e, articles_slug) => { - if (e) return; - getSolutionBySlug(question_slug, articles_slug, lang); - }); }; getHelpOnline = (problem, cn_flag, lang) => { @@ -189,7 +198,6 @@ function getSolutionBySlug(question_slug: string, articles_slug: string, lang: s function getSolutionArticlesSlugList(question_slug: string, lang: string, cb) { const opts = makeOpts(configUtils.sys.urls.graphql); opts.headers.Origin = configUtils.sys.urls.base; - // let URL_DISCUSSES = "https://leetcode.com/graphql"; let URL_DISCUSS = "https://leetcode.cn/problems/$slug/solution"; opts.headers.Referer = URL_DISCUSS.replace("$slug", question_slug); diff --git a/src/rpc/actionChain/chainNode/leetcode.ts b/src/rpc/actionChain/chainNode/leetcode.ts index fd1626e..c120bc7 100644 --- a/src/rpc/actionChain/chainNode/leetcode.ts +++ b/src/rpc/actionChain/chainNode/leetcode.ts @@ -13,6 +13,7 @@ let underscore = require("underscore"); let request = require("request"); let prompt_out = require("prompt"); +// import axios, { AxiosError, AxiosResponse } from "axios"; import { configUtils } from "../../utils/configUtils"; import { commUtils } from "../../utils/commUtils"; import { storageUtils } from "../../utils/storageUtils"; @@ -361,6 +362,48 @@ page and gets the csrf token. It then makes a post request to the login page wit the user's login and password. If the response status code is 302, it saves the user's session id and csrf token to the user object and saves the user object to the session. */ signin = (user: any, cb: any) => { + // axios + // .get(configUtils.sys.urls.login) + // .then(function (response: AxiosResponse) { + // login_info.loginCSRF = commUtils.getSetCookieValue(response, "csrftoken"); + // axios + // .post( + // configUtils.sys.urls.login, + // { + // csrfmiddlewaretoken: login_info.loginCSRF, + // login: login_info.login, + // password: login_info.pass, + // }, + // { + // headers: { + // "Content-Type": "multipart/form-data", + // Origin: configUtils.sys.urls.base, + // Referer: configUtils.sys.urls.login, + // Cookie: "csrftoken=" + login_info.loginCSRF + ";", + // }, + // } + // ) + // .then(function (response: AxiosResponse) { + // //handle success + // // console.log(response); + // login_info.sessionCSRF = commUtils.getSetCookieValue(response, "csrftoken"); + // login_info.sessionId = commUtils.getSetCookieValue(response, "LEETCODE_SESSION"); + // sessionUtils.saveUser(login_info); + // return cb(null, login_info); + // }) + // .catch(function (response: AxiosError) { + // //handle error + // if (response.response?.status !== 302) return cb("invalid password?"); + // }); + // }) + // .catch(function (error: AxiosError) { + // let error_info: any = {}; + // error_info.msg = error.message; + // if (error.response) { + // error_info.statusCode = error.response?.status; + // } + // cb(error_info); + // }); // eslint-disable-next-line @typescript-eslint/no-unused-vars request(configUtils.sys.urls.login, function (e: any, resp: any, _) { e = checkError(e, resp, 200); @@ -420,9 +463,9 @@ and csrf token to the user object and saves the user object to the session. */ }); }; - login = (user, cb) => { + normalLogin = (login_info, cb) => { let that = this; - that.signin(user, function (e, user) { + that.signin(login_info, function (e, user) { if (e) return cb(e); that.getUser(user, cb); }); diff --git a/src/rpc/actionChain/chainNode/retry.ts b/src/rpc/actionChain/chainNode/retry.ts index 88518fe..378be38 100644 --- a/src/rpc/actionChain/chainNode/retry.ts +++ b/src/rpc/actionChain/chainNode/retry.ts @@ -76,7 +76,7 @@ login function. */ return cb(); } - this.next.login(user, function (e) { + this.next.normalLogin(user, function (e) { if (e) { // } else { diff --git a/src/rpc/actionChain/chainNodeBase.ts b/src/rpc/actionChain/chainNodeBase.ts index 4331d7d..863ca73 100644 --- a/src/rpc/actionChain/chainNodeBase.ts +++ b/src/rpc/actionChain/chainNodeBase.ts @@ -60,8 +60,8 @@ export class ChainNodeBase { public testProblem(s, cb: Function): void { this.next.testProblem(s, cb); } - public login(user, cb: Function): void { - this.next.login(user, cb); + public normalLogin(login_info, cb: Function): void { + this.next.normalLogin(login_info, cb); } public logout(user, cb): void { this.next.logout(user, cb); diff --git a/src/rpc/childMain.ts b/src/rpc/childMain.ts index e024edf..5311b81 100644 --- a/src/rpc/childMain.ts +++ b/src/rpc/childMain.ts @@ -23,7 +23,8 @@ class Main { process.stdout.on("error", function (e) { if (e.code === "EPIPE") process.exit(); }); - configUtils.init(JSON.parse(process.env.ccagml || "{}")); + configUtils.init_env("LCPRCTX", JSON.parse(process.env.ccagml || "{}")); + configUtils.init_env("LCPRENVEXTRA", JSON.parse(process.env.extra || "{}")); reply.init(); storageUtils.init(); chainMgr.init(corePlugin); diff --git a/src/rpc/factory/api/userApi.ts b/src/rpc/factory/api/userApi.ts index 2937ba7..d4600a4 100644 --- a/src/rpc/factory/api/userApi.ts +++ b/src/rpc/factory/api/userApi.ts @@ -15,6 +15,7 @@ import { sessionUtils } from "../../utils/sessionUtils"; import { ApiBase } from "../apiBase"; import { chainMgr } from "../../actionChain/chainManager"; +import { configUtils } from "../../utils/configUtils"; class UserApi extends ApiBase { constructor() { @@ -53,7 +54,6 @@ class UserApi extends ApiBase { default: false, describe: "Logout", }); - argv_config.parseArgFromCmd(argv); return argv_config.get_result(); @@ -63,28 +63,36 @@ class UserApi extends ApiBase { sessionUtils.argv = argv; let user: any = null; if (argv.login) { - // login - prompt_out.colors = false; - prompt_out.message = ""; - prompt_out.start(); - prompt_out.get( - [ - { name: "login", required: true }, - { name: "pass", required: true, hidden: true }, - ], - function (e, user) { - if (e) { - return reply.info(JSON.stringify({ code: -1, msg: e.msg || e })); - } - - chainMgr.getChainHead().login(user, function (e, user) { - if (e) { - return reply.info(JSON.stringify({ code: -2, msg: e.msg || e })); - } - reply.info(JSON.stringify({ code: 100, user_name: user.name })); - }); + let login_info: any = {}; + login_info.name = configUtils.LCPRENVEXTRA?.name || ""; + login_info.pass = configUtils.LCPRENVEXTRA?.pass || ""; + chainMgr.getChainHead().normalLogin(login_info, function (e, user) { + if (e) { + return reply.info(JSON.stringify({ code: -2, msg: e.msg || e })); } - ); + reply.info(JSON.stringify({ code: 100, user_name: user.name })); + }); + // // login + // prompt_out.colors = false; + // prompt_out.message = ""; + // prompt_out.start(); + // prompt_out.get( + // [ + // { name: "login", required: true }, + // { name: "pass", required: true, hidden: true }, + // ], + // function (e, user) { + // if (e) { + // return reply.info(JSON.stringify({ code: -1, msg: e.msg || e })); + // } + // chainMgr.getChainHead().login(user, function (e, user) { + // if (e) { + // return reply.info(JSON.stringify({ code: -2, msg: e.msg || e })); + // } + // reply.info(JSON.stringify({ code: 100, user_name: user.name })); + // }); + // } + // ); } else if (argv.logout) { // logout user = chainMgr.getChainHead().logout(user, true); diff --git a/src/rpc/utils/configUtils.ts b/src/rpc/utils/configUtils.ts index 7b7f124..b7faa25 100644 --- a/src/rpc/utils/configUtils.ts +++ b/src/rpc/utils/configUtils.ts @@ -10,7 +10,8 @@ let underscore = require("underscore"); class Config { - LCPTCTX: any; + LCPRCTX: any; + LCPRENVEXTRA: any; app: any; sys: any; autologin: any; @@ -103,8 +104,8 @@ class Config { this.plugins = {}; } - init(ctx) { - this.LCPTCTX = ctx; + init_env(key, value) { + this[key] = value; } getAll(useronly) { diff --git a/src/service/BricksDataService.ts b/src/service/BricksDataService.ts index c126421..1fea3d0 100644 --- a/src/service/BricksDataService.ts +++ b/src/service/BricksDataService.ts @@ -38,7 +38,7 @@ export class BricksDataService implements TreeDataProvider { label: element.name, collapsibleState: element.collapsibleState, // 没有子节点 command: { - command: "lcpr.signin", + command: "lcpr.newlogin", title: "工头说你不是我们工地的人", }, }; diff --git a/src/service/TreeDataService.ts b/src/service/TreeDataService.ts index e35cf06..ca797ed 100644 --- a/src/service/TreeDataService.ts +++ b/src/service/TreeDataService.ts @@ -60,7 +60,7 @@ export class TreeDataService implements vscode.TreeDataProvider { label: element.name, collapsibleState: vscode.TreeItemCollapsibleState.None, command: { - command: "lcpr.signin", + command: "lcpr.newlogin", title: "未登录", }, }; diff --git a/src/utils/CliUtils.ts b/src/utils/CliUtils.ts index 36b9b56..014445f 100644 --- a/src/utils/CliUtils.ts +++ b/src/utils/CliUtils.ts @@ -96,19 +96,16 @@ export async function executeCommandWithProgress( return result; } -function childLCPTCTX(): string { - return JSON.stringify(logOutput.getLCPTCTXAll()); -} - // clone process.env and add http proxy -export function createEnvOption(): {} { +export function createEnvOption(extra?: string): {} { const proxy: string | undefined = getHttpAgent(); const env: any = Object.create(process.env); if (proxy) { env.http_proxy = proxy; return env; } - env.ccagml = childLCPTCTX(); + env.ccagml = JSON.stringify(logOutput.getLCPRCTXAll()); + env.extra = extra; return env; } diff --git a/src/utils/ConfigUtils.ts b/src/utils/ConfigUtils.ts index 5a07dc9..e17957f 100644 --- a/src/utils/ConfigUtils.ts +++ b/src/utils/ConfigUtils.ts @@ -158,19 +158,19 @@ export function enableSideMode(): boolean { return getVsCodeConfig().get("enableSideMode", true); } -export function getNodePath() { +export function getNodePath(): string { return getVsCodeConfig().get("nodePath", "node" /* default value */); } -export function isShowLocked() { +export function isShowLocked(): boolean { return !!getVsCodeConfig().get("showLocked"); } -export function isUseVscodeNode() { +export function isUseVscodeNode(): boolean { return getVsCodeConfig().get("useVscodeNode") === true; } -export function isUseWsl() { +export function isUseWsl(): boolean { return getVsCodeConfig().get("useWsl") === true; } @@ -178,7 +178,7 @@ export function getSortingStrategy(): SortingStrategy { return getVsCodeConfig().get("problems.sortStrategy", SortingStrategy.None); } -export async function updateSortingStrategy(value: string, flag: boolean) { +export async function updateSortingStrategy(value: string, flag: boolean): Promise { await getVsCodeConfig().update("problems.sortStrategy", value, flag); } diff --git a/src/utils/OutputUtils.ts b/src/utils/OutputUtils.ts index d69157e..b85203b 100644 --- a/src/utils/OutputUtils.ts +++ b/src/utils/OutputUtils.ts @@ -45,7 +45,7 @@ export async function promptForSignIn(): Promise { ); switch (choice) { case DialogOptions.yes: - await vscode.commands.executeCommand("lcpr.signin"); + await vscode.commands.executeCommand("lcpr.newlogin"); break; case DialogOptions.singUp: if (getLeetCodeEndpoint()) { @@ -83,7 +83,7 @@ export async function promptForOpenOutputChannel(message: string, type: OutPutTy class LogOutput implements vscode.Disposable { private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel("LeetCodeProblemRating"); - private LCPTCTX = {}; + private LCPRCTX = {}; public appendLine(message: string): void { this.channel.appendLine(message); } @@ -100,16 +100,16 @@ class LogOutput implements vscode.Disposable { this.channel.dispose(); } - public setLCPTCTX(k, v) { - this.LCPTCTX[k] = v; + public setLCPRCTX(k, v) { + this.LCPRCTX[k] = v; } - public getLCPTCTX(k) { - return this.LCPTCTX[k]; + public getLCPRCTX(k) { + return this.LCPRCTX[k]; } - public getLCPTCTXAll() { - return this.LCPTCTX; + public getLCPRCTXAll() { + return this.LCPRCTX; } } From cbecfcfb8c2b3628a2ccaed6419682b563dd0c46 Mon Sep 17 00:00:00 2001 From: ccagml Date: Sat, 11 Mar 2023 10:23:51 +0800 Subject: [PATCH 3/6] update --- src/rpc/actionChain/chainNode/leetcode.ts | 107 +++++++++++----------- src/rpc/factory/api/userApi.ts | 2 +- 2 files changed, 56 insertions(+), 53 deletions(-) diff --git a/src/rpc/actionChain/chainNode/leetcode.ts b/src/rpc/actionChain/chainNode/leetcode.ts index c120bc7..ba0453c 100644 --- a/src/rpc/actionChain/chainNode/leetcode.ts +++ b/src/rpc/actionChain/chainNode/leetcode.ts @@ -361,76 +361,79 @@ server to get the problem's description, test cases, and other information. */ page and gets the csrf token. It then makes a post request to the login page with the csrf token and the user's login and password. If the response status code is 302, it saves the user's session id and csrf token to the user object and saves the user object to the session. */ - signin = (user: any, cb: any) => { - // axios - // .get(configUtils.sys.urls.login) - // .then(function (response: AxiosResponse) { - // login_info.loginCSRF = commUtils.getSetCookieValue(response, "csrftoken"); - // axios - // .post( - // configUtils.sys.urls.login, - // { - // csrfmiddlewaretoken: login_info.loginCSRF, - // login: login_info.login, - // password: login_info.pass, - // }, - // { - // headers: { - // "Content-Type": "multipart/form-data", - // Origin: configUtils.sys.urls.base, - // Referer: configUtils.sys.urls.login, - // Cookie: "csrftoken=" + login_info.loginCSRF + ";", + signin = (login_info: any, cb: any) => { + // axios + // .get(configUtils.sys.urls.login) + // .then(function (response: AxiosResponse) { + // login_info.loginCSRF = commUtils.getSetCookieValue(response, "csrftoken"); + // axios + // .post( + // configUtils.sys.urls.login, + // { + // csrfmiddlewaretoken: login_info.loginCSRF, + // login: login_info.login, + // password: login_info.pass, // }, - // } - // ) - // .then(function (response: AxiosResponse) { - // //handle success - // // console.log(response); - // login_info.sessionCSRF = commUtils.getSetCookieValue(response, "csrftoken"); - // login_info.sessionId = commUtils.getSetCookieValue(response, "LEETCODE_SESSION"); - // sessionUtils.saveUser(login_info); - // return cb(null, login_info); - // }) - // .catch(function (response: AxiosError) { - // //handle error - // if (response.response?.status !== 302) return cb("invalid password?"); - // }); - // }) - // .catch(function (error: AxiosError) { - // let error_info: any = {}; - // error_info.msg = error.message; - // if (error.response) { - // error_info.statusCode = error.response?.status; - // } - // cb(error_info); - // }); + // { + // headers: { + // "Content-Type": "multipart/form-data", + // Origin: configUtils.sys.urls.base, + // Referer: configUtils.sys.urls.login, + // Cookie: "csrftoken=" + login_info.loginCSRF + ";", + // }, + // } + // ) + // .then(function (response: AxiosResponse) { + // //handle success + // // console.log(response); + // login_info.sessionCSRF = commUtils.getSetCookieValue(response, "csrftoken"); + // login_info.sessionId = commUtils.getSetCookieValue(response, "LEETCODE_SESSION"); + // sessionUtils.saveUser(login_info); + // return cb(null, login_info); + // }) + // .catch(function (response: AxiosError) { + // //handle error + // if (response.response?.status !== 302) return cb("invalid password?"); + // login_info.sessionCSRF = commUtils.getSetCookieValue(response, "csrftoken"); + // login_info.sessionId = commUtils.getSetCookieValue(response, "LEETCODE_SESSION"); + // sessionUtils.saveUser(login_info); + // return cb(null, login_info); + // }); + // }) + // .catch(function (error: AxiosError) { + // let error_info: any = {}; + // error_info.msg = error.message; + // if (error.response) { + // error_info.statusCode = error.response?.status; + // } + // cb(error_info); + // }); // eslint-disable-next-line @typescript-eslint/no-unused-vars request(configUtils.sys.urls.login, function (e: any, resp: any, _) { e = checkError(e, resp, 200); if (e) return cb(e); - user.loginCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); + login_info.loginCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); const opts = { url: configUtils.sys.urls.login, headers: { Origin: configUtils.sys.urls.base, Referer: configUtils.sys.urls.login, - Cookie: "csrftoken=" + user.loginCSRF + ";", + Cookie: "csrftoken=" + login_info.loginCSRF + ";", }, form: { - csrfmiddlewaretoken: user.loginCSRF, - login: user.login, - password: user.pass, + csrfmiddlewaretoken: login_info.loginCSRF, + login: login_info.login, + password: login_info.pass, }, }; // eslint-disable-next-line @typescript-eslint/no-unused-vars request.post(opts, function (e: any, resp: any, _) { if (e) return cb(e); if (resp.statusCode !== 302) return cb("invalid password?"); - - user.sessionCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); - user.sessionId = commUtils.getSetCookieValue(resp, "LEETCODE_SESSION"); - sessionUtils.saveUser(user); - return cb(null, user); + login_info.sessionCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); + login_info.sessionId = commUtils.getSetCookieValue(resp, "LEETCODE_SESSION"); + sessionUtils.saveUser(login_info); + return cb(null, login_info); }); }); }; diff --git a/src/rpc/factory/api/userApi.ts b/src/rpc/factory/api/userApi.ts index d4600a4..86518dd 100644 --- a/src/rpc/factory/api/userApi.ts +++ b/src/rpc/factory/api/userApi.ts @@ -64,7 +64,7 @@ class UserApi extends ApiBase { let user: any = null; if (argv.login) { let login_info: any = {}; - login_info.name = configUtils.LCPRENVEXTRA?.name || ""; + login_info.login = configUtils.LCPRENVEXTRA?.name || ""; login_info.pass = configUtils.LCPRENVEXTRA?.pass || ""; chainMgr.getChainHead().normalLogin(login_info, function (e, user) { if (e) { From 8815b8084a7d14cd1bfd345fb35949553794e6b2 Mon Sep 17 00:00:00 2001 From: ccagml Date: Sat, 11 Mar 2023 11:33:48 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E6=9B=BF=E6=8D=A2asiox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/bin/leetcode | 2 +- src/dao/scoreDao.ts | 10 +++++----- src/rpc/actionChain/chainNode/cache.ts | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/resources/bin/leetcode b/resources/bin/leetcode index 02f42bd..25d197c 100755 --- a/resources/bin/leetcode +++ b/resources/bin/leetcode @@ -1,3 +1,3 @@ #!/usr/bin/env node -require("../../out/src/childProcessCall/childMain"); +require("../../out/src/rpc/childMain"); diff --git a/src/dao/scoreDao.ts b/src/dao/scoreDao.ts index 48aae3e..3ca600b 100644 --- a/src/dao/scoreDao.ts +++ b/src/dao/scoreDao.ts @@ -15,13 +15,13 @@ class ScoreDao { public getScoreData(onlineData?): Map { let nameSiteMapping = new Map(); let temp = this.scoreBase as IScoreData[]; - if (onlineData) { - temp = onlineData; + if (onlineData && Array.isArray(onlineData)) { + onlineData.forEach((element) => { + element.score = "" + Math.floor(element.Rating || 0); + nameSiteMapping.set("" + element.ID, element); + }); } temp.forEach((element) => { - // Rating - // ID - // ContestSlug element.score = "" + Math.floor(element.Rating || 0); nameSiteMapping.set("" + element.ID, element); }); diff --git a/src/rpc/actionChain/chainNode/cache.ts b/src/rpc/actionChain/chainNode/cache.ts index 597eb8e..b036e03 100644 --- a/src/rpc/actionChain/chainNode/cache.ts +++ b/src/rpc/actionChain/chainNode/cache.ts @@ -58,14 +58,14 @@ problems from the next layer. */ if (cacheRantingData) { return cb(null, cacheRantingData); } - this.next.getRatingOnline(function (e, ratingData) { + this.next.getRatingOnline(function (e, ratingObj) { if (e) return cb(e); - let ratingObj; - try { - ratingObj = JSON.parse(ratingData); - } catch (error) { - return cb("JSON.parse(ratingData) error"); - } + // let ratingObj; + // try { + // ratingObj = JSON.parse(ratingData); + // } catch (error) { + // return cb("JSON.parse(ratingData) error"); + // } storageUtils.setCache(commUtils.KEYS.ranting_path, ratingObj); return cb(null, ratingObj); }); From 776ac956a786a1af4b660732c6105e66ac2f80f9 Mon Sep 17 00:00:00 2001 From: ccagml Date: Sat, 11 Mar 2023 11:37:58 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f062c17..0a1da1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## version 2.18.2 + +- 修改部分登录流程 +- 部分请求使用 asiox 替换 request + ## version 2.18.1 - 增加周赛场次信息展示 From 07d71a33ca473a212b0e019aa03b2b7b9d730890 Mon Sep 17 00:00:00 2001 From: ccagml Date: Sat, 18 Mar 2023 15:22:40 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E5=8E=BB=E9=99=A4request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 4 +- package.json | 2 +- src/rpc/actionChain/chainNode/leetcode.cn.ts | 203 ++++--- src/rpc/actionChain/chainNode/leetcode.ts | 606 +++++++++---------- 4 files changed, 392 insertions(+), 423 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15834fa..17b5060 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-leetcode-problem-rating", - "version": "2.18.1", + "version": "2.19.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-leetcode-problem-rating", - "version": "2.18.1", + "version": "2.19.1", "license": "MIT", "dependencies": { "ansi-styles": "3.2.1", diff --git a/package.json b/package.json index e12eab2..1551cbd 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-leetcode-problem-rating", "displayName": "LeetCode", "description": "%main.description%", - "version": "2.18.2", + "version": "2.19.1", "author": "ccagml", "publisher": "ccagml", "license": "MIT", diff --git a/src/rpc/actionChain/chainNode/leetcode.cn.ts b/src/rpc/actionChain/chainNode/leetcode.cn.ts index 6f295c3..5f568b6 100644 --- a/src/rpc/actionChain/chainNode/leetcode.cn.ts +++ b/src/rpc/actionChain/chainNode/leetcode.cn.ts @@ -9,8 +9,6 @@ import { ChainNodeBase } from "../chainNodeBase"; -let request = require("request"); - import axios, { AxiosError, AxiosResponse } from "axios"; import { configUtils } from "../../utils/configUtils"; @@ -44,7 +42,6 @@ class LeetCodeCn extends ChainNodeBase { if (e) return cb(e); if (needTranslation) { - // only translate titles of the list if user requested that.getProblemsTitle(function (e, titles) { if (e) return cb(e); @@ -70,17 +67,25 @@ class LeetCodeCn extends ChainNodeBase { opts.json = true; opts.body = getProblemsTitleCNBody(); - request.post(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + const json_data = JSON.parse(_response.data); - const titles: Object = []; - body.data.translations.forEach(function (x) { - titles[x.questionId] = x.title; - }); + const titles: Object = []; + json_data.translations.forEach(function (x) { + titles[x.questionId] = x.title; + }); - return cb(null, titles); - }); + return cb(null, titles); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* A function that gets the question of the day from leetcode. */ @@ -91,17 +96,25 @@ class LeetCodeCn extends ChainNodeBase { opts.json = true; opts.body = getQuestionOfTodayCNBody(); - request.post(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - let result: any = {}; - result.titleSlug = body.data.todayRecord[0].question.titleSlug; - result.questionId = body.data.todayRecord[0].question.questionId; - result.fid = body.data.todayRecord[0].question.questionFrontendId; - result.date = body.data.todayRecord[0].data; - result.userStatus = body.data.todayRecord[0].userStatus; - return cb(null, result); - }); + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + const json_data = JSON.parse(_response.data); + let result: any = {}; + result.titleSlug = json_data.todayRecord[0].question.titleSlug; + result.questionId = json_data.todayRecord[0].question.questionId; + result.fid = json_data.todayRecord[0].question.questionFrontendId; + result.date = json_data.todayRecord[0].data; + result.userStatus = json_data.todayRecord[0].userStatus; + return cb(null, result); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* A function that is used to get the user contest ranking information. */ getUserContestP = (username, cb) => { @@ -111,21 +124,25 @@ class LeetCodeCn extends ChainNodeBase { opts.json = true; opts.body = getUserContestPCNBody(username); - request.post(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - return cb(null, body.data); - }); + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + const json_data = JSON.parse(_response.data); + + return cb(null, json_data); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* A function that is used to get the rating of the problems. */ getRatingOnline = (cb) => { - // const _request = request.defaults({ timeout: 2000, jar: true }); - // _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error: any, _, body: any) { - // cb(error, body); - // }); - axios .get("https://zerotrac.github.io/leetcode_problem_rating/data.json", { timeout: 2000 }) .then(function (response: AxiosResponse) { @@ -168,31 +185,41 @@ function getSolutionBySlug(question_slug: string, articles_slug: string, lang: s opts.json = true; opts.body = getSolutionBySlugCNBody(articles_slug); - request.post(opts, function (_, __, body) { - // let bbb = body; - // console.log(bbb); - let solution = body.data.solutionArticle; - if (!solution) return reply.error("本题没有题解"); - - let link = URL_DISCUSS.replace("$slug", question_slug).replace("$articles_slug", articles_slug); - // let content = solution.content.replace(/\\n/g, "\n").replace(/\\t/g, "\t"); - let content = solution.content.replace(/\\n/g, "\n"); - - content = content.replace(/\\textit{/g, "{"); - content = content.replace(/\\texttt{/g, "{"); - content = content.replace(/\\text{/g, "{"); - - let solution_result: any = {}; - solution_result.problem_name = solution.title; - solution_result.title = solution.title; - solution_result.url = link; - solution_result.lang = lang; - solution_result.author = solution.author.username; - solution_result.votes = solution.voteCount; - solution_result.body = content; - solution_result.is_cn = true; - reply.info(JSON.stringify({ code: 100, solution: solution_result })); - }); + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + const json_data = JSON.parse(_response.data); + + let solution = json_data.solutionArticle; + if (!solution) { + return reply.error("本题没有题解"); + } + let link = URL_DISCUSS.replace("$slug", question_slug).replace("$articles_slug", articles_slug); + // let content = solution.content.replace(/\\n/g, "\n").replace(/\\t/g, "\t"); + let content = solution.content.replace(/\\n/g, "\n"); + + content = content.replace(/\\textit{/g, "{"); + content = content.replace(/\\texttt{/g, "{"); + content = content.replace(/\\text{/g, "{"); + + let solution_result: any = {}; + solution_result.problem_name = solution.title; + solution_result.title = solution.title; + solution_result.url = link; + solution_result.lang = lang; + solution_result.author = solution.author.username; + solution_result.votes = solution.voteCount; + solution_result.body = content; + solution_result.is_cn = true; + reply.info(JSON.stringify({ code: 100, solution: solution_result })); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + reply.info(JSON.stringify(sessionUtils.errors.EXPIRED)); + } else { + reply.info(JSON.stringify({ msg: response.message, statusCode: response.status })); + } + }); } function getSolutionArticlesSlugList(question_slug: string, lang: string, cb) { @@ -204,46 +231,42 @@ function getSolutionArticlesSlugList(question_slug: string, lang: string, cb) { opts.json = true; opts.body = getSolutionArticlesSlugListCNBody(question_slug, lang); - request.post(opts, function (e, _, body) { - let edges = body?.data?.questionSolutionArticles?.edges || []; - let temp_result; - edges.forEach((element) => { - if (element?.node?.slug) { - temp_result = element?.node?.slug; - return; + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + const json_data = JSON.parse(_response.data); + let edges = json_data.questionSolutionArticles?.edges || []; + let temp_result; + edges.forEach((element) => { + if (element?.node?.slug) { + temp_result = element?.node?.slug; + return; + } + }); + + cb(null, temp_result); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); } }); - - cb(e, temp_result); - }); -} - -function signOpts(opts: any, user: any) { - opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";"; - opts.headers["X-CSRFToken"] = user.sessionCSRF; - opts.headers["X-Requested-With"] = "XMLHttpRequest"; } -function makeOpts(url: any) { - let opts: any = {}; +function makeOpts(url) { + const opts: any = {}; opts.url = url; opts.headers = {}; - if (sessionUtils.isLogin()) signOpts(opts, sessionUtils.getUser()); - return opts; -} - -function checkError(e: any, resp: any, expectedStatus: any) { - if (!e && resp && resp.statusCode !== expectedStatus) { - const code = resp.statusCode; - - if (code === 403 || code === 401) { - e = sessionUtils.errors.EXPIRED; - } else { - e = { msg: "http error", statusCode: code }; - } + if (sessionUtils.isLogin()) { + let user = sessionUtils.getUser(); + opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";"; + opts.headers["X-CSRFToken"] = user.sessionCSRF; + opts.headers["X-Requested-With"] = "XMLHttpRequest"; } - return e; + return opts; } export const pluginObj: LeetCodeCn = new LeetCodeCn(); diff --git a/src/rpc/actionChain/chainNode/leetcode.ts b/src/rpc/actionChain/chainNode/leetcode.ts index ba0453c..d237fbb 100644 --- a/src/rpc/actionChain/chainNode/leetcode.ts +++ b/src/rpc/actionChain/chainNode/leetcode.ts @@ -13,7 +13,7 @@ let underscore = require("underscore"); let request = require("request"); let prompt_out = require("prompt"); -// import axios, { AxiosError, AxiosResponse } from "axios"; +import axios, { AxiosError, AxiosResponse } from "axios"; import { configUtils } from "../../utils/configUtils"; import { commUtils } from "../../utils/commUtils"; import { storageUtils } from "../../utils/storageUtils"; @@ -65,39 +65,45 @@ class LeetCode extends ChainNodeBase { getCategoryProblems = (category, cb) => { const opts = makeOpts(configUtils.sys.urls.problems.replace("$category", category)); - request(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); + axios + .get(opts.url, opts) + .then(function (_response: AxiosResponse) { + const json_data = JSON.parse(_response.data); - const json = JSON.parse(body); + if (json_data.user_name.length === 0) { + return cb(sessionUtils.errors.EXPIRED); + } - if (json.user_name.length === 0) { - return cb(sessionUtils.errors.EXPIRED); - } + const problems = json_data.stat_status_pairs + .filter((p) => !p.stat.question__hide) + .map(function (p) { + return { + state: p.status || "None", + id: p.stat.question_id, + fid: p.stat.frontend_question_id, + name: p.stat.question__title, + slug: p.stat.question__title_slug, + link: configUtils.sys.urls.problem.replace("$slug", p.stat.question__title_slug), + locked: p.paid_only, + percent: (p.stat.total_acs * 100) / p.stat.total_submitted, + level: commUtils.getNameByLevel(p.difficulty.level), + starred: p.is_favor, + category: json_data.category_slug, + }; + }); - const problems = json.stat_status_pairs - .filter((p) => !p.stat.question__hide) - .map(function (p) { - return { - state: p.status || "None", - id: p.stat.question_id, - fid: p.stat.frontend_question_id, - name: p.stat.question__title, - slug: p.stat.question__title_slug, - link: configUtils.sys.urls.problem.replace("$slug", p.stat.question__title_slug), - locked: p.paid_only, - percent: (p.stat.total_acs * 100) / p.stat.total_submitted, - level: commUtils.getNameByLevel(p.difficulty.level), - starred: p.is_favor, - category: json.category_slug, - }; - }); - - return cb(null, problems); - }); + return cb(null, problems); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; - /* A function that takes in a problem and a callback function. It then makes a request to the leetcode + /* A function that takes in a problem and a callback function. It then makes to the leetcode server to get the problem's description, test cases, and other information. */ getProblem = (problem, needTranslation, cb) => { const user = sessionUtils.getUser(); @@ -109,27 +115,34 @@ server to get the problem's description, test cases, and other information. */ opts.json = true; opts.body = getQuestionDetailBody(problem.slug); - request.post(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - - const q = body.data.question; - if (!q) return cb("failed to load problem!"); - - problem.totalAC = JSON.parse(q.stats).totalAccepted; - problem.totalSubmit = JSON.parse(q.stats).totalSubmission; - problem.likes = q.likes; - problem.dislikes = q.dislikes; - - problem.desc = q.translatedContent && needTranslation ? q.translatedContent : q.content; - - problem.templates = JSON.parse(q.codeDefinition); - problem.testcase = q.sampleTestCase; - problem.testable = q.enableRunCode; - problem.templateMeta = JSON.parse(q.metaData); - return cb(null, problem); - }); + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + const q = _response.data.data.question; + if (!q) return cb("failed to load problem!"); + + problem.totalAC = JSON.parse(q.stats).totalAccepted; + problem.totalSubmit = JSON.parse(q.stats).totalSubmission; + problem.likes = q.likes; + problem.dislikes = q.dislikes; + + problem.desc = q.translatedContent && needTranslation ? q.translatedContent : q.content; + + problem.templates = JSON.parse(q.codeDefinition); + problem.testcase = q.sampleTestCase; + problem.testable = q.enableRunCode; + problem.templateMeta = JSON.parse(q.metaData); + + return cb(null, problem); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* A function that is used to run the code on the server. */ runCode = (opts, problem, cb) => { @@ -148,24 +161,29 @@ server to get the problem's description, test cases, and other information. */ }); let that = this; - request(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - - if (body.error) { - if (!body.error.includes("too soon")) return cb(body.error); - ++opts._delay; - - const reRun = underscore.partial(that.runCode, opts, problem, cb); - return setTimeout(reRun, opts._delay * 1000); - } - - opts.json = false; - opts.body = null; + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + let json_data = JSON.parse(_response.data); + if (json_data.error) { + if (!json_data.error.includes("too soon")) { + return cb(json_data.error); + } + ++opts._delay; - return cb(null, body); - }); + const reRun = underscore.partial(that.runCode, opts, problem, cb); + return setTimeout(reRun, opts._delay * 1000); + } + return cb(null, json_data); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* A function that is used to verify the result of a task. */ @@ -175,20 +193,27 @@ server to get the problem's description, test cases, and other information. */ opts.url = configUtils.sys.urls.verify.replace("$id", task.id); let that = this; - request(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - let result = JSON.parse(body); - if (result.state === "SUCCESS") { - result = that.formatResult(result); - underscore.extendOwn(result, task); - queue.ctx.results.push(result); - } else { - queue.addTask(task); - } - return cb(); - }); + axios + .get(opts.url, opts) + .then(function (_response: AxiosResponse) { + let result = JSON.parse(_response.data); + if (result.state === "SUCCESS") { + result = that.formatResult(result); + underscore.extendOwn(result, task); + queue.ctx.results.push(result); + } else { + queue.addTask(task); + } + return cb(); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* Formatting the result of the submission. */ @@ -279,34 +304,45 @@ server to get the problem's description, test cases, and other information. */ const opts = makeOpts(configUtils.sys.urls.submissions.replace("$slug", problem.slug)); opts.headers.Referer = configUtils.sys.urls.problem.replace("$slug", problem.slug); - request(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - - // FIXME: this only return the 1st 20 submissions, we should get next if necessary. - const submissions = JSON.parse(body).submissions_dump; - for (const submission of submissions) - submission.id = underscore.last(underscore.compact(submission.url.split("/"))); - - return cb(null, submissions); - }); + axios + .get(opts.url, opts) + .then(function (_response: AxiosResponse) { + const submissions = JSON.parse(_response.data).submissions_dump; + for (const submission of submissions) + submission.id = underscore.last(underscore.compact(submission.url.split("/"))); + + return cb(null, submissions); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* Getting the submission code and the runtime distribution chart. */ getSubmission = (submission, cb) => { const opts = makeOpts(configUtils.sys.urls.submission.replace("$id", submission.id)); - request(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - - let re = body.match(/submissionCode:\s('[^']*')/); - if (re) submission.code = eval(re[1]); - - re = body.match(/runtimeDistributionFormatted:\s('[^']+')/); - if (re) submission.distributionChart = JSON.parse(eval(re[1])); - return cb(null, submission); - }); + axios + .get(opts.url, opts) + .then(function (_response: AxiosResponse) { + let re = _response.data.match(/submissionCode:\s('[^']*')/); + if (re) submission.code = eval(re[1]); + + re = _response.data.match(/runtimeDistributionFormatted:\s('[^']+')/); + if (re) submission.distributionChart = JSON.parse(eval(re[1])); + return cb(null, submission); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; /* A function that is used to star a problem. */ @@ -320,122 +356,113 @@ server to get the problem's description, test cases, and other information. */ ? getAddQuestionToFavoriteBody(user.hash, problem.id) : getRemoveQuestionFromFavoriteBody(user.hash, problem.id); // getStarProblem(user.hash, problem.id); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - request.post(opts, function (e: any, resp: any, _) { - e = checkError(e, resp, 200); - if (e) return cb(e); - return cb(null, starred); - }); + axios + .post(opts.url, opts.body, opts) + .then(function (_response: AxiosResponse) { + return cb(null, starred); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; - /* Making a request to the server to get the favorites. */ + /* Making a to the server to get the favorites. */ getFavorites = (cb: any) => { const opts = makeOpts(configUtils.sys.urls.favorites); - request(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - - const favorites = JSON.parse(body); - return cb(null, favorites); - }); + axios + .get(opts.url, opts) + .then(function (_response: AxiosResponse) { + const favorites = JSON.parse(_response.data); + return cb(null, favorites); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; - /* Making a POST request to the GraphQL API. */ + /* Making a POST to the GraphQL API. */ getUserInfo = (cb: any) => { const opts = makeOpts(configUtils.sys.urls.graphql); opts.headers.Origin = configUtils.sys.urls.base; opts.headers.Referer = configUtils.sys.urls.base; opts.json = true; opts.body = getUserInfoBody(); - request.post(opts, function (e, resp, body) { - e = checkError(e, resp, 200); - if (e) return cb(e); - const user = body.data.user; - return cb(null, user); - }); + axios + .post(opts.url, getUserInfoBody(), opts) + .then(function (_response: AxiosResponse) { + const user = JSON.parse(_response.data.user); + return cb(null, user); + }) + .catch(function (response: AxiosError) { + if (response.status == 403 || response.status == 401) { + cb(sessionUtils.errors.EXPIRED); + } else { + cb({ msg: response.message, statusCode: response.status }); + } + }); }; - /* A function that takes in a user object and a callback function. It then makes a request to the login -page and gets the csrf token. It then makes a post request to the login page with the csrf token and + /* A function that takes in a user object and a callback function. It then makes a to the login +page and gets the csrf token. It then makes a post to the login page with the csrf token and the user's login and password. If the response status code is 302, it saves the user's session id and csrf token to the user object and saves the user object to the session. */ signin = (login_info: any, cb: any) => { - // axios - // .get(configUtils.sys.urls.login) - // .then(function (response: AxiosResponse) { - // login_info.loginCSRF = commUtils.getSetCookieValue(response, "csrftoken"); - // axios - // .post( - // configUtils.sys.urls.login, - // { - // csrfmiddlewaretoken: login_info.loginCSRF, - // login: login_info.login, - // password: login_info.pass, - // }, - // { - // headers: { - // "Content-Type": "multipart/form-data", - // Origin: configUtils.sys.urls.base, - // Referer: configUtils.sys.urls.login, - // Cookie: "csrftoken=" + login_info.loginCSRF + ";", - // }, - // } - // ) - // .then(function (response: AxiosResponse) { - // //handle success - // // console.log(response); - // login_info.sessionCSRF = commUtils.getSetCookieValue(response, "csrftoken"); - // login_info.sessionId = commUtils.getSetCookieValue(response, "LEETCODE_SESSION"); - // sessionUtils.saveUser(login_info); - // return cb(null, login_info); - // }) - // .catch(function (response: AxiosError) { - // //handle error - // if (response.response?.status !== 302) return cb("invalid password?"); - // login_info.sessionCSRF = commUtils.getSetCookieValue(response, "csrftoken"); - // login_info.sessionId = commUtils.getSetCookieValue(response, "LEETCODE_SESSION"); - // sessionUtils.saveUser(login_info); - // return cb(null, login_info); - // }); - // }) - // .catch(function (error: AxiosError) { - // let error_info: any = {}; - // error_info.msg = error.message; - // if (error.response) { - // error_info.statusCode = error.response?.status; - // } - // cb(error_info); - // }); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - request(configUtils.sys.urls.login, function (e: any, resp: any, _) { - e = checkError(e, resp, 200); - if (e) return cb(e); - login_info.loginCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); - const opts = { - url: configUtils.sys.urls.login, - headers: { - Origin: configUtils.sys.urls.base, - Referer: configUtils.sys.urls.login, - Cookie: "csrftoken=" + login_info.loginCSRF + ";", - }, - form: { - csrfmiddlewaretoken: login_info.loginCSRF, - login: login_info.login, - password: login_info.pass, - }, - }; - // eslint-disable-next-line @typescript-eslint/no-unused-vars - request.post(opts, function (e: any, resp: any, _) { - if (e) return cb(e); - if (resp.statusCode !== 302) return cb("invalid password?"); - login_info.sessionCSRF = commUtils.getSetCookieValue(resp, "csrftoken"); - login_info.sessionId = commUtils.getSetCookieValue(resp, "LEETCODE_SESSION"); - sessionUtils.saveUser(login_info); - return cb(null, login_info); + axios + .get(configUtils.sys.urls.login) + .then(function (response: AxiosResponse) { + login_info.loginCSRF = commUtils.getSetCookieValue(response, "csrftoken"); + axios + .post( + configUtils.sys.urls.login, + { + csrfmiddlewaretoken: login_info.loginCSRF, + login: login_info.login, + password: login_info.pass, + }, + { + headers: { + "Content-Type": "multipart/form-data", + Origin: configUtils.sys.urls.base, + Referer: configUtils.sys.urls.login, + Cookie: "csrftoken=" + login_info.loginCSRF + ";", + }, + } + ) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .then(function (_response: AxiosResponse) { + //handle success + // console.log(response); + return cb("invalid password?"); + }) + .catch(function (response: AxiosError) { + //handle error + if (response.response?.status !== 302) { + return cb("invalid password?"); + } + login_info.sessionCSRF = commUtils.getSetCookieValue(response, "csrftoken"); + login_info.sessionId = commUtils.getSetCookieValue(response, "LEETCODE_SESSION"); + sessionUtils.saveUser(login_info); + return cb(null, login_info); + }); + }) + .catch(function (error: AxiosError) { + let error_info: any = {}; + error_info.msg = error.message; + if (error.response) { + error_info.statusCode = error.response?.status; + } + cb(error_info); }); - }); }; /* Retrieving the user's favorites and user info. */ @@ -447,12 +474,7 @@ and csrf token to the user object and saves the user object to the session. */ if (f) { user.hash = f.id_hash; user.name = favorites.user_name; - } else { - // reply.warn("Favorite not found?"); } - } else { - // return cb(e); - // reply.warn("Failed to retrieve user favorites: " + e); } that.getUserInfo(function (e, _user) { @@ -490,7 +512,7 @@ and csrf token to the user object and saves the user object to the session. */ }; /* A function that is used to login to leetcode. */ - requestLeetcodeAndSave = (request, leetcodeUrl, user, cb) => { + callLeetcodeAndSave = (request, leetcodeUrl, user, cb) => { let that = this; // eslint-disable-next-line @typescript-eslint/no-unused-vars request.get({ url: leetcodeUrl }, function (_, resp, __) { @@ -560,7 +582,7 @@ and csrf token to the user object and saves the user object to the session. */ return cb("GitHub login failed"); } if (resp.request.uri.href !== urls.github_tf_redirect) { - return that.requestLeetcodeAndSave(_request, leetcodeUrl, user, cb); + return that.callLeetcodeAndSave(_request, leetcodeUrl, user, cb); } prompt_out.colors = false; prompt_out.message = ""; @@ -596,7 +618,7 @@ and csrf token to the user object and saves the user object to the session. */ if (resp.request.uri.href === urls.github_tf_session_request) { return cb("Invalid two-factor code please check"); } - that.requestLeetcodeAndSave(_request, leetcodeUrl, user, cb); + that.callLeetcodeAndSave(_request, leetcodeUrl, user, cb); }); } ); @@ -658,68 +680,30 @@ and csrf token to the user object and saves the user object to the session. */ if (resp.statusCode !== 200) { return cb("LinkedIn login failed"); } - that.requestLeetcodeAndSave(_request, leetcodeUrl, user, cb); + that.callLeetcodeAndSave(_request, leetcodeUrl, user, cb); }); }); }; /* A function that is used to get the rating of the problems. */ getRatingOnline = (cb) => { - const _request = request.defaults({ timeout: 2000, jar: true }); - _request("https://zerotrac.github.io/leetcode_problem_rating/data.json", function (error: any, _, body: any) { - // console.log(error); - // console.log(info); - cb(error, body); - }); + axios + .get("https://zerotrac.github.io/leetcode_problem_rating/data.json", { timeout: 2000 }) + .then(function (response: AxiosResponse) { + cb(null, response.data); + }) + .catch(function (error: AxiosError) { + let error_info: any = {}; + error_info.msg = error.message; + if (error.response) { + error_info.statusCode = error.response?.status; + } + cb(error_info); + }); }; /* A function that gets the question of the day from leetcode. */ getQuestionOfToday = (cb) => { - // const opts = makeOpts(configUtils.sys.urls.graphql); - // opts.headers.Origin = configUtils.sys.urls.base; - // opts.headers.Referer = "https://leetcode.com/"; - - // opts.json = true; - // opts.body = { - // operationName: "questionOfToday", - // variables: {}, - // query: [ - // "query questionOfToday {", - // " todayRecord {", - // " date", - // " userStatus", - // " question {", - // " titleSlug", - // " questionId", - // " questionFrontendId", - // // ' content', - // // ' stats', - // // ' likes', - // // ' dislikes', - // // ' codeDefinition', - // // ' sampleTestCase', - // // ' enableRunCode', - // // ' metaData', - // // ' translatedContent', - // " __typename", - // " }", - // " __typename", - // " }", - // "}", - // ].join("\n"), - // }; - - // request.post(opts, function (e, resp, body) { - // e = checkError(e, resp, 200); - // if (e) return cb(e); - // let result: any = {}; - // result.titleSlug = body.data.todayRecord[0].question.titleSlug; - // result.questionId = body.data.todayRecord[0].question.questionId; - // result.fid = body.data.todayRecord[0].question.questionFrontendId; - // result.date = body.data.todayRecord[0].data; - // result.userStatus = body.data.todayRecord[0].userStatus; - // return cb(null, result); - // }); cb(null, {}); }; @@ -728,47 +712,6 @@ and csrf token to the user object and saves the user object to the session. */ const opts = makeOpts(configUtils.sys.urls.noj_go); opts.headers.Origin = configUtils.sys.urls.base; opts.headers.Referer = configUtils.sys.urls.u.replace("$username", username); - - // opts.json = true; - // opts.body = { - // variables: { - // userSlug: username, - // }, - // query: [ - // " query userContestRankingInfo($userSlug: String!) {", - // " userContestRanking(userSlug: $userSlug) {", - // " attendedContestsCount", - // " rating", - // " globalRanking", - // " localRanking", - // " globalTotalParticipants", - // " localTotalParticipants", - // " topPercentage", - // " }", - // // ' userContestRankingHistory(userSlug: $userSlug) {', - // // ' attended', - // // ' totalProblems', - // // ' trendingDirection', - // // ' finishTimeInSeconds', - // // ' rating', - // // ' score', - // // ' ranking', - // // ' contest {', - // // ' title', - // // ' titleCn', - // // ' startTime', - // // ' }', - // // ' }', - // " }", - // ].join("\n"), - // }; - - // request.post(opts, function (e, resp, body) { - // e = checkError(e, resp, 200); - // if (e) return cb(e); - - // return cb(null, body.data); - // }); cb(null, {}); }; @@ -795,7 +738,7 @@ and csrf token to the user object and saves the user object to the session. */ } /** - * It takes a problem object, a language, and a callback. It then makes a request to the LeetCode + * It takes a problem object, a language, and a callback. It then makes a to the LeetCode * Discuss API to get the top voted solution for that problem in that language * @param problem - the problem object * @param lang - The language of the solution. @@ -807,20 +750,20 @@ function getHelpEn(problem, lang, cb) { let URL_DISCUSSES = "https://leetcode.com/graphql"; if (lang === "python3") lang = "python"; - - let opts = { - url: URL_DISCUSSES, - json: true, - body: getGetHelpEnBody(lang, problem.id), - }; - request(opts, function (e, resp, body) { - if (e) return cb(e); - if (resp.statusCode !== 200) return cb({ msg: "http error", statusCode: resp.statusCode }); - - const solutions = body.data.questionTopicsList.edges; - const solution = solutions.length > 0 ? solutions[0].node : null; - return cb(null, solution); - }); + axios + .post(URL_DISCUSSES, { + url: URL_DISCUSSES, + json: true, + body: getGetHelpEnBody(lang, problem.id), + }) + .then(function (_response: AxiosResponse) { + const solutions = _response.data.questionTopicsList.edges; + const solution = solutions.length > 0 ? solutions[0].node : null; + return cb(null, solution); + }) + .catch(function (response: AxiosError) { + return cb({ msg: response.message, statusCode: response.status }, null); + }); } function makeOpts(url) { const opts: any = {}; @@ -828,27 +771,30 @@ function makeOpts(url) { opts.headers = {}; if (sessionUtils.isLogin()) { - signOpts(opts, sessionUtils.getUser()); + let user = sessionUtils.getUser(); + opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";"; + opts.headers["X-CSRFToken"] = user.sessionCSRF; + opts.headers["X-Requested-With"] = "XMLHttpRequest"; } return opts; } -function signOpts(opts, user) { - opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";"; - opts.headers["X-CSRFToken"] = user.sessionCSRF; - opts.headers["X-Requested-With"] = "XMLHttpRequest"; -} -function checkError(e, resp, expectedStatus) { - if (!e && resp && resp.statusCode !== expectedStatus) { - const code = resp.statusCode; - - if (code === 403 || code === 401) { - e = sessionUtils.errors.EXPIRED; - } else { - e = { msg: "http error", statusCode: code }; - } - } - return e; -} +// function signOpts(opts, user) { +// opts.headers.Cookie = "LEETCODE_SESSION=" + user.sessionId + ";csrftoken=" + user.sessionCSRF + ";"; +// opts.headers["X-CSRFToken"] = user.sessionCSRF; +// opts.headers["X-Requested-With"] = "XMLHttpRequest"; +// } +// function checkError(e, resp, expectedStatus) { +// if (!e && resp && resp.statusCode !== expectedStatus) { +// const code = resp.statusCode; + +// if (code === 403 || code === 401) { +// e = sessionUtils.errors.EXPIRED; +// } else { +// e = { msg: "http error", statusCode: code }; +// } +// } +// return e; +// } export const pluginObj: LeetCode = new LeetCode();