Last active
April 26, 2021 13:36
-
-
Save GabriOliv/287a3166a0ca5ad92b4199ddce611adc to your computer and use it in GitHub Desktop.
Python + GithubAPI; Script to clone public Repos and Gists.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3.8 | |
# python3.8 script_clone.py | |
#Modules Import | |
import math | |
import os | |
import requests | |
import sys | |
# CONST Color Terminal Output | |
# Colors | |
# 0 reset | |
# 1 bold | |
# 4 underline | |
# 30-37 normal fg colors | |
# 40-47 normal bg colors | |
# 90-97 bright fg colors | |
# 100-107 bright bg colors | |
# Sequence | |
# 38;5;(0-255)m fg colors | |
# 48;5;(0-255)m fg colors | |
# (30-37);5m blink normal fg colors | |
# (90-97);5m blink bright fg colors | |
RESET = '\u001b[0m' | |
CYAN = '\u001b[36m' | |
GRAY = '\u001b[90m' | |
RED = '\u001b[91m' | |
GREEN = '\u001b[92m' | |
class Github: | |
# Constructor | |
def __init__(self, username): | |
#Username | |
self.__username = username | |
# API URLs | |
self.__api_url_users = 'https://api.github.com/users/' + username | |
self.__api_url_repos = 'https://api.github.com/users/' + username + '/repos?per_page=50' | |
self.__api_url_gists = 'https://api.github.com/users/' + username + '/gists?per_page=50' | |
# Clone Option | |
# 0 = Nothing | |
# 1 = Repos | |
# 2 = Gist | |
self.__clone = 0 | |
# JSON Request Response | |
self.__json_users = None | |
self.__json_repos = None | |
self.__json_gists = None | |
# JSON Request SET | |
self.__set_json_users() | |
self.__set_json_repos() | |
self.__set_json_gists() | |
# GET __username | |
@property | |
def username(self): | |
return self.__username | |
# GET __api_url_users | |
@property | |
def users(self): | |
return self.__api_url_users | |
# GET __api_url_repos | |
@property | |
def repos(self): | |
return self.__api_url_repos | |
# GET __api_url_gists | |
@property | |
def gists(self): | |
return self.__api_url_gists | |
# GET __clone | |
@property | |
def clone(self): | |
return self.__clone | |
# SET __clone | |
@clone.setter | |
def clone(self,choice): | |
self.__clone = choice | |
# GET __json_users | |
@property | |
def json_users(self): | |
return self.__json_users | |
# SET Private __json_users | |
def __set_json_users(self): | |
try: | |
response = requests.get(self.users) | |
assert response.status_code == 200 | |
except AssertionError: | |
print(RED + '[!] GitHub User not Found' + RESET) | |
exit() | |
else: | |
self.__json_users = response.json() | |
# GET __json_repos | |
@property | |
def json_repos(self): | |
return self.__json_repos | |
# SET Private __json_repos | |
def __set_json_repos(self): | |
try: | |
response = requests.get(self.repos) | |
assert response.status_code == 200 | |
except AssertionError: | |
print(RED + '[!] GitHub User not Found' + RESET) | |
exit() | |
else: | |
self.__json_repos = response.json() | |
# GET __json_gists | |
@property | |
def json_gists(self): | |
return self.__json_gists | |
# SET Private __json_gists | |
def __set_json_gists(self): | |
try: | |
response = requests.get(self.gists) | |
assert response.status_code == 200 | |
except AssertionError: | |
print(RED + '[!] GitHub User not Found' + RESET) | |
exit() | |
else: | |
self.__json_gists = response.json() | |
def download(self): | |
if self.clone == '1': | |
self.__git_clone_repos() | |
elif self.clone == '2': | |
self.__git_clone_gists() | |
else: | |
print(RED + 'Download Parameter Not Set' + RESET) | |
# GIT_CLONE_REPOS Private | |
def __git_clone_repos(self): | |
# Repos Total | |
total = len(self.json_repos) | |
# Dir Creation | |
os.system("mkdir repos_" + self.username.lower()) | |
os.chdir(os.path.abspath(os.curdir) + "/repos_" + self.username.lower()) | |
# Step Counter | |
counter = 0 | |
#Element Access | |
for element in self.json_repos: | |
counter += 1 | |
draw_progress(total,counter) | |
# Progress Bar Draw | |
print(" (" + str(counter).zfill(2) + ") -", CYAN + element['name'] + RESET) | |
print("URL: " + CYAN + element['git_url'].lower() + RESET) | |
# GIT CLONE Command | |
print(GRAY, end="") | |
os.system('git clone --quiet ' + element['git_url']) | |
print(RESET, end="") | |
# Clear Last Output | |
sys.stdout.write("\033[K \033[F" * 2) | |
# GIT_CLONE_GISTS Private | |
def __git_clone_gists(self): | |
# Repos Total | |
total = len(self.json_gists) | |
# Dir Creation | |
os.system("mkdir gists_" + self.username.lower()) | |
os.chdir(os.path.abspath(os.curdir) + "/gists_" + self.username.lower()) | |
# Step Counter | |
counter = 0 | |
#Element Access | |
for element in self.json_gists: | |
counter += 1 | |
draw_progress(total,counter) | |
gist_name = '' | |
objkeys = element['files'].keys() | |
# Gist Names | |
for files in element['files']: | |
gist_name = files | |
break | |
# Progress Bar Draw | |
print(" (" + str(counter).zfill(2) + ") -", CYAN + gist_name + RESET) | |
print("URL: " + CYAN + element['git_pull_url'].lower() + RESET) | |
# GIT CLONE Command | |
print(GRAY, end="") | |
os.system('git clone --quiet ' + element['git_pull_url'] + " " + gist_name) | |
print(RESET, end="") | |
# Clear Last Output | |
sys.stdout.write("\033[K \033[F" * 2) | |
# String Function Overloading | |
def __str__(self): | |
return ( | |
'\nGit: ' + GREEN + str(profile.json_users['login']) + RESET + | |
'\tName: ' + GREEN + str(profile.json_users['name']) + RESET + | |
'\n\nBlog: ' + CYAN + str(profile.json_users['blog']) + RESET + | |
'\nLocation: ' + CYAN + str(profile.json_users['location']) + RESET + | |
'\nCompany: ' + CYAN + str(profile.json_users['company']) + RESET + | |
'\nBio: ' + GRAY + str(profile.json_users['bio'])[:60] + RESET + | |
'\n\nRepos: ' + CYAN + str(profile.json_users['public_repos']) + RESET + | |
'\tGists: ' + CYAN + str(profile.json_users['public_gists']) + RESET + | |
'\n\nFollow-> in:' + CYAN + str(profile.json_users['followers']) + RESET + | |
'\t out:' + CYAN + str(profile.json_users['following']) + RESET + | |
'\nCreated: ' + CYAN + str(profile.json_users['created_at']) + RESET | |
) | |
def size_format(total_size): | |
if total_size < 1024: | |
return str(round(total_size,2)) + ' KB' | |
elif total_size < 1048576: | |
total_size = total_size / (1024) | |
return str(round(total_size,2)) + ' MB' | |
else: | |
total_size = total_size / (1024*1024) | |
return str(round(total_size,2)) + ' GB' | |
def draw_progress(total,progress): | |
# Ratio Progress | |
ratio = (progress / total) | |
# Progress String | |
progress = ratio / 0.1 | |
# Percent Step | |
step = math.floor(progress) | |
# Bar Draw | |
print("[", end="") | |
for i in range(step): | |
print(CYAN + "#" + RESET, end="") | |
for i in range(10-step): | |
print("_", end="") | |
print("][" + str(round(progress*10, 1)).zfill(5)+"%]", end="") | |
# Main Entry Point | |
print('\u001b[1m\u001b[33m\u001b[44m' + ' Python ' + RESET + '\u001b[30m\u001b[47m' + ' + ' + RESET + '\u001b[1m\u001b[35m\u001b[40m' + ' GitHub.API ' + RESET + "\n\n") | |
# https://api.github.com/ | |
# Ask username | |
username = str(input('Enter the GitHub Username: ')).lower() | |
# Loading MSG | |
print(GREEN + 'Loading ...' + RESET) | |
# Create Object | |
profile = Github(username) | |
# Loading MSG REMOVE | |
sys.stdout.write("\033[K \033[F" * 2) | |
# HEAD INFO Output | |
print(profile) | |
# Print Size Repos | |
download_size = 0 | |
for repos in profile.json_repos: | |
download_size += repos['size'] | |
print('\n\nAPI limit of ' + RED + '50' + RESET + ' element ') | |
print('Repos: ' + GREEN + str(len(profile.json_repos)) + RESET, end='\t') | |
print('Size: ' + GREEN + size_format(download_size) + RESET) | |
# Print Size Gists | |
download_size = 0 | |
for gist in profile.json_gists: | |
objkeys = gist['files'].keys() | |
for key in objkeys: | |
download_size += gist['files'][key]['size'] | |
print('Gists: ' + GREEN + str(len(profile.json_gists)) + RESET, end='\t') | |
print('Size: ' + GREEN + size_format(download_size) + RESET) | |
# Exception Download | |
try: | |
profile.clone = input("\n[" + GREEN + "1" + RESET + "] Repositories\n[" + GREEN + "2" + RESET + "] Gists Codes\nDownload:") | |
assert int(profile.clone) == 1 or int(profile.clone) == 2 | |
except AssertionError: | |
print("\n\t" + RED + "[!] Wrong Option" + RESET) | |
exit() | |
except ValueError: | |
print("\n\t" + RED + "[!] Value Error" + RESET) | |
exit() | |
# Label Start Clone Tree | |
print(GREEN + "\n\n[!] Cloning ...\n" + RESET) | |
# Download Step | |
profile.download() | |
# Remove Loading Bar | |
sys.stdout.write("\033[K \033[F" * 3) | |
# Done MSG | |
print("\n" + GREEN + "[!] Done" + RESET + "\n\n") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Terminal Output