Skip to content

Commit bbc041d

Browse files
feat: re-add cookie-based login method (LeetCode-OpenSource#969)
* feat: re-add cookie-based login method * chore: optimize tslint config * chore : change build.yml --------- Co-authored-by: leo.zhao <zale0201@gmail.com>
1 parent b495812 commit bbc041d

File tree

7 files changed

+89
-67
lines changed

7 files changed

+89
-67
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,3 @@ jobs:
4848

4949
- name: VSCE Packge
5050
run: npx vsce package
51-
52-
darwin:
53-
name: macOS
54-
runs-on: macos-latest
55-
timeout-minutes: 30
56-
steps:
57-
- uses: actions/checkout@v2
58-
59-
- name: Setup Node.js environment
60-
uses: actions/setup-node@v2
61-
with:
62-
node-version: 14
63-
64-
- name: Install Node.js modules
65-
run: npm install
66-
67-
- name: Lint
68-
run: npm run lint
69-
70-
- name: VSCE Packge
71-
run: npx vsce package

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"editor.formatOnSave": true,
2+
"editor.formatOnSave": false,
33
"editor.insertSpaces": true,
44
"editor.tabSize": 4,
55
"files.insertFinalNewline": true,

src/leetCodeManager.ts

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import { EventEmitter } from "events";
66
import * as vscode from "vscode";
77
import { leetCodeChannel } from "./leetCodeChannel";
88
import { leetCodeExecutor } from "./leetCodeExecutor";
9-
import { Endpoint, loginArgsMapping, urls, urlsCn, UserStatus } from "./shared";
9+
import { Endpoint, IQuickItemEx, loginArgsMapping, urls, urlsCn, UserStatus } from "./shared";
1010
import { createEnvOption } from "./utils/cpUtils";
1111
import { DialogType, openUrl, promptForOpenOutputChannel } from "./utils/uiUtils";
1212
import * as wsl from "./utils/wslUtils";
1313
import { getLeetCodeEndpoint } from "./commands/plugin";
1414
import { globalState } from "./globalState";
1515
import { queryUserData } from "./request/query-user-data";
16-
import { parseQuery, sleep } from "./utils/toolUtils";
16+
import { parseQuery } from "./utils/toolUtils";
1717

1818
class LeetCodeManager extends EventEmitter {
1919
private currentUser: string | undefined;
@@ -42,6 +42,19 @@ class LeetCodeManager extends EventEmitter {
4242
}
4343
}
4444

45+
private async updateUserStatusWithCookie(cookie: string): Promise<void> {
46+
globalState.setCookie(cookie);
47+
const data = await queryUserData();
48+
globalState.setUserStatus(data);
49+
await this.setCookieToCli(cookie, data.username);
50+
if (data.username) {
51+
vscode.window.showInformationMessage(`Successfully ${data.username}.`);
52+
this.currentUser = data.username;
53+
this.userStatus = UserStatus.SignedIn;
54+
this.emit("statusChanged");
55+
}
56+
}
57+
4558
public async handleUriSignIn(uri: vscode.Uri): Promise<void> {
4659
try {
4760
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (progress: vscode.Progress<{}>) => {
@@ -52,24 +65,61 @@ class LeetCodeManager extends EventEmitter {
5265
promptForOpenOutputChannel(`Failed to get cookie. Please log in again`, DialogType.error);
5366
return;
5467
}
55-
globalState.setCookie(cookie);
56-
const data = await queryUserData();
57-
globalState.setUserStatus(data);
58-
await this.setCookieToCli(cookie, data.username);
59-
if (data.username) {
60-
vscode.window.showInformationMessage(`Successfully ${data.username}.`);
61-
this.currentUser = data.username;
62-
this.userStatus = UserStatus.SignedIn;
63-
this.emit("statusChanged");
64-
}
68+
69+
await this.updateUserStatusWithCookie(cookie)
70+
6571
});
6672
} catch (error) {
6773
promptForOpenOutputChannel(`Failed to log in. Please open the output channel for details`, DialogType.error);
6874
}
6975
}
7076

77+
public async handleInputCookieSignIn(): Promise<void> {
78+
const cookie: string | undefined = await vscode.window.showInputBox({
79+
prompt: 'Enter LeetCode Cookie',
80+
password: true,
81+
ignoreFocusOut: true,
82+
validateInput: (s: string): string | undefined =>
83+
s ? undefined : 'Cookie must not be empty',
84+
})
85+
86+
await this.updateUserStatusWithCookie(cookie || '')
87+
}
88+
7189
public async signIn(): Promise<void> {
72-
openUrl(this.getAuthLoginUrl());
90+
const picks: Array<IQuickItemEx<string>> = []
91+
picks.push(
92+
{
93+
label: 'Web Authorization',
94+
detail: 'Open browser to authorize login on the website',
95+
value: 'WebAuth',
96+
description: '[Recommended]'
97+
},
98+
{
99+
label: 'LeetCode Cookie',
100+
detail: 'Use LeetCode cookie copied from browser to login',
101+
value: 'Cookie',
102+
}
103+
)
104+
105+
const choice: IQuickItemEx<string> | undefined = await vscode.window.showQuickPick(picks)
106+
if (!choice) {
107+
return
108+
}
109+
const loginMethod: string = choice.value
110+
111+
if (loginMethod === 'WebAuth') {
112+
openUrl(this.getAuthLoginUrl())
113+
return
114+
}
115+
116+
try {
117+
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: "Fetching user data..." }, async () => {
118+
await this.handleInputCookieSignIn()
119+
});
120+
} catch (error) {
121+
promptForOpenOutputChannel(`Failed to log in. Please open the output channel for details`, DialogType.error);
122+
}
73123
}
74124

75125
public async signOut(): Promise<void> {
@@ -136,15 +186,16 @@ class LeetCodeManager extends EventEmitter {
136186
} else if (data.match(this.failRegex)) {
137187
childProc.stdin?.end();
138188
return reject(new Error("Faile to login"));
189+
} else if (data.match(/login: /)) {
190+
childProc.stdin?.write(`${name}\n`);
191+
} else if (data.match(/cookie: /)) {
192+
childProc.stdin?.write(`${cookie}\n`);
139193
}
140194
});
141195

142196
childProc.stderr?.on("data", (data: string | Buffer) => leetCodeChannel.append(data.toString()));
143197

144198
childProc.on("error", reject);
145-
childProc.stdin?.write(`${name}\n`);
146-
await sleep(800);
147-
childProc.stdin?.write(`${cookie}\n`);
148199
});
149200
}
150201
}

src/utils/httpUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function LcAxios<T = any>(path: string, settings?: AxiosRequestConfig): A
1616
}
1717
return axios(path, {
1818
headers: {
19-
referer: referer,
19+
referer,
2020
"content-type": "application/json",
2121
cookie,
2222
...(settings && settings.headers),

src/utils/toolUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export function parseQuery(query: string): { [key: string]: string } {
99
return queryObject;
1010
}
1111

12-
let keyValuePairs = query.split("&");
12+
const keyValuePairs = query.split("&");
1313
keyValuePairs.forEach((pair) => {
1414
const firstEqualsIndex = pair.indexOf("=");
1515
if (firstEqualsIndex !== -1) {

src/utils/trackingUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class TrackData implements ITrackData {
9090
if (!Array.isArray(reportItems)) {
9191
reportItems = [reportItems];
9292
}
93-
let randomId = getRandomString(60);
93+
const randomId = getRandomString(60);
9494
reportItems.forEach((item) => {
9595
this.reportCache.push({
9696
...item,

tslint.json

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,28 @@
11
{
22
"defaultSeverity": "error",
3-
"extends": [
4-
"tslint:recommended"
5-
],
3+
"extends": ["tslint:recommended"],
64
"jsRules": {},
75
"rules": {
8-
"forin": false,
96
"object-literal-sort-keys": false,
10-
"indent": [
11-
true,
12-
"spaces"
13-
],
7+
"ordered-imports": [false],
8+
"indent": [true, "spaces"],
149
"no-string-literal": false,
1510
"no-namespace": false,
16-
"max-line-length": [
17-
false,
18-
120
19-
],
20-
"typedef": [
21-
true,
22-
"call-signature",
23-
"arrow-call-signature",
24-
"parameter",
25-
"arrow-parameter",
26-
"property-declaration",
27-
"variable-declaration",
28-
"member-variable-declaration"
29-
],
30-
"variable-name": [
31-
true,
32-
"allow-leading-underscore"
33-
]
11+
"max-line-length": [false, 120],
12+
"typedef": false,
13+
"no-implicit-dependencies": [true, ["vscode"]],
14+
"trailing-comma": false,
15+
"no-any": false,
16+
"object-literal-key-quotes": [true, "consistent-as-needed"],
17+
"prefer-object-spread": false,
18+
"no-unnecessary-await": false,
19+
"semicolon": [false],
20+
"quotemark": [false],
21+
"member-ordering": [false],
22+
"variable-name": [false],
23+
"curly": false,
24+
"interface-over-type-literal": [false],
25+
"no-unused-expression": false
3426
},
3527
"rulesDirectory": []
3628
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy