| 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} |
|
|