Skip to content

Commit fe6469f

Browse files
authored
Update and rename ArborBuilder.sh to ArborBuilder.py
1 parent e6ee64e commit fe6469f

File tree

2 files changed

+200
-58
lines changed

2 files changed

+200
-58
lines changed

ArborBuilder.py

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
import requests
2+
import json
3+
4+
# Function to display an ASCII art banner
5+
def print_banner():
6+
print(r'''
7+
_____ _ _ _____ _
8+
| _ |___ ___ |_|___ ___| |_| _ |___| |_ ___ ___ v2.0.0
9+
| __| _| . | | | -_| _| _| | _| . | . | _|
10+
|__| |_| |___|_| |___|___|_| |__|__|_| |___|___|_|
11+
|___|
12+
13+
''')
14+
print_banner()
15+
16+
# Output file for saving file and directory names
17+
OUTPUT_FILE = "github_project_tree.txt"
18+
CONFIG_LOG_FILE = "GithubConfigLog.json"
19+
TOKENS_FILE = "GithubTokens.config"
20+
21+
# GitHub API base URL
22+
GITHUB_API_URL = "https://api.github.com"
23+
24+
# Function to fetch file and directory names recursively
25+
def fetch_files_and_directories(url, indent):
26+
# Fetch the list of files and directories from the GitHub API
27+
headers = {"Authorization": f"token {TOKEN}"} if TOKEN else {}
28+
response = requests.get(url, headers=headers)
29+
response.raise_for_status()
30+
entries = response.json()
31+
32+
# Output the items with appropriate indentation, filtering out invalid characters
33+
for entry in entries:
34+
entry_name = entry["name"]
35+
36+
# Check if the entry contains any control characters or invalid characters
37+
if any(ord(c) < 32 or ord(c) == 127 for c in entry_name):
38+
continue
39+
40+
# Check if the entry is a directory
41+
is_directory = entry["type"]
42+
43+
if is_directory == "dir":
44+
# If it's a directory, create a corresponding entry in the output
45+
with open(OUTPUT_FILE, "a", encoding="utf-8") as file:
46+
file.write(f"{indent} ├── {entry_name}\n")
47+
# Recursively fetch files and directories within this directory
48+
fetch_files_and_directories(entry["url"], f"{indent} │")
49+
else:
50+
# If it's a file, create an entry without the trailing "/"
51+
with open(OUTPUT_FILE, "a", encoding="utf-8") as file:
52+
file.write(f"{indent} └── {entry_name}\n")
53+
54+
# Function to display previous configurations and get user input for selection
55+
def select_previous_config():
56+
print("Previous Configurations:")
57+
58+
try:
59+
with open(CONFIG_LOG_FILE, "r") as config_file:
60+
previous_configs = [json.loads(line) for line in config_file if line.strip()]
61+
except (FileNotFoundError, json.JSONDecodeError):
62+
previous_configs = []
63+
64+
username_dict = {}
65+
66+
for config in previous_configs:
67+
if isinstance(config, dict):
68+
username = config.get("USERNAME", "Unknown")
69+
token_name = config.get("TOKEN_NAME", "Unknown")
70+
token = get_token_by_name(token_name)
71+
72+
if username not in username_dict:
73+
# Fetch public repositories for the user
74+
repositories = get_public_repositories(username)
75+
username_dict[username] = {"TOKEN": token, "REPOS": repositories}
76+
77+
for i, username in enumerate(username_dict.keys(), start=1):
78+
print(f"{i}. {username}")
79+
80+
try:
81+
choice_username = int(input("Enter the number to select a username or 0 for new input: "))
82+
if choice_username == 0:
83+
return get_user_input()
84+
else:
85+
selected_username = list(username_dict.keys())[choice_username - 1]
86+
except (ValueError, IndexError):
87+
print("Invalid choice. Exiting.")
88+
exit()
89+
90+
# Display public repositories as options
91+
print(f"Public Repositories for {selected_username}:")
92+
for i, repo in enumerate(username_dict[selected_username]["REPOS"], start=1):
93+
print(f"{i}. {repo}")
94+
95+
try:
96+
choice_repo = int(input("Enter the number to select a repository or 0 for new input: "))
97+
if choice_repo == 0:
98+
return get_user_input()
99+
else:
100+
selected_repo = username_dict[selected_username]["REPOS"][choice_repo - 1]
101+
except (ValueError, IndexError):
102+
print("Invalid choice. Exiting.")
103+
exit()
104+
105+
return {"USERNAME": selected_username, "REPO": selected_repo, "TOKEN": username_dict[selected_username]["TOKEN"]}
106+
107+
# Function to fetch public repositories for a GitHub user
108+
def get_public_repositories(username):
109+
url = f"{GITHUB_API_URL}/users/{username}/repos"
110+
response = requests.get(url)
111+
response.raise_for_status()
112+
repositories = [repo["name"] for repo in response.json()]
113+
return repositories
114+
115+
# Function to display previous tokens and get user input for selection
116+
def select_previous_tokens():
117+
print("Previous Tokens:")
118+
119+
try:
120+
with open(TOKENS_FILE, "r") as tokens_file:
121+
tokens = [line.strip() for line in tokens_file if line.strip()]
122+
except FileNotFoundError:
123+
tokens = []
124+
125+
for i, token in enumerate(tokens, start=1):
126+
print(f"{i}. {token}")
127+
128+
try:
129+
choice_token = int(input("Enter the number to select a token or 0 for new input: "))
130+
if choice_token == 0:
131+
new_token = input("Enter the new token: ")
132+
add_token(new_token)
133+
return new_token
134+
else:
135+
selected_token = tokens[choice_token - 1]
136+
return selected_token
137+
except (ValueError, IndexError):
138+
print("Invalid choice. Exiting.")
139+
exit()
140+
141+
# Function to add a new token to the tokens file
142+
def add_token(token):
143+
with open(TOKENS_FILE, "a") as tokens_file:
144+
tokens_file.write(f"{token}\n")
145+
146+
# Function to get a token by its name
147+
def get_token_by_name(token_name):
148+
try:
149+
with open(TOKENS_FILE, "r") as tokens_file:
150+
tokens = [line.strip() for line in tokens_file if line.strip()]
151+
return tokens[0] if token_name in tokens else None
152+
except FileNotFoundError:
153+
return None
154+
155+
# Function to get user input for GitHub configuration
156+
def get_user_input():
157+
username = input("Enter your GitHub username: ")
158+
token = select_previous_tokens()
159+
160+
# Fetch live public repositories for the user
161+
repositories = get_public_repositories(username)
162+
163+
# Display public repositories as options
164+
print(f"Public Repositories for {username}:")
165+
for i, repo in enumerate(repositories, start=1):
166+
print(f"{i}. {repo}")
167+
168+
try:
169+
choice_repo = int(input("Enter the number to select a repository or 0 for new input: "))
170+
if choice_repo == 0:
171+
return get_user_input()
172+
else:
173+
selected_repo = repositories[choice_repo - 1]
174+
except (ValueError, IndexError):
175+
print("Invalid choice. Exiting.")
176+
exit()
177+
178+
return {"USERNAME": username, "REPO": selected_repo, "TOKEN": token}
179+
180+
# Initialize the output file
181+
with open(OUTPUT_FILE, "w", encoding="utf-8") as file:
182+
file.write("## Project Directory/Structure/Tree \n .\n\n")
183+
184+
# Get user input for GitHub configuration
185+
config = select_previous_config()
186+
187+
# Set the GitHub username, repository name, and personal access token
188+
USERNAME = config["USERNAME"]
189+
REPO = config["REPO"]
190+
TOKEN = config["TOKEN"]
191+
192+
# Save the entered configuration to the log file
193+
with open(CONFIG_LOG_FILE, "a") as config_file:
194+
json.dump(config, config_file)
195+
config_file.write("\n")
196+
197+
# Start fetching files and directories for the root directory
198+
fetch_files_and_directories(f"{GITHUB_API_URL}/repos/{USERNAME}/{REPO}/contents", "")
199+
200+
print(f"Project structure saved in {OUTPUT_FILE}")

ArborBuilder.sh

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)