80 lines
2.7 KiB
Python
80 lines
2.7 KiB
Python
|
import base64
|
||
|
import struct
|
||
|
import io
|
||
|
import zipfile
|
||
|
from typing import List, Optional
|
||
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
||
|
from sqlalchemy.orm import Session
|
||
|
from ..dependencies import get_db
|
||
|
from ..schemas import *
|
||
|
from ..utils import crc32, map_model_to_out_schema
|
||
|
from ..models import *
|
||
|
from ..config import config
|
||
|
|
||
|
|
||
|
router = APIRouter()
|
||
|
|
||
|
MAX_UPLOAD_SIZE = config["max_file_size"]
|
||
|
|
||
|
|
||
|
@router.get("/maps", tags=["maps"], response_model=List[MapOut])
|
||
|
async def get_all_maps(db: Session = Depends(get_db)):
|
||
|
return [map_model_to_out_schema(m) for m in db.query(Map).all()]
|
||
|
|
||
|
|
||
|
@router.get("/map", tags=["maps"], response_model=MapOut)
|
||
|
async def get_map_by_crc(human_crc: Optional[str] = Query(None, min_length=8, max_length=8),
|
||
|
crc: Optional[int] = Query(None),
|
||
|
db: Session = Depends(get_db)):
|
||
|
|
||
|
if not human_crc and not crc:
|
||
|
raise HTTPException(status_code=400, detail="Please use crc or human_crc but not both")
|
||
|
if human_crc and crc:
|
||
|
raise HTTPException(status_code=400, detail="Please use crc or human_crc but not both")
|
||
|
|
||
|
if human_crc:
|
||
|
crc_int = struct.unpack(">L", bytes.fromhex(human_crc))[0]
|
||
|
else:
|
||
|
crc_int = crc
|
||
|
existing_map = db.query(Map).filter(Map.crc == crc_int).first()
|
||
|
if not existing_map:
|
||
|
raise HTTPException(status_code=404, detail="Map not found")
|
||
|
return map_model_to_out_schema(existing_map)
|
||
|
|
||
|
|
||
|
@router.post("/maps", tags=["maps"], response_model=MapOut)
|
||
|
async def upload_map(map_in: MapIn, db: Session = Depends(get_db)):
|
||
|
filename = map_in.name
|
||
|
if not filename.lower().endswith(".gck"):
|
||
|
raise HTTPException(status_code=400, detail="Invalid file")
|
||
|
|
||
|
map_bytes = base64.b64decode(map_in.b64_data.encode("utf8"))
|
||
|
if len(map_bytes) > MAX_UPLOAD_SIZE:
|
||
|
raise HTTPException(status_code=400, detail="File too big")
|
||
|
|
||
|
map_io = io.BytesIO(map_bytes)
|
||
|
try:
|
||
|
zipfile.ZipFile(map_io)
|
||
|
except zipfile.BadZipfile:
|
||
|
raise HTTPException(status_code=400, detail="File is not a valid map")
|
||
|
|
||
|
crc = crc32(map_bytes)
|
||
|
existing_map = db.query(Map).filter(Map.crc == crc).first()
|
||
|
if existing_map:
|
||
|
return map_model_to_out_schema(existing_map)
|
||
|
else:
|
||
|
uploaded_filename = "%s.gck" % crc
|
||
|
with open("%s%s" % (config["upload_path"], uploaded_filename), "wb") as fp:
|
||
|
fp.write(map_bytes)
|
||
|
|
||
|
uploaded_map = Map()
|
||
|
uploaded_map.crc = crc
|
||
|
uploaded_map.name = map_in.name
|
||
|
uploaded_map.filename = uploaded_filename
|
||
|
uploaded_map.size = len(map_bytes)
|
||
|
db.add(uploaded_map)
|
||
|
db.commit()
|
||
|
db.refresh(uploaded_map)
|
||
|
|
||
|
return map_model_to_out_schema(uploaded_map)
|