diff options
Diffstat (limited to 'api.py')
-rw-r--r-- | api.py | 57 |
1 files changed, 57 insertions, 0 deletions
@@ -0,0 +1,57 @@ +import hmac +import hashlib +import traceback +import itertools +import time +import os + +from tqdm import tqdm +from filecrypt import key_id, token_b64encode + +_retry_range = lambda retries: itertools.cycle([None]) if retries is None else range(retries) + +def upload(path, file_id, size, base_url, api_key, chunk_size=int(10e6), progress=True, max_retries=None): + import requests + + with tqdm(total=size, unit='B', unit_scale=True, disable=(not progress)) as pbar, open(path, 'rb') as f: + pos = 0 + while True: + chunk = f.read(chunk_size) + if not chunk: + break + + hash = hashlib.sha3_256() + hash.update(chunk) + hash = hash.digest() + + content_range = f'bytes {pos}-{pos+len(chunk)-1}/{size}' + pos += len(chunk) + + mac = hmac.new(api_key, digestmod='sha3_256') + mac.update(file_id.encode()) + mac.update(hash) + mac.update(content_range.encode()) + + post_url = '/'.join([ + base_url, + key_id(api_key), + file_id, + token_b64encode(mac.digest()), + token_b64encode(hash)]) + + for attempt in _retry_range(max_retries): + try: + res = requests.post(post_url, files={'chunk': chunk}, headers={'content-range': content_range}) + break + except requests.exceptions.RequestException as e: + print(f'Upload error: {type(e).__name__}') + time.sleep(1) + print('Retrying.') + else: + print(f'Repeated errors uploading. Exiting.') + print(f'Leaving encrypted file under: {path}') + sys.exit(1) + pbar.update(len(chunk)) + + os.remove(path) + |