Skip to content

Instantly share code, notes, and snippets.

@GabriOliv
Last active April 26, 2021 13:36
Show Gist options
  • Save GabriOliv/287a3166a0ca5ad92b4199ddce611adc to your computer and use it in GitHub Desktop.
Save GabriOliv/287a3166a0ca5ad92b4199ddce611adc to your computer and use it in GitHub Desktop.
Python + GithubAPI; Script to clone public Repos and Gists.
#!/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")
@GabriOliv
Copy link
Author

GabriOliv commented Apr 15, 2021

Terminal Output

Start End
clone_script_python_01 clone_script_python_02

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment