|
| 1 | +import requests |
| 2 | +import json |
| 3 | +from datetime import datetime |
| 4 | +from bs4 import BeautifulSoup |
| 5 | + |
| 6 | +# Set variables |
| 7 | +date_str = datetime.now().strftime('%B %-d, %Y') |
| 8 | +repo_url = "https://github.com/ContextLab/leetcode-solutions" |
| 9 | +readme_file = "README.md" |
| 10 | +leetcode_api_url = "https://leetcode.com/graphql" |
| 11 | +daily_challenge_query = { |
| 12 | + "query": """query questionOfToday { |
| 13 | + activeDailyCodingChallengeQuestion { |
| 14 | + date |
| 15 | + link |
| 16 | + question { |
| 17 | + questionId |
| 18 | + title |
| 19 | + titleSlug |
| 20 | + difficulty |
| 21 | + } |
| 22 | + } |
| 23 | + }""", |
| 24 | + "operationName": "questionOfToday" |
| 25 | +} |
| 26 | + |
| 27 | +# Fetch daily challenge details from API |
| 28 | +response = requests.post(leetcode_api_url, json=daily_challenge_query) |
| 29 | +data = response.json() |
| 30 | + |
| 31 | +# Debug: Print the entire response to check its structure |
| 32 | +print(json.dumps(data, indent=2)) |
| 33 | + |
| 34 | +# Fetch the daily challenge details from the daily challenge page for verification |
| 35 | +daily_challenge_page = requests.get("https://leetcode.com/problemset/all/") |
| 36 | +soup = BeautifulSoup(daily_challenge_page.content, 'html.parser') |
| 37 | + |
| 38 | +# Initialize variables for cross-verified details |
| 39 | +daily_challenge_title = None |
| 40 | +daily_challenge_slug = None |
| 41 | +daily_challenge_id = None |
| 42 | + |
| 43 | +# Attempt to fetch the daily challenge details |
| 44 | +try: |
| 45 | + daily_challenge_section = soup.find('div', {'class': 'question-list-table'}) |
| 46 | + if daily_challenge_section: |
| 47 | + first_problem = daily_challenge_section.find_all('tr')[1] # Skip header row |
| 48 | + daily_challenge_title = first_problem.find('a', {'class': 'title'}).text.strip() |
| 49 | + daily_challenge_slug = first_problem.find('a', {'class': 'title'})['href'].strip().split('/')[-2] |
| 50 | + daily_challenge_id = first_problem.find_all('td')[1].text.strip() |
| 51 | + |
| 52 | + # Print the cross-verified details for debugging |
| 53 | + print(f"Cross-verified Title: {daily_challenge_title}") |
| 54 | + print(f"Cross-verified Slug: {daily_challenge_slug}") |
| 55 | + print(f"Cross-verified ID: {daily_challenge_id}") |
| 56 | + else: |
| 57 | + raise Exception("Error: Could not fetch the daily challenge from the problem set page.") |
| 58 | +except Exception as e: |
| 59 | + print(f"Error: Exception occurred while fetching daily challenge details: {e}") |
| 60 | + raise |
| 61 | + |
| 62 | +# Check if the expected data is present in the API response |
| 63 | +if 'data' in data and 'activeDailyCodingChallengeQuestion' in data['data']: |
| 64 | + problem = data['data']['activeDailyCodingChallengeQuestion']['question'] |
| 65 | + problem_id = problem['questionId'] |
| 66 | + title = problem['title'] |
| 67 | + title_slug = problem['titleSlug'] |
| 68 | + link = f"https://leetcode.com/problems/{title_slug}" |
| 69 | + difficulty = problem['difficulty'] |
| 70 | + difficulty_icon = "🟢" if difficulty == "Easy" else "🟡" if difficulty == "Medium" else "🔴" |
| 71 | + note_link = f"{repo_url}/tree/main/problems/{problem_id}" |
| 72 | + |
| 73 | + # Print the API details for debugging |
| 74 | + print(f"API Title: {title}") |
| 75 | + print(f"API Slug: {title_slug}") |
| 76 | + print(f"API ID: {problem_id}") |
| 77 | + |
| 78 | + # Check if the API title and slug match the cross-verified title and slug |
| 79 | + if daily_challenge_title and (daily_challenge_title != title or daily_challenge_slug != title_slug): |
| 80 | + raise Exception("Error: The titles or slugs do not match. The API might be providing incorrect details.") |
| 81 | + |
| 82 | + # Create the new entry |
| 83 | + new_entry = f"| {date_str} | [{problem_id}]({link}) | [Click here]({note_link}) | {difficulty_icon} {difficulty} |" |
| 84 | + |
| 85 | + # Read the entire README file |
| 86 | + with open(readme_file, 'r') as file: |
| 87 | + lines = file.readlines() |
| 88 | + |
| 89 | + # Initialize variables to store parts of the README |
| 90 | + before_table = [] |
| 91 | + table_content = [] |
| 92 | + after_table = [] |
| 93 | + in_table_section = False |
| 94 | + |
| 95 | + # Process the README line by line |
| 96 | + for line in lines: |
| 97 | + if "Problems we've attempted so far:" in line: |
| 98 | + in_table_section = True |
| 99 | + before_table.append(line) |
| 100 | + elif "# Join our discussion!" in line: |
| 101 | + in_table_section = False |
| 102 | + after_table.append(line) |
| 103 | + elif in_table_section: |
| 104 | + table_content.append(line) |
| 105 | + else: |
| 106 | + if table_content: |
| 107 | + after_table.append(line) |
| 108 | + else: |
| 109 | + before_table.append(line) |
| 110 | + |
| 111 | + # Strip trailing whitespace from the last row of the table content |
| 112 | + if table_content: |
| 113 | + table_content[-1] = table_content[-1].rstrip() |
| 114 | + |
| 115 | + # Rebuild the README with the new entry added to the table |
| 116 | + updated_readme = before_table + table_content + [new_entry + '\n'] + after_table |
| 117 | + |
| 118 | + # Overwrite the README file with the updated content |
| 119 | + with open(readme_file, 'w') as file: |
| 120 | + file.writelines(updated_readme) |
| 121 | + |
| 122 | + print("README file updated successfully!") |
| 123 | +else: |
| 124 | + raise Exception("Error: Unexpected response structure.") |
0 commit comments