Skip to content

Commit 8fa42fe

Browse files
committed
Refactor variable names to increase readability
1 parent 9406cc7 commit 8fa42fe

File tree

3 files changed

+58
-33
lines changed

3 files changed

+58
-33
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ docker run -it -v $(pwd):/usr/app/out --rm nevermendel/leetcode-export
7272
## Login
7373

7474
To download your submissions you need to log in your LeetCode account by providing the cookies. To log in using cookies,
75-
you need to get them from a session where you are already logged in.
75+
get them from an existing session.
7676

7777
**Steps required**:
7878

79-
- Login in your LeetCode account in your browser
79+
- Login in to LeetCode in the web browser
8080
- Open the browser's Dev Tool
8181
- Click on the Network tab
8282
- Copy the cookie header that can be found under Request Headers in any leetcode.com request.

leetcode_export/__main__.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
'''
2+
LeetCode Export.
3+
4+
Export your LeetCode submissions and related problem statements.
5+
'''
16
import argparse
27
import logging
38
import os
@@ -10,17 +15,17 @@
1015

1116

1217
def parse_args():
13-
parser = argparse.ArgumentParser(description='Export LeetCode solutions', formatter_class=argparse.RawTextHelpFormatter)
18+
parser = argparse.ArgumentParser(description='Export LeetCode submissions', formatter_class=argparse.RawTextHelpFormatter)
1419
parser.add_argument('--cookies', type=str, help='set LeetCode cookies')
1520
parser.add_argument('--folder', type=str, default='.', help='set output folder')
1621
parser.add_argument('--problem-folder-name', type=str, default='${question_id}-${title_slug}',
1722
help='problem folder name format')
18-
parser.add_argument('--problem-filename', type=str, default='${question_id}-${title_slug}.html',
19-
help='problem description filename format')
20-
parser.add_argument('--problem-content', type=str,
23+
parser.add_argument('--problem-statement-filename', type=str, default='${question_id}-${title_slug}.html',
24+
help='problem statement filename format')
25+
parser.add_argument('--problem-statement-content', type=str,
2126
default='<h1>${question_id} - ${title}</h1><h2>Difficulty: ${difficulty} - ' +
2227
'<a href="https://leetcode.com/problems/${title_slug}/">${title_slug}</a></h2>${content}',
23-
help='problem description content format')
28+
help='problem statement content format')
2429
parser.add_argument('--submission-filename', type=str,
2530
default='${date_formatted} - ${status_display} - runtime ${runtime} - memory ${memory}.${extension}',
2631
help='submission filename format')
@@ -73,9 +78,9 @@ def main():
7378
logging.info(args)
7479

7580
problem_folder_name_template = Template(args.problem_folder_name)
76-
problem_statement_template = Template(args.problem_filename)
77-
problem_content_template = Template(args.problem_content)
78-
submission_template = Template(args.submission_filename)
81+
problem_statement_filename_template = Template(args.problem_statement_filename)
82+
problem_statement_template = Template(args.problem_statement_content)
83+
submission_filename_template = Template(args.submission_filename)
7984

8085
leetcode = LeetCode()
8186
cookies = args.cookies
@@ -84,8 +89,8 @@ def main():
8489
cookies = input("Insert LeetCode cookies: ")
8590

8691
if not leetcode.set_cookies(cookies):
87-
print(
88-
"Cookies not valid. Copy them from the Network tab of your browser by clicking on any leetcode.com request and going in Request Headers > cookie.")
92+
logging.error(
93+
"Cookies not valid. Copy them from the Network tab of your browser by clicking on any leetcode.com request and going in Request Headers > cookie. Check README.md file for further information")
8994
exit(1)
9095

9196
# Create output folder if it doesn't already exist
@@ -103,28 +108,28 @@ def main():
103108
continue
104109

105110
if submission.title_slug not in title_slug_to_problem_folder_name:
106-
problem_statement = leetcode.get_problem(submission.title_slug)
111+
problem_statement = leetcode.get_problem_statement(submission.title_slug)
107112
problem_folder_name = problem_folder_name_template.substitute(**problem_statement.__dict__)
108113
title_slug_to_problem_folder_name[submission.title_slug] = problem_folder_name
109114
if not os.path.exists(problem_folder_name):
110115
os.mkdir(problem_folder_name)
111116
os.chdir(problem_folder_name)
112117

113-
problem_statement_filename = problem_statement_template.substitute(**problem_statement.__dict__)
118+
problem_statement_filename = problem_statement_filename_template.substitute(**problem_statement.__dict__)
114119
if not os.path.exists(problem_statement_filename):
115120
with open(problem_statement_filename, 'w+') as problem_statement_file:
116-
problem_statement_file.write(problem_content_template.substitute(**problem_statement.__dict__))
121+
problem_statement_file.write(problem_statement_template.substitute(**problem_statement.__dict__))
117122
else:
118123
os.chdir(title_slug_to_problem_folder_name[submission.title_slug])
119124

