@@ -6,7 +6,7 @@ import { EventEmitter } from "events";
6
6
import * as vscode from "vscode" ;
7
7
import { leetCodeChannel } from "./leetCodeChannel" ;
8
8
import { leetCodeExecutor } from "./leetCodeExecutor" ;
9
- import { UserStatus } from "./shared" ;
9
+ import { IQuickItemEx , loginArgsMapping , UserStatus } from "./shared" ;
10
10
import { createEnvOption } from "./utils/cpUtils" ;
11
11
import { DialogType , promptForOpenOutputChannel } from "./utils/uiUtils" ;
12
12
import * as wsl from "./utils/wslUtils" ;
@@ -34,14 +34,43 @@ class LeetCodeManager extends EventEmitter {
34
34
}
35
35
}
36
36
37
- public async signIn ( isByCookie : boolean = false ) : Promise < void > {
38
- const loginArg : string = "-l" ;
39
- const cookieArg : string = "-c" ;
40
- const commandArg : string = isByCookie ? cookieArg : loginArg ;
37
+ public async signIn ( ) : Promise < void > {
38
+ const picks : Array < IQuickItemEx < string > > = [ ] ;
39
+ picks . push (
40
+ {
41
+ label : "LeetCode Account" ,
42
+ detail : "Use LeetCode account to login" ,
43
+ value : "LeetCode" ,
44
+ } ,
45
+ {
46
+ label : "LeetCode Cookie" ,
47
+ detail : "Use LeetCode cookie copied from browser to login" ,
48
+ value : "Cookie" ,
49
+ } ,
50
+ {
51
+ label : "Third-Party: GitHub" ,
52
+ detail : "Use GitHub account to login" ,
53
+ value : "GitHub" ,
54
+ } ,
55
+ {
56
+ label : "Third-Party: LinkedIn" ,
57
+ detail : "Use LinkedIn account to login" ,
58
+ value : "LinkedIn" ,
59
+ } ,
60
+ ) ;
61
+ const choice : IQuickItemEx < string > | undefined = await vscode . window . showQuickPick ( picks ) ;
62
+ if ( ! choice ) {
63
+ return ;
64
+ }
65
+ const loginMethod : string = choice . value ;
66
+ const commandArg : string | undefined = loginArgsMapping . get ( loginMethod ) ;
67
+ if ( ! commandArg ) {
68
+ throw new Error ( `The login method "${ loginMethod } " is not supported.` ) ;
69
+ }
70
+ const isByCookie : boolean = loginMethod === "Cookie" ;
41
71
const inMessage : string = isByCookie ? "sign in by cookie" : "sign in" ;
42
72
try {
43
73
const userName : string | undefined = await new Promise ( async ( resolve : ( res : string | undefined ) => void , reject : ( e : Error ) => void ) : Promise < void > => {
44
- let result : string = "" ;
45
74
46
75
const leetCodeBinaryPath : string = await leetCodeExecutor . getLeetCodeBinaryPath ( ) ;
47
76
@@ -52,10 +81,27 @@ class LeetCodeManager extends EventEmitter {
52
81
env : createEnvOption ( ) ,
53
82
} ) ;
54
83
55
- childProc . stdout . on ( "data" , ( data : string | Buffer ) => {
84
+ childProc . stdout . on ( "data" , async ( data : string | Buffer ) => {
56
85
data = data . toString ( ) ;
57
- result = result . concat ( data ) ;
58
86
leetCodeChannel . append ( data ) ;
87
+ if ( data . includes ( "twoFactorCode" ) ) {
88
+ const twoFactor : string | undefined = await vscode . window . showInputBox ( {
89
+ prompt : "Enter two-factor code." ,
90
+ validateInput : ( s : string ) : string | undefined => s && s . trim ( ) ? undefined : "The input must not be empty" ,
91
+ } ) ;
92
+ if ( ! twoFactor ) {
93
+ childProc . kill ( ) ;
94
+ return resolve ( undefined ) ;
95
+ }
96
+ childProc . stdin . write ( `${ twoFactor } \n` ) ;
97
+ childProc . stdin . end ( ) ;
98
+ } else {
99
+ const match : RegExpMatchArray | null = data . match ( / (?: .* ) S u c c e s s f u l l y .* l o g i n a s ( .* ) / i) ;
100
+ if ( match && match [ 1 ] ) {
101
+ childProc . stdin . end ( ) ;
102
+ return resolve ( match [ 1 ] ) ;
103
+ }
104
+ }
59
105
} ) ;
60
106
61
107
childProc . stderr . on ( "data" , ( data : string | Buffer ) => leetCodeChannel . append ( data . toString ( ) ) ) ;
@@ -80,13 +126,9 @@ class LeetCodeManager extends EventEmitter {
80
126
return resolve ( undefined ) ;
81
127
}
82
128
childProc . stdin . write ( `${ pwd } \n` ) ;
83
- childProc . stdin . end ( ) ;
84
- childProc . on ( "close" , ( ) => {
85
- const match : RegExpMatchArray | null = result . match ( / (?: .* ) S u c c e s s f u l l y ( l o g i n | c o o k i e l o g i n ) a s ( .* ) / i) ;
86
- if ( match && match [ 2 ] ) {
87
- resolve ( match [ 2 ] ) ;
88
- } else {
89
- reject ( new Error ( `Failed to ${ inMessage } .` ) ) ;
129
+ childProc . on ( "close" , ( code : number ) => {
130
+ if ( code !== 0 ) {
131
+ reject ( new Error ( "Failed to login." ) ) ;
90
132
}
91
133
} ) ;
92
134
} ) ;
0 commit comments