From 2c121c9a1e353d22182e1ca8ba1dcf0a6bbf69c7 Mon Sep 17 00:00:00 2001 From: Miyamizu-MitsuhaSang <2510681107@qq.com> Date: Mon, 15 Sep 2025 01:25:18 +0800 Subject: [PATCH] =?UTF-8?q?main.py:=20=E6=96=B0=E5=A2=9E=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20md5.py:=20=E7=BF=BB=E8=AF=91=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=AF=86=E9=92=A5=E5=A4=84=E7=90=86=E5=87=BD=E6=95=B0?= =?UTF-8?q?=20settings.py=20Settings=E7=B1=BB=E4=BE=9D=E8=B5=96.env?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=86=99=E5=85=A5=20trans=5Fschemas.py:=20?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=E7=BF=BB=E8=AF=91=E8=AF=B7=E6=B1=82=E7=B1=BB?= =?UTF-8?q?=E5=92=8C=E7=BF=BB=E8=AF=91=E5=9B=9E=E5=BA=94=E7=B1=BB=EF=BC=88?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E7=B1=BB=E5=B0=9A=E6=9C=AA=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=EF=BC=89=20translator.py:=20=E6=8F=90=E4=BE=9B=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E6=8E=A5=E5=8F=A3=E5=92=8C=E7=AE=A1=E7=90=86debug?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/translator.py | 118 +++++++++++++++++++++++++++++++++++ app/schemas/trans_schemas.py | 28 +++++++++ main.py | 3 + scripts/md5.py | 5 ++ settings.py | 9 ++- 5 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 app/api/translator.py create mode 100644 app/schemas/trans_schemas.py create mode 100644 scripts/md5.py diff --git a/app/api/translator.py b/app/api/translator.py new file mode 100644 index 0000000..d8a24e0 --- /dev/null +++ b/app/api/translator.py @@ -0,0 +1,118 @@ +from typing import Tuple +from wsgiref import headers + +import httpx +import random +import json +from hashlib import md5 + +import requests +from fastapi import APIRouter, Depends, HTTPException + +from app.models import User +from app.schemas.trans_schemas import TransResponse +from app.utils.security import is_admin_user, get_current_user +from scripts.md5 import make_md5 +from settings import settings + +translator_router = APIRouter() + +# For list of language codes, please refer to `https://api.fanyi.baidu.com/doc/21` +from_lang = 'en' +to_lang = 'zh' + + +# endpoint = 'https://api.fanyi.baidu.com' +# path = '/api/trans/vip/translate' +# url = endpoint + path +# +# query = 'Hello World! This is 1st paragraph.\nThis is 2nd paragraph.' +# +# salt = random.randint(32768, 65536) +# sign = make_md5(appid + query + str(salt) + appkey) +# +# headers = {'Content-Type': 'application/x-www-form-urlencoded'} +# payload = {'appid': appid, 'q': query, 'from': from_lang, 'to': to_lang, 'salt': salt, 'sign': sign} +# +# +# # Send request +# r = requests.post(url, params=payload, headers=headers) +# result = r.json() +# +# # Show response +# print(json.dumps(result, indent=4, ensure_ascii=False)) + +async def baidu_translation(query: str, from_lang: str, to_lang: str): + url = "http://api.fanyi.baidu.com/api/trans/vip/translate" + + appid = settings.BAIDU_APPID + appkey = settings.BAIDU_APPKEY + + salt = str(random.randint(32768, 65536)) + sign = make_md5(appid + query + salt + appkey) + + payload = { + "q": query, + "from": from_lang, + "to": to_lang, + "appid": appid, + "salt": salt, + "sign": sign, + } + + print(payload) + + request = httpx.Request( + "POST", + url, + data=payload, + headers={"Content-Type": "application/x-www-form-urlencoded"} + ) + print("完整请求内容:") + print("URL:", request.url) + print("Headers:", request.headers) + print("Body:", request.content.decode("utf-8")) + + async with httpx.AsyncClient(timeout=10) as client: + response = await client.post( + url, + data=payload, + headers={'Content-Type': 'application/x-www-form-urlencoded'} + ) + + if response.status_code != 200: + raise HTTPException(status_code=500, detail=response.text) + + data = response.json() + print(json.dumps(data, indent=2, ensure_ascii=False)) + + if "trans_result" not in data: + raise HTTPException(status_code=500, detail=data.get("error_msg", "Unknown error")) + + return "\n".join([item["dst"] for item in data["trans_result"]]) + + +@translator_router.post('/translate', response_model=TransResponse) +async def translate( + query: str, + from_lang: str = 'auto', + to_lang: str = 'zh', + user=Depends(get_current_user) +): + text = await baidu_translation( + query=query, + from_lang=from_lang, + to_lang=to_lang + ) + return TransResponse(translated_text=text) + + +@translator_router.post('/translate/debug') +async def test_translate( + query: str, + from_lang: str = "auto", + to_lang: str = 'zh', + admin_user: Tuple[User, dict] = Depends(is_admin_user) +): + raw = await baidu_translation(query, from_lang, to_lang) + return TransResponse(translated_text=raw) diff --git a/app/schemas/trans_schemas.py b/app/schemas/trans_schemas.py new file mode 100644 index 0000000..87aaa31 --- /dev/null +++ b/app/schemas/trans_schemas.py @@ -0,0 +1,28 @@ +from typing import Literal + +from pydantic import BaseModel, field_validator, model_validator + + +class TransRequest(BaseModel): + from_lang: Literal['fr', 'jp', 'zh'] = 'fr' + to_lang: Literal['fr', 'jp', 'zh'] = 'zh' + + @field_validator('from_lang', 'to_lang') + @classmethod + def validate_lang(cls, v): + allowed_langs = {'auto', 'fr', 'jp', 'zh'} + if v not in allowed_langs: + raise ValueError(f'Unsupported language: {v}') + return v + + @model_validator(mode="after") + def check_lang(self): + if self.from_lang == self.to_lang: + raise ValueError("from_lang and to_lang cannot be the same") + elif self.to_lang == 'auto': + raise ValueError("to_lang cannot be 'auto'") + return self + + +class TransResponse(BaseModel): + translated_text: str diff --git a/main.py b/main.py index 03aed37..a90ca7f 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,7 @@ import uvicorn from tortoise.contrib.fastapi import register_tortoise from app.api.redis_test import redis_test_router +from app.api.translator import translator_router from app.utils import redis_client from settings import TORTOISE_ORM,ONLINE_SETTINGS from app.api.users import users_router @@ -54,5 +55,7 @@ app.include_router(dict_search, tags=["Dictionary Search API"]) app.include_router(redis_test_router, tags=["Redis Test-Only API"]) +app.include_router(translator_router, tags=["Translation API"]) + if __name__ == "__main__": uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True) diff --git a/scripts/md5.py b/scripts/md5.py new file mode 100644 index 0000000..6786ed0 --- /dev/null +++ b/scripts/md5.py @@ -0,0 +1,5 @@ +from hashlib import md5 + + +def make_md5(s, encoding='utf-8'): + return md5(s.encode(encoding)).hexdigest() diff --git a/settings.py b/settings.py index a51f967..c9c455b 100644 --- a/settings.py +++ b/settings.py @@ -43,8 +43,13 @@ ONLINE_SETTINGS = { class Settings(BaseSettings): - USE_OAUTH = False - SECRET_KEY = "asdasdasd-odjfnsodfnosidnfdf-0oq2j01j0jf0i1ej0fij10fd" + USE_OAUTH: bool = False + SECRET_KEY: str + BAIDU_APPID: str + BAIDU_APPKEY: str + + class Config: + env_file = '.env' settings = Settings()