120-
sub_filename = submission_template.substitute(**submission.__dict__)
121-
if not os.path.exists(sub_filename):
122-
logging.info(f"Writing {submission.title_slug}/{sub_filename}")
123-
sub_file = open(sub_filename, 'w+')
125+
submission_filename = submission_filename_template.substitute(**submission.__dict__)
126+
if not os.path.exists(submission_filename):
127+
logging.info(f"Writing {submission.title_slug}/{submission_filename}")
128+
sub_file = open(submission_filename, 'w+')
124129
sub_file.write(submission.code)
125130
sub_file.close()
126131
else:
127-
logging.info(f"{submission.title_slug}/{sub_filename} already exists, skipping it")
132+
logging.info(f"{submission.title_slug}/{submission_filename} already exists, skipping it")
128133

129134
os.chdir("..")
130135

leetcode_export/leetcode.py

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
'''
2+
LeetCode Python APIs for retrieving submitted problems and problem statements.
3+
'''
14
import datetime
25
import logging
36
from time import sleep
@@ -18,6 +21,12 @@ def __init__(self):
1821
self.user_logged_expiration = datetime.datetime.now()
1922

2023
def log_in(self, username: str, password: str) -> bool:
24+
'''
25+
Log in to LeetCode using username and password
26+
:param username: LeetCode username
27+
:param password: LeetCode password
28+
:return: bool, true if login is successful, false otherwise
29+
'''
2130
self.session.get(LOGIN_URL)
2231

2332
csrftoken = self.session.cookies.get('csrftoken')
@@ -42,16 +51,27 @@ def set_cookies(self, cookies: str) -> bool:
4251
:param cookies: string with cookies to set
4352
:return: bool, true if login is successful, false otherwise
4453
'''
45-
cookies_list = cookies.split(';')
46-
cookies_list = map(lambda el: el.split('='), cookies_list)
47-
for cookies in cookies_list:
48-
self.session.cookies.set(cookies[0].strip(), cookies[1].strip())
54+
valid_cookies = True
55+
cookie_dict = {}
56+
57+
for cookie in cookies.split(';'):
58+
cookie_split = [el.strip() for el in cookie.split('=', 1)]
59+
if len(cookie_split) != 2:
60+
valid_cookies = False
61+
break
62+
cookie_dict[cookie_split[0]] = cookie_split[1]
63+
64+
valid_cookies = valid_cookies and 'csrftoken' in cookie_dict and 'LEETCODE_SESSION' in cookie_dict
65+
if not valid_cookies:
66+
logging.error("Cookie format not valid. Expected: 'csrftoken=value1;LEETCODE_SESSION=value2;...'")
67+
return False
68+
69+
for (cookie_key, cookie_value) in cookie_dict.items():
70+
self.session.cookies.set(cookie_key, cookie_value)
4971
if self.is_user_logged():
50-
logging.info("Cookies set successful")
72+
logging.info("Cookie set successful")
5173
return True
52-
else:
53-
logging.warning("Cookies set failed")
54-
return False
74+
return False
5575

5676
def is_user_logged(self) -> bool:
5777
'''
@@ -69,12 +89,12 @@ def is_user_logged(self) -> bool:
6989
self.user_logged = True
7090
self.user_logged_expiration = datetime.datetime.now() + datetime.timedelta(hours=5)
7191
return True
72-
logging.debug("User is not logged in")
92+
logging.error("User is not logged in or account is invalid!")
7393
return False
7494

75-
def get_problem(self, slug: str) -> Problem:
95+
def get_problem_statement(self, slug: str) -> Problem:
7696
'''
77-
Get LeetCode problem info
97+
Get LeetCode problem statement
7898
:param slug: problem identifier
7999
:return: Problem
80100
'''
@@ -91,7 +111,7 @@ def get_submissions(self) -> Iterator[Submission]:
91111
:return: Iterator[Submission], LeetCode submission
92112
'''
93113
if not self.is_user_logged():
94-
logging.warning("Trying to get user submissions while user is not logged in")
114+
logging.error("Trying to get user submissions while user is not logged in")
95115
return None
96116

97117
current = 0
@@ -115,6 +135,6 @@ def get_submissions(self) -> Iterator[Submission]:
115135
yield submission
116136

117137
current += 20
118-
sleep(5)
138+
sleep(5) # cooldown time for get request
119139
if 'detail' in response_json:
120140
logging.warning(response_json['detail'])

0 commit comments

Comments
 (0)