Last active
December 29, 2023 07:11
-
-
Save notpushkin/5a4f10e07a9b9c994d74d2be37920da9 to your computer and use it in GitHub Desktop.
Use Netlify as a personal pomf / dropbox
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 | |
""" | |
Usage: | |
pomflify.py inputfile [filename for url] | |
pomflify.py '~/Music/Empty streets.flac' "$(pwgen 6 1).flac" | |
Author: Alexander Pushkov <alexander@notpushk.in> | |
License: ISC (https://opensource.org/licenses/ISC) | |
""" | |
import os | |
import json | |
import math | |
import hashlib | |
from urllib.parse import quote as urlquote | |
import requests | |
try: | |
raise ImportError # tqdm doesn't work yet | |
from tqdm import tqdm as _tqdm | |
class tqdm(_tqdm): | |
def __bool__(self): | |
return True | |
except ImportError: | |
tqdm = lambda it, *a, **kw: it | |
def parse_config(): | |
loc = os.path.expanduser("~/.config/pomflify.json") | |
try: | |
with open(loc) as f: | |
return json.load(f) | |
except: | |
print( | |
"Put this in ~/.config/pomflify.json:\n\n" + | |
json.dumps({ | |
"api_root": "(optional)", | |
"token": "(your token from Netlify)", | |
"site_id": "(domain or API ID of your Netlify site)" | |
}, indent=4) + | |
"\n" | |
) | |
raise | |
def url(cfg, path): | |
api_root = cfg.get("api_root", "https://api.netlify.com/api/v1/") | |
return f"{api_root}{path.lstrip('/')}?access_token={cfg['token']}" | |
def iter_file(f): | |
while True: | |
data = f.read(1024) | |
if not data: | |
break | |
yield data | |
def hash_file(f): | |
sha1 = hashlib.sha1() | |
for data in iter_file(f): | |
sha1.update(data) | |
f.seek(0) | |
return sha1.hexdigest() | |
def main(cfg, file_path, file_name=None): | |
if file_name is None: | |
file_name = os.path.basename(file_path).replace(" ", "_") | |
file_obj = open(file_path, "rb") | |
file_hash = hash_file(file_obj) | |
r = requests.get(url(cfg, f"sites/{cfg['site_id']}")) | |
r.raise_for_status() | |
deploy_id = r.json()["published_deploy"]["id"] | |
r = requests.get(url(cfg, f"deploys/{deploy_id}/files")) | |
r.raise_for_status() | |
old_files = {f["id"]: f["sha"] for f in r.json()} | |
print(old_files.keys()) | |
# if f"/{file_name}" in old_files: | |
# print(f"{file_name} already exists, aborting") | |
# raise SystemExit | |
r = requests.post(url(cfg, f"sites/{cfg['site_id']}/deploys"), json={ | |
"files": { | |
**old_files, | |
f"/{file_name}": file_hash, | |
} | |
}) | |
r.raise_for_status() | |
deploy = r.json() | |
required = deploy["required"] | |
try: | |
required.remove(file_hash) | |
except ValueError: | |
print("File already on Netlify CDN") | |
else: | |
itr = tqdm( | |
iter_file(file_obj), | |
unit='KB', | |
unit_scale=False, | |
total=math.ceil(os.path.getsize(file_path) / 1024), | |
) | |
r = requests.put(url(cfg, f"deploys/{deploy['id']}/files/{urlquote(file_name)}"), headers={ | |
"Content-type": "application/octet-stream" | |
}, data=itr) | |
r.raise_for_status() | |
assert len(required) == 0 | |
print(f"{deploy['url']}/{urlquote(file_name)}") | |
if __name__ == '__main__': | |
import sys | |
main(parse_config(), *sys.argv[1:]) |
Author
notpushkin
commented
Oct 8, 2018
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment