Skip to content

Instantly share code, notes, and snippets.

@notpushkin
Last active December 29, 2023 07:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save notpushkin/5a4f10e07a9b9c994d74d2be37920da9 to your computer and use it in GitHub Desktop.
Save notpushkin/5a4f10e07a9b9c994d74d2be37920da9 to your computer and use it in GitHub Desktop.
Use Netlify as a personal pomf / dropbox
#!/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:])
@notpushkin
Copy link
Author

notpushkin commented Oct 8, 2018

# Bonus points if you add a redirect to this page (or any other if you want to):
$ cat > /tmp/_redirects
/ https://ale.sh/pomf

$ pomflify.py /tmp/_redirects

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