diff --git a/.gitignore b/.gitignore index 9f1c92715..d2a36c905 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea/ .vscode/ .DS_Store +.env diff --git a/scripts/common.bash b/scripts/common.bash new file mode 100755 index 000000000..5636e71da --- /dev/null +++ b/scripts/common.bash @@ -0,0 +1,132 @@ +#!/usr/bin/env bash + +source scripts/languages.bash + +# Load environment variables from .env file +function load_env_vars() { + if [ -f .env ]; then + # shellcheck disable=SC2046 + export echo $(sed <.env 's/#.*//g' | xargs | envsubst) + + # Check if required variables are set and not equal to default values + if [ "$NICKNAME" = "your_nickname" ] || [ "$LANGUAGE" = "choose_your_language" ]; then + echo "Error: Required environment variables are set to default values." + echo "Please update NICKNAME and LANGUAGE in the .env file with appropriate values." + exit 1 + fi + + # Check if the specified language is valid + + if [[ ! "${!language_extensions[@]}" =~ $LANGUAGE ]]; then + echo "Error: Invalid language specified in the .env file." + echo "Please set LANGUAGE to one of the following valid languages:" + echo "${!language_extensions[@]}" + exit 1 + fi + fi +} + +# Check if Bash version meets the minimum requirement +function check_bash_version() { + local required_version=$1 + local bash_version + bash_version=$(bash --version | head -n1 | awk '{print $4}' | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/') + + if [[ $bash_version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+) ]]; then + local major=${BASH_REMATCH[1]} + local minor=${BASH_REMATCH[2]} + local patch=${BASH_REMATCH[3]} + + IFS='.' read -r -a required_parts <<<"$required_version" + local required_major=${required_parts[0]} + local required_minor=${required_parts[1]} + local required_patch=${required_parts[2]} + + if ((major > required_major || (\ + major == required_major && minor > required_minor) || (\ + major == required_major && minor == required_minor && patch >= required_patch))); then + return 0 + else + return 1 + fi + else + return 1 + fi +} + +# Check if a command is installed +function check_command() { + local command="$1" + if ! command -v "$command" &>/dev/null; then + echo "The $command command is not installed." + read -r -p "Do you want to install $command? (Y/n): " install_command + case "$install_command" in + [nN] | [nN][oO]) + echo "Installation of $command has been rejected. Exiting the script." + exit 1 + ;; + *) + echo "Proceeding with the installation of $command..." + brew install "$command" + ;; + esac + fi +} + +# Generates the solution code template with question details and author information +function make_solution_code() { + local question_id=$1 + local question_name=$2 + local question_url=$3 + local code=$4 + local comment=${language_comments[$LANGUAGE]} + local nickname + if [ -n "$NICKNAME" ]; then + nickname=$NICKNAME + else + nickname=Unknown + fi + local content + content=$( + cat </dev/null 2>&1 && pwd)" + language_extension=${language_extensions[$LANGUAGE]} + + solution_folder="$DIR/../$title_slug" + mkdir -p "$solution_folder" + + solution_file="$solution_folder/$nickname.$language_extension" + echo "$content" >"$solution_file" + echo "File creation completed" +} diff --git a/scripts/languages.bash b/scripts/languages.bash new file mode 100755 index 000000000..0b99d79b0 --- /dev/null +++ b/scripts/languages.bash @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +declare -A language_extensions=( + ["cpp"]="cpp" + ["java"]="java" + ["python"]="py" + ["python3"]="py" + ["c"]="c" + ["csharp"]="cs" + ["javascript"]="js" + ["typescript"]="ts" + ["php"]="php" + ["swift"]="swift" + ["kotlin"]="kt" + ["dart"]="dart" + ["go"]="go" + ["ruby"]="rb" + ["scala"]="scala" + ["rust"]="rs" + ["racket"]="rkt" + ["erlang"]="erl" + ["elixir"]="ex" +) + +declare -A language_comments=( + ["cpp"]="// " + ["java"]="// " + ["python"]="# " + ["python3"]="# " + ["c"]="// " + ["csharp"]="// " + ["javascript"]="// " + ["typescript"]="// " + ["php"]="// " + ["swift"]="// " + ["kotlin"]="// " + ["dart"]="// " + ["go"]="// " + ["ruby"]="# " + ["scala"]="// " + ["rust"]="// " + ["racket"]="; " + ["erlang"]="% " + ["elixir"]="# " +) diff --git a/scripts/leetcode.bash b/scripts/leetcode.bash new file mode 100755 index 000000000..02774311c --- /dev/null +++ b/scripts/leetcode.bash @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +source scripts/common.bash +source scripts/leetcode_helper.bash + +function main() { + load_env_vars + + # Check if required commands are installed + check_command "jq" + check_command "bash" + check_command "brew" + + # Set the required Bash version + local required_bash_version="4.0.0" + + # Check Bash version and proceed with installation if necessary + if check_bash_version "$required_bash_version"; then + echo "Bash version meets the minimum requirement (>= $required_bash_version). Skipping installation." + else + echo "Bash version does not meet the minimum requirement (>= $required_bash_version). Proceeding with installation using Homebrew..." + # Add your Homebrew installation commands here + brew update + brew install bash + fi + + # Check if the problem title-slug or URL is provided + if [ "$#" -eq 1 ]; then + input="$1" + if [[ "$input" == *"https://leetcode.com/problems/"* ]]; then + # If the input is a LeetCode URL + problem_slug=$(extract_problem_name "$input") + else + # If the input is already a title-slug + problem_slug="$input" + fi + else + echo "Please provide the LeetCode problem title-slug or URL." + exit 1 + fi + + echo "Problem Slug: $problem_slug" + + # GraphQL query to fetch problem details + query=$(make_query "$problem_slug") + + echo "Requesting problem details from LeetCode GraphQL API..." + + # Send a POST request to the LeetCode GraphQL API + response=$(request "$query") + + # Check if the response contains valid data + if ! echo -E "$response" | jq -e '.data.question' >/dev/null 2>&1; then + echo -E "$response" + echo "Failed to receive a valid response from the LeetCode API. Exiting the script." + exit 1 + fi + + echo "Received problem details response from LeetCode." + + # Create the file + + create_file "$response" +} + +# Call the main function +main "$@" diff --git a/scripts/leetcode_helper.bash b/scripts/leetcode_helper.bash new file mode 100755 index 000000000..b2d059f5a --- /dev/null +++ b/scripts/leetcode_helper.bash @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +# Extract the title-slug from the LeetCode URL +function extract_problem_name() { + local url="$1" + echo "$url" | sed -n 's/.*\/problems\/\([^/]*\)\/.*/\1/p' +} + +# Generates the GraphQL query to fetch problem details based on the provided title-slug +function make_query() { + local question_slug=$1 + # shellcheck disable=SC2016 + local query='{ + "query": "query selectProblem($titleSlug: String!) { question(titleSlug: $titleSlug) { questionFrontendId title titleSlug codeSnippets { langSlug code } } }", + "variables": { + "titleSlug": "'"$question_slug"'" + } +}' + echo "$query" +} + +# Sends a POST request to the LeetCode GraphQL API with the generated query +function request() { + local query="$1" + local response + response=$(curl -s -X POST -H "Content-Type: application/json" --data "$query" https://leetcode.com/graphql) + echo -E "$response" +} + +# Creates a file for the LeetCode problem +# +# Parses the JSON response from the LeetCode API, extracts relevant problem details, +# generates the solution code template using the `make_solution_code()` function, +# and saves the file using the `save_file()` function. +function create_file() { + local json_data="$1" + local question_id + local title + local title_slug + local code_snippet + local content + + question_id=$(echo -E "$json_data" | jq -r '.data.question.questionFrontendId') + title=$(echo -E "$json_data" | jq -r '.data.question.title') + title_slug=$(echo -E "$json_data" | jq -r '.data.question.titleSlug') + + # Generate the code snippet + code_snippet=$(echo -E "$json_data" | jq -r ".data.question.codeSnippets[] | select(.langSlug == \"$LANGUAGE\") | .code") + + # Generate the entire code + content=$(make_solution_code "$question_id" "$title" "https://leetcode.com/problems/$title_slug/description/" "$code_snippet") + + save_file "$title_slug" "$content" +}