|
| 1 | +import os # For getting the current working directory and making directories |
| 2 | +import sys # For getting command line arguments |
| 3 | +from enum import Enum # For the enum class |
| 4 | +from selenium import webdriver # For getting the HTML of the problem |
| 5 | +import requests # For downloading images |
| 6 | +from bs4 import BeautifulSoup # For parsing HTML |
| 7 | +import markdownify as md # For converting HTML to Markdown |
| 8 | +sys.path.append("utils") # Add the utils directory to the path |
| 9 | +import pytermgui_tui as tui # Import the TUI |
| 10 | +from data import Data # Import the Data class |
| 11 | +from projcets_helpers import * # Import the projects creation methods |
| 12 | + |
| 13 | +BASE_URL = "https://leetcode.com/problems/" # The base URL of the problem |
| 14 | + |
| 15 | +BASE_URL = BASE_URL + "merge-two-sorted-lists" # The URL of the problem for testing |
| 16 | + |
| 17 | +# Stup the tui |
| 18 | +tui.setup() |
| 19 | + |
| 20 | +# Check if user provided a URL as an argument |
| 21 | +if len(sys.argv) < 2: |
| 22 | + # If not, ask for one |
| 23 | + problem_url = tui.get_the_url(BASE_URL) |
| 24 | +else: |
| 25 | + # If so, use it |
| 26 | + problem_url = sys.argv[1] |
| 27 | + # Check if user provided a problem title instead of a URL, if so, add the base URL |
| 28 | + if not problem_url.startswith(BASE_URL) and not problem_url.startswith("http"): |
| 29 | + problem_url = BASE_URL + problem_url |
| 30 | + |
| 31 | +# Check if the URL is valid |
| 32 | +if not problem_url.startswith(BASE_URL): |
| 33 | + print("Invalid URL, please enter a valid URL(LeeCode problem URL)") |
| 34 | + exit(1) |
| 35 | + |
| 36 | +# Setup the driver (firefox) |
| 37 | +driver = webdriver.Firefox() |
| 38 | + |
| 39 | +driver.get(problem_url) # Open the URL in the browser |
| 40 | + |
| 41 | +soup = BeautifulSoup(driver.page_source, "lxml") # Parse the HTML |
| 42 | + |
| 43 | +driver.quit() # Close the driver |
| 44 | + |
| 45 | +# Get the main div (the problem details are in this div) |
| 46 | +main_div = soup.find("div", {"class": "ssg__qd-splitter-primary-w"}).find("div", {"class": "ssg__qd-splitter-primary-h"}) |
| 47 | + |
| 48 | +# Get the title of the problem |
| 49 | +title = soup.title.string.lower().replace(" - leetcode", "").replace(" ", "_") |
| 50 | + |
| 51 | +level = main_div.find("div", {"class": "mt-3 flex space-x-4"}).find("div", {"class": "py-1"}).text.lower() |
| 52 | + |
| 53 | +# Check if the level directory exists, if not, create it |
| 54 | +if not os.path.exists(level): |
| 55 | + os.mkdir(level) |
| 56 | + |
| 57 | +# Check if the problem directory exists, if not, create it |
| 58 | +problem_path = os.path.join(level, title) |
| 59 | +if not os.path.exists(problem_path): |
| 60 | + os.mkdir(problem_path) |
| 61 | + |
| 62 | +# Get the description of the problem |
| 63 | +discription = main_div.find("div", {"class": "_1l1MA"}) |
| 64 | + |
| 65 | +# Show the tui for confirm the data and choose the language to solve the problem |
| 66 | +data = tui.confirm_data(Data(title, level, problem_path)) |
| 67 | + |
| 68 | +# Download the images if there are any |
| 69 | +for img in discription.find_all("img"): |
| 70 | + src = img["src"] |
| 71 | + req = requests.get(src) |
| 72 | + if req.status_code == 200: |
| 73 | + img_name = src.split("/")[-1] |
| 74 | + img_path = os.path.join(data.problem_path, "images", img_name) |
| 75 | + if not os.path.exists(img_path): |
| 76 | + if not os.path.exists(os.path.dirname(img_path)): |
| 77 | + os.makedirs(os.path.dirname(img_path)) |
| 78 | + with open(img_path, "wb") as f: |
| 79 | + f.write(req.content) |
| 80 | + img["src"] = img_path.replace(data.problem_path, ".") |
| 81 | + |
| 82 | +# Convert the discription to Markdown |
| 83 | +discription = md.markdownify(str(discription), heading_style="ATX") |
| 84 | + |
| 85 | +# Add the title to the discription |
| 86 | +discription = "# " + data.title.capitalize().replace("_", " ") + "\n" + discription |
| 87 | + |
| 88 | +# Add the problem URL to the discription |
| 89 | +discription = discription + "\n- [Problem URL](" + problem_url + ")" |
| 90 | + |
| 91 | +# Write the discription to the README.md file, if it doesn't exist |
| 92 | +if not os.path.exists(os.path.join(data.problem_path, "README.md")): |
| 93 | + with open(os.path.join(data.problem_path, "README.md"), "w") as f: |
| 94 | + f.write(discription) |
| 95 | + |
| 96 | +# Create the NOTE.md file, if it doesn't exist |
| 97 | +if not os.path.exists(os.path.join(data.problem_path, "NOTE.md")): |
| 98 | + with open(os.path.join(data.problem_path, "NOTE.md"), "w") as f: |
| 99 | + f.write("## There is no note for this problem yet ¯\(ツ)/¯") |
| 100 | + |
| 101 | +# Create the solution project for each language |
| 102 | +for lang in data.solve_with: |
| 103 | + lang_path = os.path.join(data.problem_path, lang) |
| 104 | + if not os.path.exists(lang_path): |
| 105 | + os.mkdir(lang_path) |
| 106 | + match lang: |
| 107 | + case "python" | "py": |
| 108 | + create_python_project(lang_path) |
| 109 | + case "java": |
| 110 | + create_java_project(lang_path) |
| 111 | + case "c++" | "cpp": |
| 112 | + create_cpp_project(lang_path) |
| 113 | + case "c": |
| 114 | + create_c_project(lang_path) |
| 115 | + case "rust": |
| 116 | + create_rust_project(lang_path) |
| 117 | + case "go": |
| 118 | + create_go_project(lang_path) |
| 119 | + case _: # If other language, do nothing |
| 120 | + pass |
| 121 | + |
0 commit comments