mirror of
https://github.com/xfgryujk/blivechat.git
synced 2025-04-03 16:10:35 +08:00
添加百度翻译官方接口
This commit is contained in:
parent
0b848b1288
commit
df6097a184
@ -109,6 +109,11 @@ class AppConfig:
|
|||||||
translator_config['secret_id'] = section['secret_id']
|
translator_config['secret_id'] = section['secret_id']
|
||||||
translator_config['secret_key'] = section['secret_key']
|
translator_config['secret_key'] = section['secret_key']
|
||||||
translator_config['region'] = section['region']
|
translator_config['region'] = section['region']
|
||||||
|
elif type_ == 'BaiduTranslate':
|
||||||
|
translator_config['source_language'] = section['source_language']
|
||||||
|
translator_config['target_language'] = section['target_language']
|
||||||
|
translator_config['app_id'] = section['app_id']
|
||||||
|
translator_config['secret'] = section['secret']
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'Invalid translator type: {type_}')
|
raise ValueError(f'Invalid translator type: {type_}')
|
||||||
|
|
||||||
|
@ -113,3 +113,30 @@ secret_key =
|
|||||||
# 北京:ap-beijing;上海:ap-shanghai;香港:ap-hongkong;首尔:ap-seoul
|
# 北京:ap-beijing;上海:ap-shanghai;香港:ap-hongkong;首尔:ap-seoul
|
||||||
# 完整地域列表见文档:https://cloud.tencent.com/document/api/551/15615#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8
|
# 完整地域列表见文档:https://cloud.tencent.com/document/api/551/15615#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8
|
||||||
region = ap-shanghai
|
region = ap-shanghai
|
||||||
|
|
||||||
|
|
||||||
|
[baidu_translate]
|
||||||
|
# 文档:https://fanyi-api.baidu.com/
|
||||||
|
# 定价:https://fanyi-api.baidu.com/product/112
|
||||||
|
# * 标准版完全免费,不限使用字符量(QPS=1)
|
||||||
|
# * 高级版每月前200万字符免费,超出后仅收取超出部分费用(QPS=10),49元/百万字符
|
||||||
|
# * 尊享版每月前200万字符免费,超出后仅收取超出部分费用(QPS=100),49元/百万字符
|
||||||
|
|
||||||
|
# 类型:百度翻译
|
||||||
|
type = BaiduTranslate
|
||||||
|
|
||||||
|
# 请求间隔时间(秒),等于 1 / QPS
|
||||||
|
query_interval = 1.5
|
||||||
|
# 最大队列长度,注意最长等待时间等于 最大队列长度 * 请求间隔时间
|
||||||
|
max_queue_size = 9
|
||||||
|
|
||||||
|
# 自动:auto;中文:zh;日语:jp;英语:en;韩语:kor
|
||||||
|
# 完整语言列表见文档:https://fanyi-api.baidu.com/doc/21
|
||||||
|
# 源语言
|
||||||
|
source_language = zh
|
||||||
|
# 目标语言
|
||||||
|
target_language = jp
|
||||||
|
|
||||||
|
# 百度翻译开放平台应用ID和密钥
|
||||||
|
app_id =
|
||||||
|
secret =
|
||||||
|
@ -7,6 +7,7 @@ import hashlib
|
|||||||
import hmac
|
import hmac
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import random
|
||||||
import re
|
import re
|
||||||
from typing import *
|
from typing import *
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ NO_TRANSLATE_TEXTS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_main_event_loop = asyncio.get_event_loop()
|
_main_event_loop = asyncio.get_event_loop()
|
||||||
_http_session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10))
|
_http_session = None
|
||||||
_translate_providers: List['TranslateProvider'] = []
|
_translate_providers: List['TranslateProvider'] = []
|
||||||
# text -> res
|
# text -> res
|
||||||
_translate_cache: Dict[str, str] = {}
|
_translate_cache: Dict[str, str] = {}
|
||||||
@ -35,6 +36,9 @@ def init():
|
|||||||
|
|
||||||
|
|
||||||
async def _do_init():
|
async def _do_init():
|
||||||
|
global _http_session
|
||||||
|
_http_session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10))
|
||||||
|
|
||||||
cfg = config.get_config()
|
cfg = config.get_config()
|
||||||
if not cfg.enable_translate:
|
if not cfg.enable_translate:
|
||||||
return
|
return
|
||||||
@ -63,6 +67,11 @@ def create_translate_provider(cfg):
|
|||||||
cfg['target_language'], cfg['secret_id'], cfg['secret_key'],
|
cfg['target_language'], cfg['secret_id'], cfg['secret_key'],
|
||||||
cfg['region']
|
cfg['region']
|
||||||
)
|
)
|
||||||
|
elif type_ == 'BaiduTranslate':
|
||||||
|
return BaiduTranslate(
|
||||||
|
cfg['query_interval'], cfg['max_queue_size'], cfg['source_language'],
|
||||||
|
cfg['target_language'], cfg['app_id'], cfg['secret']
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -464,3 +473,65 @@ class TencentTranslate(FlowControlTranslateProvider):
|
|||||||
|
|
||||||
def _on_cool_down_timeout(self):
|
def _on_cool_down_timeout(self):
|
||||||
self._cool_down_timer_handle = None
|
self._cool_down_timer_handle = None
|
||||||
|
|
||||||
|
|
||||||
|
class BaiduTranslate(FlowControlTranslateProvider):
|
||||||
|
def __init__(self, query_interval, max_queue_size, source_language, target_language,
|
||||||
|
app_id, secret):
|
||||||
|
super().__init__(query_interval, max_queue_size)
|
||||||
|
self._source_language = source_language
|
||||||
|
self._target_language = target_language
|
||||||
|
self._app_id = app_id
|
||||||
|
self._secret = secret
|
||||||
|
|
||||||
|
self._cool_down_timer_handle = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_available(self):
|
||||||
|
return self._cool_down_timer_handle is None and super().is_available
|
||||||
|
|
||||||
|
async def _do_translate(self, text):
|
||||||
|
try:
|
||||||
|
async with _http_session.post(
|
||||||
|
'https://fanyi-api.baidu.com/api/trans/vip/translate',
|
||||||
|
data=self._add_sign({
|
||||||
|
'q': text,
|
||||||
|
'from': self._source_language,
|
||||||
|
'to': self._target_language,
|
||||||
|
'appid': self._app_id,
|
||||||
|
'salt': random.randint(1, 999999999)
|
||||||
|
})
|
||||||
|
) as r:
|
||||||
|
if r.status != 200:
|
||||||
|
logger.warning('BaiduTranslate request failed: status=%d %s', r.status, r.reason)
|
||||||
|
return None
|
||||||
|
data = await r.json()
|
||||||
|
except (aiohttp.ClientConnectionError, asyncio.TimeoutError):
|
||||||
|
return None
|
||||||
|
error_code = data.get('error_code', None)
|
||||||
|
if error_code is not None:
|
||||||
|
logger.warning('BaiduTranslate failed: %s %s', error_code, data['error_msg'])
|
||||||
|
self._on_fail(error_code)
|
||||||
|
return None
|
||||||
|
return ''.join(result['dst'] for result in data['trans_result'])
|
||||||
|
|
||||||
|
def _add_sign(self, data):
|
||||||
|
str_to_sign = f"{self._app_id}{data['q']}{data['salt']}{self._secret}"
|
||||||
|
sign = hashlib.md5(str_to_sign.encode('utf-8')).hexdigest()
|
||||||
|
return {**data, 'sign': sign}
|
||||||
|
|
||||||
|
def _on_fail(self, code):
|
||||||
|
if self._cool_down_timer_handle is not None:
|
||||||
|
return
|
||||||
|
|
||||||
|
sleep_time = 0
|
||||||
|
if code == '54004':
|
||||||
|
# 账户余额不足,需要手动处理,等5分钟
|
||||||
|
sleep_time = 5 * 60
|
||||||
|
if sleep_time != 0:
|
||||||
|
self._cool_down_timer_handle = asyncio.get_event_loop().call_later(
|
||||||
|
sleep_time, self._on_cool_down_timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
def _on_cool_down_timeout(self):
|
||||||
|
self._cool_down_timer_handle = None
|
||||||
|
Loading…
Reference in New Issue
Block a user