|
3 | 3 | import leetcode |
4 | 4 | import leetcode.auth |
5 | 5 | from datetime import datetime |
| 6 | +from leetcode.rest import ApiException |
6 | 7 |
|
7 | | -LEETCODE_SESSION_TOKEN = os.environ.get("LEETCODE_SESSION_TOKEN") |
8 | 8 |
|
9 | | -questions_file = os.getcwd() + "/src/data/questions.json" |
| 9 | +def create_leetcode_api(): |
| 10 | + LEETCODE_SESSION_TOKEN = os.environ.get("LEETCODE_SESSION_TOKEN") |
| 11 | + csrf_token = leetcode.auth.get_csrf_cookie(LEETCODE_SESSION_TOKEN) |
10 | 12 |
|
11 | | -print("=== Reading questions file ===") |
| 13 | + configuration = leetcode.Configuration() |
12 | 14 |
|
13 | | -try: |
14 | | - with open(questions_file, "r") as file: |
15 | | - questions = json.load(file) |
16 | | -except Exception as e: |
17 | | - print(e) |
18 | | - exit() |
| 15 | + configuration.api_key["x-csrftoken"] = csrf_token |
| 16 | + configuration.api_key["csrftoken"] = csrf_token |
| 17 | + configuration.api_key["LEETCODE_SESSION"] = LEETCODE_SESSION_TOKEN |
| 18 | + configuration.api_key["Referer"] = "https://leetcode.com" |
| 19 | + configuration.debug = False |
19 | 20 |
|
20 | | -print("=== Updating question metadata ===") |
| 21 | + return leetcode.DefaultApi(leetcode.ApiClient(configuration)) |
21 | 22 |
|
22 | | -startTime = datetime.now() |
23 | 23 |
|
24 | | -csrf_token = leetcode.auth.get_csrf_cookie(LEETCODE_SESSION_TOKEN) |
25 | | - |
26 | | -configuration = leetcode.Configuration() |
27 | | - |
28 | | -configuration.api_key["x-csrftoken"] = csrf_token |
29 | | -configuration.api_key["csrftoken"] = csrf_token |
30 | | -configuration.api_key["LEETCODE_SESSION"] = LEETCODE_SESSION_TOKEN |
31 | | -configuration.api_key["Referer"] = "https://leetcode.com" |
32 | | -configuration.debug = False |
33 | | - |
34 | | -api_instance = leetcode.DefaultApi(leetcode.ApiClient(configuration)) |
35 | | - |
36 | | -for question in questions["data"]: |
| 24 | +def get_question_metadata(api, title_slug): |
37 | 25 | graphql_request = leetcode.GraphqlQuery( |
38 | 26 | query='''query questionData($titleSlug: String!) { |
39 | 27 | question(titleSlug: $titleSlug) { |
|
45 | 33 | } |
46 | 34 | ''', |
47 | 35 | variables=leetcode.GraphqlQueryGetQuestionDetailVariables( |
48 | | - title_slug=question["slug"]) |
| 36 | + title_slug=title_slug) |
49 | 37 | ) |
50 | 38 |
|
51 | | - response = api_instance.graphql_post(body=graphql_request).to_dict() |
| 39 | + try: |
| 40 | + response = api.graphql_post(body=graphql_request) |
| 41 | + except ApiException as e: |
| 42 | + print( |
| 43 | + f'Exception occurred when contacting the Leetcode GraphQL API: ${e}') |
| 44 | + exit() |
52 | 45 |
|
53 | | - leetcode_title = response["data"]["question"]["title"] |
54 | | - leetcode_difficulty = response["data"]["question"]["difficulty"] |
55 | | - leetcode_companyTags = json.loads( |
56 | | - response["data"]["question"]["company_tag_stats"]) |
57 | | - leetcode_premium = response["data"]["question"]["is_paid_only"] |
| 46 | + return response |
58 | 47 |
|
59 | | - # Retrieve companies who have asked this question within 0-1 year |
60 | | - leetcode_companies = leetcode_companyTags["1"] + leetcode_companyTags["2"] |
61 | 48 |
|
| 49 | +def construct_company_tag_list(company_tags_json, sections): |
62 | 50 | companies = [] |
63 | 51 |
|
64 | | - for leetcode_company in leetcode_companies: |
65 | | - companies.append({ |
66 | | - "name": leetcode_company["name"], |
67 | | - "slug": leetcode_company["slug"], |
68 | | - "frequency": leetcode_company["timesEncountered"] |
69 | | - }) |
| 52 | + for section in sections: |
| 53 | + for company in company_tags_json[section]: |
| 54 | + companies.append({ |
| 55 | + "name": company["name"], |
| 56 | + "slug": company["slug"], |
| 57 | + "frequency": company["timesEncountered"] |
| 58 | + }) |
| 59 | + |
| 60 | + return sorted(companies, key=lambda d: d['frequency'], reverse=True) |
| 61 | + |
70 | 62 |
|
71 | | - companies = sorted(companies, key = lambda d: d['frequency'], reverse=True) |
| 63 | +def update_question_metadata(question, title, difficulty, companies, is_premium): |
| 64 | + print(f"🔄 Updating question metadata for {title}") |
72 | 65 |
|
73 | | - question["title"] = leetcode_title |
74 | | - question["difficulty"] = leetcode_difficulty |
| 66 | + question["title"] = title |
| 67 | + question["difficulty"] = difficulty |
75 | 68 | question["companies"] = companies |
76 | | - question["premium"] = leetcode_premium |
| 69 | + question["premium"] = is_premium |
| 70 | + |
| 71 | + |
| 72 | +def read_questions(file_name): |
| 73 | + print(f"💾 Loading {file_name}") |
| 74 | + |
| 75 | + try: |
| 76 | + with open(file_name, "r") as file: |
| 77 | + questions = json.load(file) |
| 78 | + print(f"✅ Finished loading {file_name}") |
| 79 | + return questions |
| 80 | + except Exception as e: |
| 81 | + print( |
| 82 | + f"❌ Exception occurred when reading {file_name}: {e}") |
| 83 | + exit() |
| 84 | + |
| 85 | + |
| 86 | +def write_questions(file_name, questions): |
| 87 | + print(f"💾 Updating {file_name}") |
| 88 | + |
| 89 | + try: |
| 90 | + with open(file_name, "w") as file: |
| 91 | + questions["updated"] = str(datetime.now().isoformat()) |
| 92 | + json.dump(questions, file, indent=2) |
| 93 | + print(f"✅ Finished updating {file_name}") |
| 94 | + except Exception as e: |
| 95 | + print( |
| 96 | + f"❌ Exception occurred when writing {file_name}: {e}") |
| 97 | + exit() |
| 98 | + |
| 99 | + |
| 100 | +def main(file_name): |
| 101 | + api = create_leetcode_api() |
| 102 | + questions = read_questions(file_name) |
| 103 | + |
| 104 | + for question in questions["data"]: |
| 105 | + title_slug = question["slug"] |
| 106 | + |
| 107 | + response = get_question_metadata(api, title_slug) |
| 108 | + |
| 109 | + question_title = response.data.question.title |
| 110 | + question_difficulty = response.data.question.difficulty |
| 111 | + question_company_tags = json.loads( |
| 112 | + response.data.question.company_tag_stats) |
| 113 | + question_is_premium = response.data.question.is_paid_only |
| 114 | + |
| 115 | + # Retrieve companies who have asked this question within the following two |
| 116 | + # company_tag_stat sections: |
| 117 | + # 1. 0-6 months |
| 118 | + # 2. 6 months to 1 year |
| 119 | + companies = construct_company_tag_list( |
| 120 | + question_company_tags, ["1", "2"]) |
| 121 | + |
| 122 | + update_question_metadata(question, question_title, question_difficulty, |
| 123 | + companies, question_is_premium) |
| 124 | + |
| 125 | + write_questions(file_name, questions) |
| 126 | + |
77 | 127 |
|
78 | | -print("=== Finished checking all questions ===") |
| 128 | +if __name__ == "__main__": |
| 129 | + file_name = os.getcwd() + "/src/data/questions.json" |
| 130 | + startTime = datetime.now() |
79 | 131 |
|
80 | | -try: |
81 | | - with open(questions_file, "w") as file: |
82 | | - questions["updated"] = str(datetime.now().isoformat()) |
83 | | - json.dump(questions, file, indent=2) |
84 | | -except Exception as e: |
85 | | - print(e) |
86 | | - exit() |
| 132 | + main(file_name) |
87 | 133 |
|
88 | | -print("=== Wrote questions file ===") |
89 | | -print(f'=== Script took: {datetime.now() - startTime} seconds ===') |
| 134 | + print(f"⏱️ Data updated in {datetime.now() - startTime} seconds") |
0 commit comments