1+ 'use strict'
2+ var request = require ( 'request' ) ;
3+
14var config = require ( '../config' ) ;
5+ var h = require ( '../helper' ) ;
6+ var log = require ( '../log' ) ;
27var Plugin = require ( '../plugin' ) ;
8+ var session = require ( '../session' ) ;
39
410//
511// [Usage]
612//
713// https://github.com/skygragon/leetcode-cli-plugins/blob/master/docs/leetcode.cn.md
814//
9- var plugin = new Plugin ( 15 , 'leetcode.cn' , '2018.11.18 ' ,
15+ var plugin = new Plugin ( 15 , 'leetcode.cn' , '2018.11.25 ' ,
1016 'Plugin to talk with leetcode-cn APIs.' ) ;
1117
1218plugin . init = function ( ) {
@@ -27,4 +33,94 @@ plugin.init = function() {
2733 config . sys . urls . favorite_delete = 'https://leetcode-cn.com/list/api/questions/$hash/$id' ;
2834} ;
2935
36+ // FIXME: refactor those
37+ // update options with user credentials
38+ function signOpts ( opts , user ) {
39+ opts . headers . Cookie = 'LEETCODE_SESSION=' + user . sessionId +
40+ ';csrftoken=' + user . sessionCSRF + ';' ;
41+ opts . headers [ 'X-CSRFToken' ] = user . sessionCSRF ;
42+ opts . headers [ 'X-Requested-With' ] = 'XMLHttpRequest' ;
43+ }
44+
45+ function makeOpts ( url ) {
46+ const opts = { } ;
47+ opts . url = url ;
48+ opts . headers = { } ;
49+
50+ if ( session . isLogin ( ) )
51+ signOpts ( opts , session . getUser ( ) ) ;
52+ return opts ;
53+ }
54+
55+ function checkError ( e , resp , expectedStatus ) {
56+ if ( ! e && resp && resp . statusCode !== expectedStatus ) {
57+ const code = resp . statusCode ;
58+ log . debug ( 'http error: ' + code ) ;
59+
60+ if ( code === 403 || code === 401 ) {
61+ e = session . errors . EXPIRED ;
62+ } else {
63+ e = { msg : 'http error' , statusCode : code } ;
64+ }
65+ }
66+ return e ;
67+ }
68+
69+ plugin . getProblems = function ( cb ) {
70+ plugin . next . getProblems ( function ( e , problems ) {
71+ if ( e ) return cb ( e ) ;
72+
73+ plugin . getProblemsTitle ( function ( e , titles ) {
74+ if ( e ) return cb ( e ) ;
75+
76+ problems . forEach ( function ( problem ) {
77+ const title = titles [ problem . fid ] ;
78+ if ( title )
79+ problem . name = title ;
80+ } ) ;
81+
82+ return cb ( null , problems ) ;
83+ } ) ;
84+ } ) ;
85+ } ;
86+
87+ plugin . getProblemsTitle = function ( cb ) {
88+ log . debug ( 'running leetcode.cn.getProblemNames' ) ;
89+
90+ const opts = makeOpts ( config . sys . urls . graphql ) ;
91+ opts . headers . Origin = config . sys . urls . base ;
92+ opts . headers . Referer = 'https://leetcode-cn.com/api/problems/algorithms/' ;
93+
94+ opts . json = true ;
95+ opts . body = {
96+ query : [
97+ 'query getQuestionTranslation($lang: String) {' ,
98+ ' translations: allAppliedQuestionTranslations(lang: $lang) {' ,
99+ ' title' ,
100+ ' question {' ,
101+ ' questionId' ,
102+ ' }' ,
103+ ' }' ,
104+ '}' ,
105+ ''
106+ ] . join ( '\n' ) ,
107+ variables : { } ,
108+ operationName : 'getQuestionTranslation'
109+ } ;
110+
111+ const spin = h . spin ( 'Downloading questions titles' ) ;
112+ request . post ( opts , function ( e , resp , body ) {
113+ spin . stop ( ) ;
114+ e = checkError ( e , resp , 200 ) ;
115+ if ( e ) return cb ( e ) ;
116+
117+ const titles = [ ] ;
118+ body . data . translations . forEach ( function ( x ) {
119+ titles [ x . question . questionId ] = x . title ;
120+ } ) ;
121+
122+ return cb ( null , titles ) ;
123+ } ) ;
124+ } ;
125+
30126module . exports = plugin ;
0 commit comments