@@ -6,7 +6,7 @@ import { EventEmitter } from "events";
66import * as vscode from "vscode" ;
77import { leetCodeChannel } from "./leetCodeChannel" ;
88import { leetCodeExecutor } from "./leetCodeExecutor" ;
9- import { UserStatus } from "./shared" ;
9+ import { IQuickItemEx , loginArgsMapping , UserStatus } from "./shared" ;
1010import { createEnvOption } from "./utils/cpUtils" ;
1111import { DialogType , promptForOpenOutputChannel } from "./utils/uiUtils" ;
1212import * as wsl from "./utils/wslUtils" ;
@@ -34,14 +34,43 @@ class LeetCodeManager extends EventEmitter {
3434}
3535}
3636
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" ;
4171const inMessage :string = isByCookie ?"sign in by cookie" :"sign in" ;
4272try {
4373const userName :string | undefined = await new Promise ( async ( resolve :( res :string | undefined ) => void , reject :( e :Error ) => void ) :Promise < void > => {
44- let result :string = "" ;
4574
4675const leetCodeBinaryPath :string = await leetCodeExecutor . getLeetCodeBinaryPath ( ) ;
4776
@@ -52,10 +81,27 @@ class LeetCodeManager extends EventEmitter {
5281env :createEnvOption ( ) ,
5382} ) ;
5483
55- childProc . stdout . on ( "data" , ( data :string | Buffer ) => {
84+ childProc . stdout . on ( "data" , async ( data :string | Buffer ) => {
5685data = data . toString ( ) ;
57- result = result . concat ( data ) ;
5886leetCodeChannel . 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+ }
59105} ) ;
60106
61107childProc . stderr . on ( "data" , ( data :string | Buffer ) => leetCodeChannel . append ( data . toString ( ) ) ) ;
@@ -80,13 +126,9 @@ class LeetCodeManager extends EventEmitter {
80126return resolve ( undefined ) ;
81127}
82128childProc . 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." ) ) ;
90132}
91133} ) ;
92134} ) ;