summaryrefslogtreecommitdiff
path: root/api.py
blob: 776395ec96d43041c03e667913aaed4c69bb99be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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)