1
1
import os
2
2
import json
3
3
import hashlib
4
- from sqlalchemy import or_
5
- from typing import Optional , Dict
6
4
import redis
7
- from fastapi import FastAPI , HTTPException , BackgroundTasks , Request , Depends , Header
5
+ import uvicorn
6
+ from contextlib import asynccontextmanager
7
+ from fastapi import FastAPI , HTTPException , BackgroundTasks , Request , Header
8
8
from fastapi .responses import RedirectResponse , FileResponse
9
9
from fastapi .middleware .cors import CORSMiddleware
10
- from contextlib import asynccontextmanager
11
10
from sqlalchemy .orm import Session
12
- import uvicorn
11
+ from sqlalchemy import or_
12
+ from typing import Optional , Dict
13
+
13
14
from fetcher import fetch_genshin_impact_update , fetch_zzz_update , fetch_starrail_update
14
15
from api_config import game_name_id_map , DOCS_URL , ACCEPTED_LANGUAGES , LANGUAGE_PAIRS , TOKEN
15
16
from base_logger import logger
@@ -73,6 +74,18 @@ async def root():
73
74
74
75
@app .post ("/translate" , response_model = TranslateResponse , tags = ["translate" ])
75
76
async def translate (request_data : TranslateRequest , request : Request ):
77
+ """
78
+ Translate an item name to an item ID, or vice versa.
79
+
80
+ - **type**: "normal" or "reverse"
81
+ - **lang**: Language code (e.g. "en", "zh-cn")
82
+ - **game**: Game name (e.g. "genshin", "starrail")
83
+ - **item_name**: The item name to translate
84
+ - **item_id**: The item ID to translate
85
+
86
+ If **`normal`**, text -> item_id
87
+ If **`reverse`**, item_id -> text
88
+ """
76
89
db = request .app .state .mysql
77
90
# Normalize language
78
91
lang = request_data .lang .lower ()
@@ -105,7 +118,7 @@ async def translate(request_data: TranslateRequest, request: Request):
105
118
# It's a list of words
106
119
word_list = json .loads (word )
107
120
rows = (
108
- db .query (column_attr , getattr (type ( column_attr .property .parent .class_ ) , 'item_id' ))
121
+ db .query (column_attr , getattr (column_attr .property .parent .class_ , 'item_id' ))
109
122
.filter_by (game_id = game_id )
110
123
.filter (column_attr .in_ (word_list ))
111
124
.all ()
@@ -120,14 +133,14 @@ async def translate(request_data: TranslateRequest, request: Request):
120
133
return TranslateResponse (item_id = result_list )
121
134
else :
122
135
row = (
123
- db .query (getattr (type ( column_attr .property .parent .class_ ) , 'item_id' ))
136
+ db .query (getattr (column_attr .property .parent .class_ , 'item_id' ))
124
137
.filter_by (game_id = game_id )
125
138
.filter (column_attr == word )
126
139
.first ()
127
140
)
128
141
if not row :
129
142
raise HTTPException (status_code = 404 , detail = "Hash ID not found" )
130
- return TranslateResponse (item_id = row [0 ])
143
+ return TranslateResponse (item_id = row [0 ], item_name = word )
131
144
132
145
# ------------------------------------------------------------------
133
146
# Translate "reverse": from item_id -> text
@@ -145,9 +158,9 @@ async def translate(request_data: TranslateRequest, request: Request):
145
158
# It's a list
146
159
item_id_list = json .loads (item_id )
147
160
rows = (
148
- db .query (getattr (type ( column_attr .property .parent .class_ ) , 'item_id' ), column_attr )
161
+ db .query (getattr (column_attr .property .parent .class_ , 'item_id' ), column_attr )
149
162
.filter_by (game_id = game_id )
150
- .filter (getattr (type ( column_attr .property .parent .class_ ) , 'item_id' ).in_ (item_id_list ))
163
+ .filter (getattr (column_attr .property .parent .class_ , 'item_id' ).in_ (item_id_list ))
151
164
.all ()
152
165
)
153
166
id_to_text_map = {r [0 ]: r [1 ] for r in rows }
@@ -161,18 +174,16 @@ async def translate(request_data: TranslateRequest, request: Request):
161
174
)
162
175
if not row :
163
176
raise HTTPException (status_code = 404 , detail = "Word at this ID not found" )
164
- return TranslateResponse (item_name = row [0 ])
177
+ return TranslateResponse (item_name = row [0 ], item_id = item_id )
165
178
166
179
else :
167
180
raise HTTPException (status_code = 403 , detail = "Translate type not supported" )
168
181
169
182
170
183
def build_language_filter (word : str ):
171
- from sqlalchemy import or_
172
- from db .crud import ACCEPTED_LANGUAGES , get_lang_column
173
184
or_conditions = []
174
185
for lang_code in ACCEPTED_LANGUAGES :
175
- column_attr = get_lang_column (lang_code )
186
+ column_attr = crud . get_lang_column (lang_code )
176
187
or_conditions .append (column_attr == word )
177
188
return or_ (* or_conditions )
178
189
@@ -346,6 +357,7 @@ def force_refresh_local_data(this_game_name: str, db: Session, redis_client: red
346
357
347
358
@app .get ("/md5/{this_game_name}" , tags = ["checksum" ])
348
359
async def get_checksum (this_game_name : str , background_tasks : BackgroundTasks ):
360
+
349
361
if this_game_name not in game_name_id_map :
350
362
raise HTTPException (status_code = 403 , detail = "Game name not accepted" )
351
363
try :
@@ -375,11 +387,7 @@ def make_checksum(this_game_name: str):
375
387
]
376
388
# If none exist, force refresh
377
389
if len (file_list ) == 0 :
378
- force_refresh_local_data (g )
379
- file_list = [
380
- f for f in os .listdir (dict_path )
381
- if f .endswith (".json" ) and "md5" not in f
382
- ]
390
+ raise RuntimeError ("No Json files found, forcing refresh." )
383
391
384
392
checksum_dict = {}
385
393
for json_file in file_list :
0 commit comments