from fastapi import APIRouter from pgsoft.pgdate.date_utils import beijing from pgsoft.pghash.md5 import md5 import pgsoft.pgfile as pgfile from time import sleep import json import os router = APIRouter(prefix="/file", tags=["File Service"]) dataset_id = "pgsoft/game" tempdir = "game" pgai_code = os.environ.get("pgai_code") db_token = os.environ.get("db_token") if db_token: print(db_token[:5]) @router.get("/download") def download_file(game: str, token: str, gamecode: str): if token != pgai_code: print(f"[{beijing()}][download file] failed") return {"status": "Failure", "detail": "Invalid token"} game = game.strip().lower() filename = gamecode.strip() + ".json" remotepath = "/".join([game, filename[:2], filename]) res = pgfile.download( dataset_id, remotepath=remotepath, repo_type="dataset", localdir=tempdir, token=db_token, ) if not res: print(f"[{beijing()}][download file] failed") return {"status": "Failure", "detail": "File not found or server error"} with open(res, "r") as f: outp = json.load(f) print(f"[{beijing()}][download file] OK") return {"status": "OK", "result": outp} @router.post("/upload") def upload_file(game: str, token: str, content: str): if token != pgai_code: print(f"[{beijing()}][upload file] failed") return {"status": "Failure", "detail": "Invalid token"} game = game.strip().lower() try: content_dict = json.loads(content) except json.JSONDecodeError as e: print(f"[{beijing()}][upload file] failed, {type(e)}: {e}") return {"status": "Failure", "detail": "Invalid JSON"} if not isinstance(content_dict, dict): print(f"[{beijing()}][upload file] failed, not a dict") return {"status": "Failure", "detail": "not a dict"} needed_keys = ["game-file", "device-id"] for key in needed_keys: if key not in content_dict: print(f'[{beijing()}][upload file] failed, missed "{key}"') return {"status": "Failure", "detail": f'missed "{key}"'} if not isinstance(content_dict["device-id"], str): print(f'[{beijing()}][upload file] failed, "device-id" is not a str') return {"status": "Failure", "detail": '"device-id" is not a str'} if not isinstance(content_dict["game-file"], dict): print(f'[{beijing()}][upload file] failed, "game-file" is not a dict') return {"status": "Failure", "detail": '"game-file" is not a dict'} obj = { "upload-time": beijing().__str__(), "game-file": content_dict["game-file"], } maxtry = 5 for retry in range(maxtry): md5code = md5(obj) remotepath = "/".join([game, md5code[:2], md5code + ".json"]) if not pgfile.api.file_exists( repo_id=dataset_id, filename=remotepath, repo_type="dataset", token=db_token, ): break sleep(0.1) obj["upload-time"] = beijing().__str__() maxtry -= 1 if not maxtry and pgfile.api.file_exists( repo_id=dataset_id, filename=remotepath, repo_type="dataset", token=db_token, ): print(f"[{beijing()}][upload file] failed, timeout, please retry") return {"status": "Failure", "detail": "timeout, please retry"} filedir = os.path.join(tempdir, game, md5code[:2]) if not os.path.exists(filedir): os.makedirs(filedir) filepath = os.path.join(filedir, md5code + ".json") content_indented = json.dumps(content_dict, indent=4) with open(filepath, "w") as f: f.write(content_indented) res = pgfile.upload( filepath, remotepath, dataset_id, "dataset", db_token, f"Updated at {beijing()}", ) if not res: print(f"[{beijing()}][upload file] failed") return {"status": "Failure", "detail": "server error"} print(f"[{beijing()}][upload file] OK") return {"status": "OK", "result": md5code} @router.get("/list") def list_files(game: str, token: str): if token != pgai_code: print(f"[{beijing()}][list files] failed") return {"status": "Failure", "detail": "Invalid token"} game = game.strip().lower() games = pgfile.list_files( repo_id=dataset_id, repo_type="dataset", token=db_token, ) if games is None: print(f"[{beijing()}][list files] failed") return {"status": "Failure", "detail": "server error"} games = { item.split(".")[0][-32:]: item for item in games if item.endswith(".json") and item.startswith(game) } print(f"[{beijing()}][list files] OK") return {"status": "OK", "result": games}