Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5a23cb3

Browse files
leo-stepseanprashad
andauthored
Use python-leetcode (#210)
* update datatip date * rewrite script to use python-leetcode library with session token * update yml with new library and session token * add day to tooltip date * Query and parse companies from Leetcode API * clean up and update data tip * Retrieve more question metadata & polish front-end connections Co-authored-by: Sean Prashad <13009507+SeanPrashad@users.noreply.github.com>
1 parent 8c28a27 commit 5a23cb3

File tree

5 files changed

+7162
-1896
lines changed

5 files changed

+7162
-1896
lines changed

‎.github/workflows/run-cron.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ jobs:
1717
architecture: 'x64'
1818
- run: |
1919
python -m pip install --upgrade pip
20-
pip install requests
20+
pip install requests python-leetcode
2121
- run: |
2222
python cron/update_questions.py
23+
env:
24+
LEETCODE_SESSION_TOKEN: ${{ secrets.LEETCODE_SESSION_TOKEN }}
2325
- uses: stefanzweifel/git-auto-commit-action@v4
2426
with:
2527
commit_message: Update questions via run-cron GitHub Action

‎cron/update_questions.py

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
import os
22
import json
3-
import requests
3+
import leetcode
4+
import leetcode.auth
45
from datetime import datetime
56

6-
query = '''query questionData($titleSlug: String!) {
7-
question(titleSlug: $titleSlug) {
8-
difficulty
9-
}
10-
}
11-
'''
7+
LEETCODE_SESSION_TOKEN = os.environ.get("LEETCODE_SESSION_TOKEN")
128

139
questions_file = os.getcwd() + "/src/data/questions.json"
1410

@@ -25,19 +21,56 @@
2521

2622
startTime = datetime.now()
2723

28-
for question in questions["data"]:
29-
variables = {"titleSlug": question["url"]}
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
3033

31-
response = requests.post("https://leetcode.com/graphql",
32-
json={"query": query, "variables": variables}
34+
api_instance = leetcode.DefaultApi(leetcode.ApiClient(configuration))
35+
36+
for question in questions["data"]:
37+
graphql_request = leetcode.GraphqlQuery(
38+
query='''query questionData($titleSlug: String!) {
39+
question(titleSlug: $titleSlug) {
40+
title
41+
difficulty
42+
companyTagStats
43+
isPaidOnly
44+
}
45+
}
46+
''',
47+
variables=leetcode.GraphqlQueryGetQuestionDetailVariables(
48+
title_slug=question["slug"])
3349
)
3450

35-
our_difficulty = question["difficulty"]
36-
leetcode_difficulty = response.json()["data"]["question"]["difficulty"]
51+
response = api_instance.graphql_post(body=graphql_request).to_dict()
52+
53+
leetcode_title = response["data"]["question"]["title"]
54+
leetcode_difficulty = response["data"]["question"]["difficulty"]
55+
leetcode_companies = json.loads(
56+
response["data"]["question"]["company_tag_stats"])["1"]
57+
leetcode_premium = response["data"]["question"]["is_paid_only"]
58+
59+
companies = []
60+
61+
for leetcode_company in leetcode_companies:
62+
company = {
63+
"name": leetcode_company["name"],
64+
"slug": leetcode_company["slug"],
65+
"frequency": leetcode_company["timesEncountered"]
66+
}
67+
68+
companies.append(company)
3769

38-
if leetcode_difficulty != our_difficulty:
39-
print(f'{question["name"]}: {our_difficulty} -> {leetcode_difficulty}')
40-
question["difficulty"] = leetcode_difficulty
70+
question["title"] = leetcode_title
71+
question["difficulty"] = leetcode_difficulty
72+
question["companies"] = companies
73+
question["premium"] = leetcode_premium
4174

4275
print("=== Finished checking all questions ===")
4376

‎src/components/Table/index.js

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
} from './filters';
2424
import { Event } from '../Shared/Tracking';
2525

26-
import questions from '../../data';
26+
import questions,{updated} from '../../data';
2727

2828
import 'react-toggle/style.css';
2929
import './styles.scss';
@@ -239,12 +239,12 @@ const Table = () => {
239239
return (
240240
<NavLink
241241
target="_blank"
242-
href={`https://leetcode.com/problems/${cellInfo.row.original.url}/`}
242+
href={`https://leetcode.com/problems/${cellInfo.row.original.slug}/`}
243243
onClick={() => {
244244
Event(
245245
'Table',
246-
'Clicked question url',
247-
`${cellInfo.row.original.name} question url`,
246+
'Clicked question title',
247+
`${cellInfo.row.original.title} question title`,
248248
);
249249
}}
250250
>
@@ -255,7 +255,7 @@ const Table = () => {
255255
) : (
256256
''
257257
)}
258-
{cellInfo.row.original.name}
258+
{cellInfo.row.original.title}
259259
</NavLink>
260260
);
261261
},
@@ -266,7 +266,7 @@ const Table = () => {
266266
accessor: 'solutions',
267267
disableSortBy: true,
268268
Cell: cellInfo => {
269-
const url = `https://leetcode.com/problems/${cellInfo.row.original.url}/`;
269+
const url = `https://leetcode.com/problems/${cellInfo.row.original.slug}/`;
270270
return (
271271
<NavLink
272272
target="_blank"
@@ -275,7 +275,7 @@ const Table = () => {
275275
Event(
276276
'Table',
277277
'Clicked solution',
278-
`${cellInfo.row.original.name} solution`,
278+
`${cellInfo.row.original.slug} solution`,
279279
);
280280
}}
281281
>
@@ -353,13 +353,21 @@ const Table = () => {
353353
},
354354
{
355355
Header: () => {
356+
const date = new Date(updated);
357+
const month = date.toLocaleString('default', {
358+
month: 'long',
359+
});
360+
const day = date.getDay();
361+
const year = date.getFullYear();
356362
return (
357363
<>
358364
<div
359365
style={{ whiteSpace: 'nowrap', display: 'inline-block' }}
360366
>
361367
Companies{' '}
362-
<span data-tip="Companies retrieved from Leetcode Premium (January 2022)">
368+
<span
369+
data-tip={`Companies retrieved from Leetcode Premium on ${month} ${day}, ${year} - thanks to @leo-step!`}
370+
>
363371
<FaQuestionCircle />
364372
</span>
365373
</div>
@@ -376,13 +384,15 @@ const Table = () => {
376384
: -1;
377385
},
378386
Cell: cellInfo => {
387+
const questionSlug = cellInfo.row.original.slug;
379388
const companies = cellInfo.row.original.companies.map(company => {
389+
const tooltipText = `Asked by ${company.name} ${company.frequency} times`;
380390
return (
381391
<img
382-
key={company}
383-
src={`${iconPath}${company}.png`}
384-
alt={company}
385-
data-tip={company}
392+
key={`${questionSlug}-${company.name}`}
393+
src={`${iconPath}${company.slug}.png`}
394+
alt={company.name}
395+
data-tip={tooltipText}
386396
/>
387397
);
388398
});

‎src/data/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import questions from './questions.json';
22

33
const sortBy = { Easy: 0, Medium: 1, Hard: 2 };
4+
const { updated, data } = questions;
45

5-
export default questions.data.sort(
6-
(a, b) => sortBy[a.difficulty] - sortBy[b.difficulty],
7-
);
6+
export { updated };
7+
export default data.sort((a, b) => sortBy[a.difficulty] - sortBy[b.difficulty]);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /