import json import pathlib import hashlib import requests import base64 import sys from os import geteuid import subprocess def compute_file_hash(filepath): with open(filepath, 'rb') as file_for_hash: data = file_for_hash.read() filesize = len(data) # Github sha value is computed as such: return hashlib.sha1(b"blob " + bytes(str(filesize), 'utf-8') + b"\0" + data).hexdigest() def get_info(repo, filepath): url = f"https://api.github.com/repos/{repo}/contents/{filepath}" r = requests.get(url) sha = r.json()['sha'] content = r.json()['content'] return sha, content def update(): with open("config.json", "r") as jsonfile: config = json.load(jsonfile) print("Updating...") for repo in config['githubfilesync']: for reponame, value in repo.items(): for filepath in value: localfile = pathlib.Path('files').joinpath(pathlib.Path(filepath).name) print(f" * {localfile} ", end='') lastsha, content = get_info(reponame, filepath) if not localfile.exists(): content = base64.b64decode(content) with open(localfile, 'wb') as f: f.write(content) print('-> Installed! ;)') else: sha = compute_file_hash(localfile) if sha == lastsha: print('-> Up-to-date.') else: content = base64.b64decode(content) with open(localfile, 'wb') as f: f.write(content) print('-> Updated!') def print_menu(menu_options): for key in menu_options.keys(): print(key, '->', menu_options[key]) def is_sudo(): return True if geteuid() == 0 else False def ask_port(default_port): while True: try: choice = input(f'What port would you like to listen on ? [{default_port}]: ') if choice == '': port = default_port else: port = int(choice) break except ValueError: print('Wrong input. Please enter a number ...') return port def listen_http(files_dir): port = ask_port(80) ips = get_ips() print('The HTTP server is about to start.\nAvailable endpoints:') for iname in ips: if port == 80: print(f' -> {iname}: http://{ips[iname]}/') else: print(f' -> {iname}: http://{ips[iname]}:{port}/') if port < 1024 and not is_sudo(): print('Listening on any port under 1024 requires root permissions.') cmd = ['sudo', 'python', '-m', 'http.server', '-d', files_dir, str(port)] else: cmd = ['python', '-m', 'http.server', '-d', files_dir, str(port)] subprocess.call(cmd) def listen_smb(files_dir): port = ask_port(445) ips = get_ips() print('The HTTP server is about to start.\nAvailable endpoints:') for iname in ips: if port == 445: print(f' -> {iname}: \\\\{ips[iname]}\\share\\') else: print(f' -> {iname}: \\\\{ips[iname]}:{port}\\share\\ # This syntax (:port) is not supported on Windows ?') if port < 1024 and not is_sudo(): print('Listening on any port under 1024 requires root permissions.') cmd = ['sudo', 'smbserver.py', '-port', str(port), 'share', files_dir] else: cmd = ['smbserver.py', '-port', str(port), 'share', files_dir] subprocess.call(cmd) def get_public_ip(): return requests.get('https://api.ipify.org').text def get_ips(): ips = dict() try: ips['public'] = get_public_ip() except requests.exceptions.ConnectionError: pass cmd = ['ip', 'a'] out = subprocess.run(cmd, capture_output=True).stdout.decode('utf-8') lines = out.split('\n') while("" in lines): lines.remove("") for line in lines: if line[0].isdigit(): iname = line.split(' ')[1].split(':')[0] if 'inet ' in line: ip = line.split(' ')[5].split('/')[0] if ip != '127.0.0.1': ips[iname] = ip return ips def menu_choice(menu_options): while(True): print_menu(menu_options) option = '' try: option = int(input('Enter your choice: ')) except ValueError: print('Wrong input. Please enter a number ...') files_dir = pathlib.Path.cwd().joinpath('files') if option == 1: listen_http(files_dir) elif option == 2: listen_smb(files_dir) elif option == 0: sys.exit('Quitting') else: print('Invalid option. Please enter a valid number.') if __name__ == '__main__': menu_options = { 1: 'HTTP', 2: 'SMB', 0: 'Exit', } update() menu_choice(menu_options)