From 80ac93367cd2030df0715125ef9f56f4b6d84d36 Mon Sep 17 00:00:00 2001 From: Eric Liang Date: Thu, 14 Jun 2018 11:46:18 -0700 Subject: [PATCH 01/12] Add binary-search-tree tag In Company plugin, binary search tree tag is missing. --- plugins/company.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/company.js b/plugins/company.js index 711d8a6..3884ba0 100644 --- a/plugins/company.js +++ b/plugins/company.js @@ -726,6 +726,7 @@ var TAGS = { '217': ['array', 'hash-table'], '218': ['binary-indexed-tree', 'divide-and-conquer', 'heap', 'segment-tree'], '219': ['array', 'hash-table'], + '220': ['binary-search-tree'], '221': ['dynamic-programming'], '222': ['binary-search', 'tree'], '223': ['math'], @@ -817,7 +818,7 @@ var TAGS = { '312': ['divide-and-conquer', 'dynamic-programming'], '313': ['heap', 'math'], '314': ['hash-table'], - '315': ['binary-indexed-tree', 'divide-and-conquer', 'segment-tree'], + '315': ['binary-indexed-tree', 'divide-and-conquer', 'segment-tree', 'binary-search-tree'], '316': ['greedy', 'stack'], '317': ['breadth-first-search'], '318': ['bit-manipulation'], @@ -829,7 +830,7 @@ var TAGS = { '324': ['sort'], '325': ['hash-table'], '326': ['math'], - '327': ['divide-and-conquer'], + '327': ['divide-and-conquer', 'binary-search-tree'], '328': ['linked-list'], '329': ['depth-first-search', 'topological-sort'], '330': ['greedy'], @@ -853,6 +854,7 @@ var TAGS = { '349': ['binary-search', 'hash-table', 'sort', 'two-pointers'], '350': ['binary-search', 'hash-table', 'sort', 'two-pointers'], '351': ['backtracking', 'dynamic-programming'], + '352': ['binary-search-tree'], '353': ['design', 'queue'], '354': ['binary-search', 'dynamic-programming'], '355': ['design', 'hash-table', 'heap'], @@ -963,7 +965,7 @@ var TAGS = { '488': ['depth-first-search'], '490': ['breadth-first-search', 'depth-first-search'], '491': ['depth-first-search'], - '493': ['binary-indexed-tree', 'divide-and-conquer', 'segment-tree'], + '493': ['binary-indexed-tree', 'divide-and-conquer', 'segment-tree', 'binary-search-tree'], '494': ['depth-first-search', 'dynamic-programming'], '495': ['array'], '496': ['stack'], @@ -989,6 +991,7 @@ var TAGS = { '526': ['backtracking'], '527': ['sort', 'string'], '529': ['breadth-first-search', 'depth-first-search'], + '530': ['array', 'depth-first-search', 'binary-search-tree'], '531': ['array', 'depth-first-search'], '532': ['array', 'two-pointers'], '533': ['array', 'depth-first-search'], @@ -1102,7 +1105,7 @@ var TAGS = { '680': ['string'], '681': ['string'], '682': ['stack'], - '683': ['array'], + '683': ['array', 'binary-search-tree'], '684': ['graph', 'tree', 'union-find'], '685': ['depth-first-search', 'graph', 'tree', 'union-find'], '686': ['string'], @@ -1118,12 +1121,12 @@ var TAGS = { '696': ['string'], '697': ['array'], '698': ['dynamic-programming'], - '699': ['segment-tree'], + '699': ['segment-tree', 'binary-search-tree'], '711': ['depth-first-search', 'hash-table'], '712': ['dynamic-programming'], '713': ['array', 'two-pointers'], '714': ['array', 'dynamic-programming', 'greedy'], - '715': ['array', 'segment-tree'], + '715': ['array', 'segment-tree', 'binary-search-tree'], '716': ['design'], '717': ['array'], '718': ['array', 'binary-search', 'dynamic-programming', 'hash-table'], @@ -1139,8 +1142,8 @@ var TAGS = { '728': ['math'], '729': ['array'], '730': ['dynamic-programming', 'string'], - '731': ['array'], - '732': ['segment-tree'], + '731': ['array', 'binary-search-tree'], + '732': ['segment-tree', 'binary-search-tree'], '733': ['depth-first-search'], '734': ['hash-table'], '735': ['stack'], From babbdf608450da7db38fcbaca1b6baf1a2555909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=A9=E5=AD=90?= Date: Thu, 9 Aug 2018 10:18:51 +0800 Subject: [PATCH 02/12] Fix leetcode-cn urls It seems the leetcode-cn plugin need one more url replaced for working well. That is config.sys.urls.problem_detail --- plugins/leetcode.cn.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/leetcode.cn.js b/plugins/leetcode.cn.js index 30c7167..8db8dfc 100644 --- a/plugins/leetcode.cn.js +++ b/plugins/leetcode.cn.js @@ -15,6 +15,7 @@ plugin.init = function() { config.sys.urls.problems = 'https://leetcode-cn.com/api/problems/$category/'; config.sys.urls.problem = 'https://leetcode-cn.com/problems/$slug/description/'; config.sys.urls.graphql = 'https://leetcode-cn.com/graphql'; + config.sys.urls.problem_detail = 'https://leetcode.com/graphql'; config.sys.urls.test = 'https://leetcode-cn.com/problems/$slug/interpret_solution/'; config.sys.urls.session = 'https://leetcode-cn.com/session/'; config.sys.urls.submit = 'https://leetcode-cn.com/problems/$slug/submit/'; From 6ef569dcf78d4eb1375a40b65bb4f14494d19954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=A9=E5=AD=90?= Date: Thu, 9 Aug 2018 10:22:04 +0800 Subject: [PATCH 03/12] Fix url Fix url for leetcode-cn --- plugins/leetcode.cn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/leetcode.cn.js b/plugins/leetcode.cn.js index 8db8dfc..53d79ce 100644 --- a/plugins/leetcode.cn.js +++ b/plugins/leetcode.cn.js @@ -15,7 +15,7 @@ plugin.init = function() { config.sys.urls.problems = 'https://leetcode-cn.com/api/problems/$category/'; config.sys.urls.problem = 'https://leetcode-cn.com/problems/$slug/description/'; config.sys.urls.graphql = 'https://leetcode-cn.com/graphql'; - config.sys.urls.problem_detail = 'https://leetcode.com/graphql'; + config.sys.urls.problem_detail = 'https://leetcode-cn.com/graphql'; config.sys.urls.test = 'https://leetcode-cn.com/problems/$slug/interpret_solution/'; config.sys.urls.session = 'https://leetcode-cn.com/session/'; config.sys.urls.submit = 'https://leetcode-cn.com/problems/$slug/submit/'; From 5ef609e75e3f19451d83ccd61e70b669d972e640 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sun, 28 Oct 2018 11:38:09 +0800 Subject: [PATCH 04/12] move plugins' specific data into separate dirs. * see https://github.com/skygragon/leetcode-cli/commit/b72d4d69fe6b3279d3f40f00bb836696139a2fcc Signed-off-by: Eric Wang --- plugins/leetcode.cn.js | 3 ++- plugins/lintcode.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/leetcode.cn.js b/plugins/leetcode.cn.js index 53d79ce..9489d61 100644 --- a/plugins/leetcode.cn.js +++ b/plugins/leetcode.cn.js @@ -5,11 +5,12 @@ var Plugin = require('../plugin'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/leetcode.cn.md // -var plugin = new Plugin(15, 'leetcode.cn', '2018.05.30', +var plugin = new Plugin(15, 'leetcode.cn', '2018.10.28', 'Plugin to talk with leetcode-cn APIs.'); plugin.init = function() { const config = require('../config'); + config.app = 'leetcode.cn'; config.sys.urls.base = 'https://leetcode-cn.com'; config.sys.urls.login = 'https://leetcode-cn.com/accounts/login/'; config.sys.urls.problems = 'https://leetcode-cn.com/api/problems/$category/'; diff --git a/plugins/lintcode.js b/plugins/lintcode.js index 5e92278..89be320 100644 --- a/plugins/lintcode.js +++ b/plugins/lintcode.js @@ -19,7 +19,7 @@ var session = require('../session'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/lintcode.md // -const plugin = new Plugin(15, 'lintcode', '2018.05.30', +const plugin = new Plugin(15, 'lintcode', '2018.10.28', 'Plugin to talk with lintcode APIs.'); // FIXME: add more langs @@ -83,6 +83,7 @@ function _strip(s) { } plugin.init = function() { + config.app = 'lintcode'; config.sys.urls.base = 'https://www.lintcode.com'; config.sys.urls.problems = 'https://www.lintcode.com/api/problems/?page=$page'; config.sys.urls.problem = 'https://www.lintcode.com/problem/$slug/description'; From e8fda163ca9770ab0c7f0981dd634b7e5f10f20f Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sun, 18 Nov 2018 10:51:26 +0800 Subject: [PATCH 05/12] [refactor] keep pace with leetcode-cli 2.5.4 Signed-off-by: Eric Wang --- plugins/github.js | 3 ++- plugins/lintcode.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/github.js b/plugins/github.js index 4c00e75..b0f8241 100644 --- a/plugins/github.js +++ b/plugins/github.js @@ -2,6 +2,7 @@ var path = require('path'); var url = require('url'); var h = require('../helper'); +var file = require('../file'); var log = require('../log'); var Plugin = require('../plugin'); @@ -47,7 +48,7 @@ plugin.submitProblem = function(problem, cb) { } ctx.message = 'update ' + filename; - ctx.content = new Buffer(h.getFileData(problem.file)).toString('base64'); + ctx.content = new Buffer(file.data(problem.file)).toString('base64'); var onFileDone = function(e, res) { if (e) diff --git a/plugins/lintcode.js b/plugins/lintcode.js index 89be320..88c7e3c 100644 --- a/plugins/lintcode.js +++ b/plugins/lintcode.js @@ -4,6 +4,7 @@ var request = require('request'); var util = require('util'); var h = require('../helper'); +var file = require('../file'); var config = require('../config'); var log = require('../log'); var Plugin = require('../plugin'); @@ -218,7 +219,7 @@ function runCode(problem, isTest, cb) { opts.headers.referer = problem.link; opts.form = { problem_id: problem.id, - code: h.getFileData(problem.file), + code: file.data(problem.file), language: lang.text }; if (isTest) { From 23f7fdba0d37b1997a2ecef2c636968cb75c77fe Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sun, 18 Nov 2018 23:41:14 +0800 Subject: [PATCH 06/12] tiny update. Signed-off-by: Eric Wang --- plugins/cookie.chrome.js | 5 +++-- plugins/github.js | 2 +- plugins/leetcode.cn.js | 4 ++-- plugins/lintcode.js | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/cookie.chrome.js b/plugins/cookie.chrome.js index 13f28f4..0291144 100644 --- a/plugins/cookie.chrome.js +++ b/plugins/cookie.chrome.js @@ -9,7 +9,7 @@ var session = require('../session'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/cookie.chrome.md // -var plugin = new Plugin(13, 'cookie.chrome', '2018.05.30', +var plugin = new Plugin(13, 'cookie.chrome', '2018.11.18', 'Plugin to reuse Chrome\'s leetcode cookie.', ['ffi:win32', 'keytar:darwin', 'ref:win32', 'ref-struct:win32', 'sqlite3']); @@ -18,7 +18,7 @@ plugin.help = function() { case 'darwin': break; case 'linux': - log.info('To complete the install: sudo apt install libsecret-tools'); + log.warn('To complete the install: sudo apt install libsecret-tools'); break; case 'win32': break; @@ -131,6 +131,7 @@ function doDecode(key, queue, cb) { Chrome.getCookies = function(cb) { var sqlite3 = require('sqlite3'); var db = new sqlite3.Database(my.getDBPath()); + db.on('error', cb); var KEYS = ['csrftoken', 'LEETCODE_SESSION']; db.serialize(function() { diff --git a/plugins/github.js b/plugins/github.js index b0f8241..6c94e9e 100644 --- a/plugins/github.js +++ b/plugins/github.js @@ -11,7 +11,7 @@ var Plugin = require('../plugin'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/github.md // -var plugin = new Plugin(100, 'github', '2018.03.24', +var plugin = new Plugin(100, 'github', '2018.11.18', 'Plugin to commit accepted code to your own github repo.', ['github@13']); diff --git a/plugins/leetcode.cn.js b/plugins/leetcode.cn.js index 9489d61..c9b1aef 100644 --- a/plugins/leetcode.cn.js +++ b/plugins/leetcode.cn.js @@ -1,3 +1,4 @@ +var config = require('../config'); var Plugin = require('../plugin'); // @@ -5,11 +6,10 @@ var Plugin = require('../plugin'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/leetcode.cn.md // -var plugin = new Plugin(15, 'leetcode.cn', '2018.10.28', +var plugin = new Plugin(15, 'leetcode.cn', '2018.11.18', 'Plugin to talk with leetcode-cn APIs.'); plugin.init = function() { - const config = require('../config'); config.app = 'leetcode.cn'; config.sys.urls.base = 'https://leetcode-cn.com'; config.sys.urls.login = 'https://leetcode-cn.com/accounts/login/'; diff --git a/plugins/lintcode.js b/plugins/lintcode.js index 88c7e3c..18b5c9d 100644 --- a/plugins/lintcode.js +++ b/plugins/lintcode.js @@ -20,7 +20,7 @@ var session = require('../session'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/lintcode.md // -const plugin = new Plugin(15, 'lintcode', '2018.10.28', +const plugin = new Plugin(15, 'lintcode', '2018.11.18', 'Plugin to talk with lintcode APIs.'); // FIXME: add more langs From aeb680a7d89ce74a039ce89cbaa3f9ff2ee4fbb7 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Mon, 19 Nov 2018 14:00:28 +0800 Subject: [PATCH 07/12] [cookie.firefox] fail on invalid cookies. Signed-off-by: Eric Wang --- plugins/cookie.firefox.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/cookie.firefox.js b/plugins/cookie.firefox.js index 45d8645..de2db29 100644 --- a/plugins/cookie.firefox.js +++ b/plugins/cookie.firefox.js @@ -6,7 +6,7 @@ var session = require('../session'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/cookie.firefox.md // -var plugin = new Plugin(13, 'cookie.firefox', '2017.12.28', +var plugin = new Plugin(13, 'cookie.firefox', '2018.11.19', 'Plugin to reuse firefox\'s leetcode cookie.', ['glob', 'sqlite3']); @@ -55,7 +55,12 @@ plugin.signin = function(user, cb) { log.debug('try to copy leetcode cookies from firefox ...'); getCookies(function(e, cookies) { if (e) { - log.error('failed to copy cookies: ' + e); + log.error('Failed to copy cookies: ' + e); + return plugin.next.signin(user, cb); + } + + if (!cookies.LEETCODE_SESSION || !cookies.csrftoken) { + log.error('Got invalid cookies: ' + JSON.stringify(cookies)); return plugin.next.signin(user, cb); } From 65cbe605aa704394dc52c385c166b6e7eadb1057 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sat, 24 Nov 2018 22:27:40 +0800 Subject: [PATCH 08/12] fixes eslint errors. Signed-off-by: Eric Wang --- .eslintrc.js | 29 ++++++++++++++++++++++++----- package.json | 4 ++-- plugins/company.js | 4 ++++ plugins/cookie.chrome.js | 6 +++--- plugins/cookie.firefox.js | 2 +- plugins/lintcode.js | 10 +++++----- plugins/solution.discuss.js | 6 +++--- 7 files changed, 42 insertions(+), 19 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f274110..0c40bef 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,17 +1,36 @@ module.exports = { "env": { "browser": false, - "node": true, - "es6": true + "es6": true, + "mocha": true, + "node": true }, - "extends": "google", + "extends": [ + "google", + "eslint:recommended" + ], "rules": { + "block-spacing": [2, "always"], + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "camelcase": [2, {properties: "never"}], "comma-dangle": 0, "curly": 0, "key-spacing": [2, {align: "value"}], - "max-len": [1, 120], + "max-len": [1, 150], + "no-console": 1, + "no-empty": [2, { "allowEmptyCatch": true }], + "no-eval": 1, // we use it on purpose + "no-loop-func": 1, + "no-multi-spaces": 0, + "no-proto": 1, + "no-unused-expressions": 1, + "no-unused-vars": 1, "no-var": 0, + "no-warning-comments": 0, + "prefer-rest-params": 0, + "prefer-spread": 0, + "quote-props": 1, "quotes": [2, "single", {avoidEscape: true}], - "require-jsdoc": 0 + "require-jsdoc": 0, } }; diff --git a/package.json b/package.json index 99fca68..4ea4b95 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ }, "homepage": "https://github.com/skygragon/leetcode-cli-plugins#readme", "devDependencies": { - "eslint": "^4.4.1", - "eslint-config-google": "^0.9.1" + "eslint": "5.9.0", + "eslint-config-google": "0.11.0" } } diff --git a/plugins/company.js b/plugins/company.js index 3884ba0..ac48974 100644 --- a/plugins/company.js +++ b/plugins/company.js @@ -21,6 +21,7 @@ var COMPONIES = { '5': ['amazon', 'bloomberg', 'microsoft'], '7': ['apple', 'bloomberg'], '8': ['amazon', 'bloomberg', 'microsoft', 'uber'], + '10': ['airbnb', 'facebook', 'google', 'twitter', 'uber'], '11': ['bloomberg'], '12': ['twitter'], @@ -84,6 +85,7 @@ var COMPONIES = { '94': ['microsoft'], '96': ['snapchat'], '98': ['amazon', 'bloomberg', 'facebook', 'microsoft'], + '100': ['bloomberg'], '101': ['bloomberg', 'linkedin', 'microsoft'], '102': ['amazon', 'apple', 'bloomberg', 'facebook', 'linkedin', 'microsoft'], @@ -532,6 +534,7 @@ var TAGS = { '7': ['math'], '8': ['math', 'string'], '9': ['math'], + '10': ['backtracking', 'dynamic-programming', 'string'], '11': ['array', 'two-pointers'], '12': ['math', 'string'], @@ -622,6 +625,7 @@ var TAGS = { '97': ['dynamic-programming', 'string'], '98': ['depth-first-search', 'tree'], '99': ['depth-first-search', 'tree'], + '100': ['depth-first-search', 'tree'], '101': ['breadth-first-search', 'depth-first-search', 'tree'], '102': ['breadth-first-search', 'tree'], diff --git a/plugins/cookie.chrome.js b/plugins/cookie.chrome.js index 0291144..e2d4278 100644 --- a/plugins/cookie.chrome.js +++ b/plugins/cookie.chrome.js @@ -28,7 +28,7 @@ plugin.help = function() { var Chrome = {}; var ChromeMAC = { - getDBPath: function() { + getDBPath: function() { return `${process.env.HOME}/Library/Application Support/Google/Chrome/${this.profile}/Cookies`; }, iterations: 1003, @@ -39,7 +39,7 @@ var ChromeMAC = { }; var ChromeLinux = { - getDBPath: function() { + getDBPath: function() { return `${process.env.HOME}/.config/google-chrome/${this.profile}/Cookies`; }, iterations: 1, @@ -52,7 +52,7 @@ var ChromeLinux = { }; var ChromeWindows = { - getDBPath: function() { + getDBPath: function() { return path.resolve(process.env.APPDATA || '', `../Local/Google/Chrome/User Data/${this.profile}/Cookies`); }, getPassword: function(cb) { cb(); } diff --git a/plugins/cookie.firefox.js b/plugins/cookie.firefox.js index de2db29..f69f869 100644 --- a/plugins/cookie.firefox.js +++ b/plugins/cookie.firefox.js @@ -48,7 +48,7 @@ function getCookies(cb) { }); }); }); -}; +} plugin.signin = function(user, cb) { log.debug('running cookie.firefox.signin'); diff --git a/plugins/lintcode.js b/plugins/lintcode.js index 18b5c9d..073d12d 100644 --- a/plugins/lintcode.js +++ b/plugins/lintcode.js @@ -218,9 +218,9 @@ function runCode(problem, isTest, cb) { const opts = makeOpts(config.sys.urls.test); opts.headers.referer = problem.link; opts.form = { - problem_id: problem.id, - code: file.data(problem.file), - language: lang.text + problem_id: problem.id, + code: file.data(problem.file), + language: lang.text }; if (isTest) { opts.form.input = problem.testcase; @@ -330,8 +330,8 @@ plugin.login = function(user, cb) { 'x-csrftoken': null }, form: { - username_or_email: user.login, - password: user.pass + username_or_email: user.login, + password: user.pass } }; diff --git a/plugins/solution.discuss.js b/plugins/solution.discuss.js index 1289a13..c155637 100644 --- a/plugins/solution.discuss.js +++ b/plugins/solution.discuss.js @@ -1,5 +1,4 @@ var _ = require('underscore'); -var cheerio = require('cheerio'); var request = require('request'); var log = require('../log'); @@ -24,7 +23,7 @@ function getSolution(problem, lang, cb) { var opts = { url: URL_DISCUSSES, json: true, - qs: { + qs: { query: [ 'query fetchTopics($questionId: Int!, $pageNo: Int!, $orderBy: String!) {', ' questionTopics(questionId: $questionId, pageNo: $pageNo, orderBy: $orderBy) {', @@ -42,8 +41,9 @@ function getSolution(problem, lang, cb) { ' }', '}' ].join('\n'), + operationName: 'fetchTopics', - variables: JSON.stringify({ + variables: JSON.stringify({ pageNo: 1, orderBy: 'most_votes', questionId: problem.id From 9de04127984e08d7d52dc0545c03291d2a69fc97 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sat, 24 Nov 2018 22:33:01 +0800 Subject: [PATCH 09/12] enable travis Signed-off-by: Eric Wang --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a6f5aa8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: node_js +node_js: + - 10 +os: + - linux +install: + - npm install +script: + - npm test From 6a33c98b09cc6a2332b42df3186cb1f80febb845 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sun, 25 Nov 2018 22:19:05 +0800 Subject: [PATCH 10/12] refs #22: show chinese question name. Signed-off-by: Eric Wang --- plugins/leetcode.cn.js | 98 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/plugins/leetcode.cn.js b/plugins/leetcode.cn.js index c9b1aef..07d5d2d 100644 --- a/plugins/leetcode.cn.js +++ b/plugins/leetcode.cn.js @@ -1,12 +1,18 @@ +'use strict' +var request = require('request'); + var config = require('../config'); +var h = require('../helper'); +var log = require('../log'); var Plugin = require('../plugin'); +var session = require('../session'); // // [Usage] // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/leetcode.cn.md // -var plugin = new Plugin(15, 'leetcode.cn', '2018.11.18', +var plugin = new Plugin(15, 'leetcode.cn', '2018.11.25', 'Plugin to talk with leetcode-cn APIs.'); plugin.init = function() { @@ -27,4 +33,94 @@ plugin.init = function() { config.sys.urls.favorite_delete = 'https://leetcode-cn.com/list/api/questions/$hash/$id'; }; +// FIXME: refactor those +// update options with user credentials +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 makeOpts(url) { + const opts = {}; + opts.url = url; + opts.headers = {}; + + if (session.isLogin()) + signOpts(opts, session.getUser()); + return opts; +} + +function checkError(e, resp, expectedStatus) { + if (!e && resp && resp.statusCode !== expectedStatus) { + const code = resp.statusCode; + log.debug('http error: ' + code); + + if (code === 403 || code === 401) { + e = session.errors.EXPIRED; + } else { + e = {msg: 'http error', statusCode: code}; + } + } + return e; +} + +plugin.getProblems = function(cb) { + plugin.next.getProblems(function(e, problems) { + if (e) return cb(e); + + plugin.getProblemsTitle(function(e, titles) { + if (e) return cb(e); + + problems.forEach(function(problem) { + const title = titles[problem.fid]; + if (title) + problem.name = title; + }); + + return cb(null, problems); + }); + }); +}; + +plugin.getProblemsTitle = function(cb) { + log.debug('running leetcode.cn.getProblemNames'); + + const opts = makeOpts(config.sys.urls.graphql); + opts.headers.Origin = config.sys.urls.base; + opts.headers.Referer = 'https://leetcode-cn.com/api/problems/algorithms/'; + + opts.json = true; + opts.body = { + query: [ + 'query getQuestionTranslation($lang: String) {', + ' translations: allAppliedQuestionTranslations(lang: $lang) {', + ' title', + ' question {', + ' questionId', + ' }', + ' }', + '}', + '' + ].join('\n'), + variables: {}, + operationName: 'getQuestionTranslation' + }; + + const spin = h.spin('Downloading questions titles'); + request.post(opts, function(e, resp, body) { + spin.stop(); + e = checkError(e, resp, 200); + if (e) return cb(e); + + const titles = []; + body.data.translations.forEach(function(x) { + titles[x.question.questionId] = x.title; + }); + + return cb(null, titles); + }); +}; + module.exports = plugin; From e0b4613c842f69a04bcf84e836d929f8ba774e5d Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sun, 3 Feb 2019 12:27:53 +0800 Subject: [PATCH 11/12] fixes #28: [solution] fixes 400 error Signed-off-by: Eric Wang --- plugins/solution.discuss.js | 46 +++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/plugins/solution.discuss.js b/plugins/solution.discuss.js index c155637..b3a9a13 100644 --- a/plugins/solution.discuss.js +++ b/plugins/solution.discuss.js @@ -11,7 +11,7 @@ var session = require('../session'); // // https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/solution.discuss.md // -var plugin = new Plugin(200, 'solution.discuss', '2018.04.14', +var plugin = new Plugin(200, 'solution.discuss', '2019.02.03', 'Plugin to fetch most voted solution in discussions.'); var URL_DISCUSSES = 'https://leetcode.com/graphql'; @@ -20,14 +20,22 @@ var URL_DISCUSS = 'https://leetcode.com/problems/$slug/discuss/$id'; function getSolution(problem, lang, cb) { if (!problem) return cb(); + if (lang === 'python3') lang = 'python'; + var opts = { url: URL_DISCUSSES, json: true, - qs: { + body: { query: [ - 'query fetchTopics($questionId: Int!, $pageNo: Int!, $orderBy: String!) {', - ' questionTopics(questionId: $questionId, pageNo: $pageNo, orderBy: $orderBy) {', - ' data {', + '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 {', @@ -42,11 +50,14 @@ function getSolution(problem, lang, cb) { '}' ].join('\n'), - operationName: 'fetchTopics', + operationName: 'questionTopicsList', variables: JSON.stringify({ - pageNo: 1, + query: '', + first: 1, + skip: 0, orderBy: 'most_votes', - questionId: problem.id + questionId: '' + problem.id, + tags: [lang] }) } }; @@ -55,23 +66,8 @@ function getSolution(problem, lang, cb) { if (resp.statusCode !== 200) return cb({msg: 'http error', statusCode: resp.statusCode}); - var langs = [lang]; - // try to find more compatible langs - if (lang === 'cpp') langs.push('c++'); - if (lang === 'csharp') langs.push('c#'); - if (lang === 'golang') langs.push('go'); - if (lang === 'javascript') langs.push('js'); - if (lang === 'python3') langs.push('python'); - - var solutions = body.data.questionTopics.data; - var solution = _.find(solutions, function(x) { - var keys = x.title.toLowerCase().split(/[^\w+]/); - for (var i = 0; i < keys.length; ++i) { - if (langs.indexOf(keys[i]) >= 0) return true; - } - return false; - }); - + const solutions = body.data.questionTopicsList.edges; + const solution = solutions.length > 0 ? solutions[0].node : null; return cb(null, solution); }); } From 752e94e8a755106106af65af9d9b831d9810c4cd Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Sun, 3 Feb 2019 12:39:39 +0800 Subject: [PATCH 12/12] fixes ut error Signed-off-by: Eric Wang --- plugins/solution.discuss.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/solution.discuss.js b/plugins/solution.discuss.js index b3a9a13..e78b90a 100644 --- a/plugins/solution.discuss.js +++ b/plugins/solution.discuss.js @@ -1,4 +1,3 @@ -var _ = require('underscore'); var request = require('request'); var log = require('../log'); @@ -25,7 +24,7 @@ function getSolution(problem, lang, cb) { var opts = { url: URL_DISCUSSES, json: true, - body: { + 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) {',