[+] api
This commit is contained in:
@@ -150,3 +150,4 @@ cython_debug/
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
||||
data/
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, Body
|
||||
from starlette.responses import RedirectResponse, HTMLResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
links = {}
|
||||
last_id = 0
|
||||
|
||||
data_path = Path('data')
|
||||
links_path = data_path / 'short-links.json'
|
||||
last_id_path = data_path / 'last_id.txt'
|
||||
|
||||
# Removed lower l
|
||||
chars = 'abcdefghijkmnopqrstuvwxyz'
|
||||
base = len(chars)
|
||||
|
||||
|
||||
def store():
|
||||
data_path.mkdir(parents=True, exist_ok=True)
|
||||
links_path.write_text(json.dumps(links))
|
||||
last_id_path.write_text(str(last_id))
|
||||
|
||||
|
||||
def load():
|
||||
global links
|
||||
global last_id
|
||||
links = json.loads(links_path.read_text()) if links_path.is_file() else {}
|
||||
last_id = int(last_id_path.read_text()) if last_id_path.is_file() else 0
|
||||
|
||||
|
||||
def encode(plain: int) -> str:
|
||||
cipher = ''
|
||||
while plain != 0:
|
||||
digit = int(plain % base)
|
||||
cipher += chars[digit]
|
||||
plain = (plain - digit) // base
|
||||
return cipher
|
||||
|
||||
|
||||
def decode(s: str) -> int:
|
||||
total = 0
|
||||
for i, token in enumerate(s):
|
||||
digit = chars.index(token)
|
||||
assert digit != -1, f'Unknown char: {token}'
|
||||
total += digit * int(base ** i)
|
||||
return total
|
||||
|
||||
|
||||
@app.get('/{short}')
|
||||
def expand(short: str):
|
||||
print(short)
|
||||
print(links)
|
||||
if short in links:
|
||||
return RedirectResponse(links[short])
|
||||
else:
|
||||
return HTMLResponse('404', status_code=404)
|
||||
|
||||
|
||||
@app.get('/')
|
||||
def get():
|
||||
return "TODO"
|
||||
|
||||
|
||||
@app.put('/')
|
||||
def put(name: str | None = None, body: str = Body()):
|
||||
global last_id
|
||||
|
||||
# Generate name
|
||||
while not name:
|
||||
last_id += 1
|
||||
name = encode(last_id)
|
||||
if name in links:
|
||||
name = None
|
||||
|
||||
# Put name
|
||||
links[name] = body
|
||||
store()
|
||||
|
||||
return f'/{name}'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
load()
|
||||
uvicorn.run(app)
|
||||
|
||||
Reference in New Issue
Block a user