From cef737ba0492e30fe3519c4b953f83d1195ec7b8 Mon Sep 17 00:00:00 2001 From: daVinci Date: Sun, 21 Apr 2024 11:11:28 -0700 Subject: [PATCH 1/2] Updated the automation to fix the build issue (hopefully.) --- .automation/Read-Only/descriptions.json | 2 +- .automation/index.py | 179 +++++++++++++++++------- Crypto/README.md | 2 +- README.md | 39 +++--- 4 files changed, 150 insertions(+), 72 deletions(-) diff --git a/.automation/Read-Only/descriptions.json b/.automation/Read-Only/descriptions.json index 9216a25..6a01fec 100644 --- a/.automation/Read-Only/descriptions.json +++ b/.automation/Read-Only/descriptions.json @@ -91,4 +91,4 @@ } } ] -} +} \ No newline at end of file diff --git a/.automation/index.py b/.automation/index.py index 63792f7..88c7c25 100644 --- a/.automation/index.py +++ b/.automation/index.py @@ -2,60 +2,135 @@ import glob import json import httpx +import logging +import chardet + +# Configure logging +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" +) TOP_LEVEL_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) AUTOMATION_DIR = os.path.dirname(os.path.abspath(__file__)) -DIRECTORY_LIST = [ y for y in glob.glob(os.path.join(TOP_LEVEL_DIR, '*')) if os.path.isdir(y) ] -DIRECTORY_LIST.sort() - -SUB_DIRECTORY_LIST = [ y for x in DIRECTORY_LIST for y in glob.glob(os.path.join(x, '*')) if os.path.isdir(y) ] -SUB_DIRECTORY_LIST.sort() -# call the CTF Time API from the url in event.txt - -with open(os.path.join(AUTOMATION_DIR, 'Change-Me/event.txt'), 'r') as f: - event_url = f.read() - # generate the api url from the event url - api_url = event_url.replace('ctftime.org/event/', 'ctftime.org/api/v1/events/') - -# get the event description from the api url -r = httpx.get(api_url + '/') -event_description = r.json()['description'] -event_name = r.json()['title'] - -# Open the descriptions file and read the descriptions into a list -with open(os.path.join(AUTOMATION_DIR, 'Read-Only/descriptions.json'), 'r') as f: - descriptions = json.load(f) - -# generate the README.md file. -# generate an unordered list of the directories and subdirectories in the repository. -# should be in the format of: -# * [directory name](directory link) -# * [subdirectory name](subdirectory link) -# * [subdirectory name](subdirectory link) -# and so on... - -with open(os.path.join(TOP_LEVEL_DIR, 'README.md'), 'w') as f: - f.write('# ' + event_name + '\n\n') - f.write(event_url + '\n\n') - f.write('## Event Description\n\n') - f.write(event_description + '\n\n') + +def fetch_event_details(event_url): + try: + api_url = event_url.replace("ctftime.org/event/", "ctftime.org/api/v1/events/") + r = httpx.get(api_url + "/") + r.raise_for_status() # Raise an exception for non-2xx status codes + event_details = r.json() + return event_details["description"], event_details["title"] + except (httpx.HTTPError, json.JSONDecodeError, KeyError) as e: + logging.error(f"Error fetching event details: {e}") + return None, None + + +def read_descriptions(file_path): + try: + with open(file_path, "rb") as f: + result = chardet.detect(f.read()) + encoding = result["encoding"] + with open(file_path, "r", encoding=encoding) as f: + descriptions = json.load(f) + return descriptions + except (FileNotFoundError, json.JSONDecodeError, UnicodeDecodeError) as e: + logging.error(f"Error reading descriptions file: {e}") + return None + + +def generate_readme( + event_name, + event_url, + event_description, + directory_list, + subdirectory_list, + descriptions, + output_path, +): + try: + with open(output_path, "w", encoding="utf-8") as f: + f.write(f"# {event_name}\n\n") + f.write(f"{event_url}\n\n") + f.write("## Event Description\n\n") + f.write(f"{event_description}\n\n") + for directory in directory_list: + directory_name = os.path.basename(directory) + f.write(f"## [{directory_name}](<{directory_name}/>)\n") + for subdirectory in subdirectory_list: + if os.path.dirname(subdirectory) == directory: + subdirectory_name = os.path.basename(subdirectory) + f.write( + f" * #### [{subdirectory_name}](<{directory_name}/{subdirectory_name}/>)\n" + ) + except IOError as e: + logging.error(f"Error writing to {output_path}: {e}") + + +def main(): + DIRECTORY_LIST = [ + os.path.normpath(y) + for y in glob.glob(os.path.join(TOP_LEVEL_DIR, "*")) + if os.path.isdir(y) + ] + DIRECTORY_LIST.sort() + + SUB_DIRECTORY_LIST = [ + os.path.normpath(y) + for x in DIRECTORY_LIST + for y in glob.glob(os.path.join(x, "*")) + if os.path.isdir(y) + ] + SUB_DIRECTORY_LIST.sort() + + event_file_path = os.path.join(AUTOMATION_DIR, "Change-Me", "event.txt") + descriptions_file_path = os.path.join( + AUTOMATION_DIR, "Read-Only", "descriptions.json" + ) + + try: + with open(event_file_path, "r") as f: + event_url = f.read().strip() + except FileNotFoundError: + logging.error(f"Event file '{event_file_path}' not found.") + return + + event_description, event_name = fetch_event_details(event_url) + if event_description is None or event_name is None: + return + + descriptions = read_descriptions(descriptions_file_path) + if descriptions is None: + return + + top_level_readme_path = os.path.join(TOP_LEVEL_DIR, "README.md") + generate_readme( + event_name, + event_url, + event_description, + DIRECTORY_LIST, + SUB_DIRECTORY_LIST, + descriptions, + top_level_readme_path, + ) + for directory in DIRECTORY_LIST: - f.write('## [{}](<{}>)\n'.format(os.path.basename(directory), os.path.basename(directory))) - for subdirectory in SUB_DIRECTORY_LIST: - if os.path.dirname(subdirectory) == directory: - f.write(' * #### [{}](<{}/{}/>)\n'.format(os.path.basename(subdirectory), os.path.basename(directory), os.path.basename(subdirectory) )) - -# do the same thing for the README in each directory -for directory in DIRECTORY_LIST: - with open(os.path.join(directory, 'README.md'), 'w') as f: - f.write('# ' + os.path.basename(directory) + '\n\n') - # From the descriptions var, check if the directory name is contained in the category and if so, write the description to the README - f.write('### Category Description\n\n') - for category in descriptions['categories']: - if os.path.basename(directory) in category['name']: - f.write(category['details']['description'] + '\n\n') - f.write('## Challenges\n\n') - for subdirectory in SUB_DIRECTORY_LIST: - if os.path.dirname(subdirectory) == directory: - f.write('- ### [{}](<{}>)\n'.format(os.path.basename(subdirectory), os.path.basename(subdirectory))) \ No newline at end of file + directory_readme_path = os.path.join(directory, "README.md") + with open(directory_readme_path, "w", encoding="utf-8") as f: + f.write(f"# {os.path.basename(directory)}\n\n") + f.write("### Category Description\n\n") + for category in descriptions["categories"]: + if os.path.basename(directory) in category["name"]: + f.write(f"{category['details']['description']}\n\n") + f.write("## Challenges\n\n") + for subdirectory in SUB_DIRECTORY_LIST: + if os.path.dirname(subdirectory) == directory: + f.write( + f"- ### [{os.path.basename(subdirectory)}](<{os.path.basename(subdirectory)}/>)\n" + ) + + logging.info("README files generated successfully.") + + +if __name__ == "__main__": + main() diff --git a/Crypto/README.md b/Crypto/README.md index 822da87..56f9842 100644 --- a/Crypto/README.md +++ b/Crypto/README.md @@ -6,4 +6,4 @@ The word “cryptography” technically means the art of writing codes. When it ## Challenges -- ### [Example]() +- ### [Example]() diff --git a/README.md b/README.md index 53d03bc..c7f890c 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,21 @@ -# MapleCTF 2023 - -https://ctftime.org/event/2038 - -## Event Description - -Maple Bacon's jeopardy-style MapleCTF! Featuring challenges in web, pwn, rev, crypto and more. - -## [Crypto]() - * #### [Example]() -## [Forensics]() -## [Misc]() -## [OSINT]() -## [Pwn]() -## [Reverse]() -## [Steganography]() -## [Web]() -## [Blockchain]() \ No newline at end of file +# MapleCTF 2023 + +https://ctftime.org/event/2038 + +## Event Description + +Maple Bacon's jeopardy-style MapleCTF! Featuring challenges in web, pwn, rev, crypto and more. + + +Thank you to our prizes sponsors – Zellic, Trail of Bits, HackerOne, Offensive Security, and Vector35! Infrastructure sponsored by GCP. + +## [Blockchain]() +## [Crypto]() + * #### [Example]() +## [Forensics]() +## [Misc]() +## [OSINT]() +## [Pwn]() +## [Reverse]() +## [Steganography]() +## [Web]() From c215ebbb77a2be9233e87a871b3acba6e8c55e77 Mon Sep 17 00:00:00 2001 From: daVinci Date: Sun, 21 Apr 2024 11:20:12 -0700 Subject: [PATCH 2/2] updated reqs doc for not failing reasons. --- .automation/Read-Only/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.automation/Read-Only/requirements.txt b/.automation/Read-Only/requirements.txt index 7922838..a516f6a 100644 --- a/.automation/Read-Only/requirements.txt +++ b/.automation/Read-Only/requirements.txt @@ -1 +1,2 @@ -httpx \ No newline at end of file +chardet==4.0.0 +httpx==0.27.0 \ No newline at end of file