2020-02-03 16:18:21 +08:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import configparser
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
from typing import *
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2022-03-01 22:13:25 +08:00
|
|
|
BASE_PATH = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
WEB_ROOT = os.path.join(BASE_PATH, 'frontend', 'dist')
|
|
|
|
DATA_PATH = os.path.join(BASE_PATH, 'data')
|
|
|
|
|
2021-04-18 17:54:41 +08:00
|
|
|
CONFIG_PATH_LIST = [
|
2022-03-01 22:13:25 +08:00
|
|
|
os.path.join(DATA_PATH, 'config.ini'),
|
|
|
|
os.path.join(DATA_PATH, 'config.example.ini')
|
2021-04-18 17:54:41 +08:00
|
|
|
]
|
2020-02-03 16:18:21 +08:00
|
|
|
|
|
|
|
_config: Optional['AppConfig'] = None
|
|
|
|
|
|
|
|
|
2024-02-18 17:04:20 +08:00
|
|
|
def init(cmd_args):
|
|
|
|
if reload(cmd_args):
|
2020-08-16 12:13:53 +08:00
|
|
|
return
|
|
|
|
logger.warning('Using default config')
|
2024-02-18 17:04:20 +08:00
|
|
|
|
|
|
|
config = AppConfig()
|
|
|
|
config.load_cmd_args(cmd_args)
|
|
|
|
|
2020-08-16 12:13:53 +08:00
|
|
|
global _config
|
2024-02-18 17:04:20 +08:00
|
|
|
_config = config
|
2020-02-03 16:18:21 +08:00
|
|
|
|
|
|
|
|
2024-02-18 17:04:20 +08:00
|
|
|
def reload(cmd_args):
|
2021-04-18 17:54:41 +08:00
|
|
|
config_path = ''
|
|
|
|
for path in CONFIG_PATH_LIST:
|
|
|
|
if os.path.exists(path):
|
|
|
|
config_path = path
|
|
|
|
break
|
|
|
|
if config_path == '':
|
|
|
|
return False
|
|
|
|
|
2020-02-03 16:18:21 +08:00
|
|
|
config = AppConfig()
|
2021-04-18 17:54:41 +08:00
|
|
|
if not config.load(config_path):
|
2020-08-16 12:13:53 +08:00
|
|
|
return False
|
2024-02-18 17:04:20 +08:00
|
|
|
config.load_cmd_args(cmd_args)
|
|
|
|
|
2020-08-16 12:13:53 +08:00
|
|
|
global _config
|
|
|
|
_config = config
|
|
|
|
return True
|
2020-02-03 16:18:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
def get_config():
|
|
|
|
return _config
|
|
|
|
|
|
|
|
|
|
|
|
class AppConfig:
|
|
|
|
def __init__(self):
|
2024-02-18 17:04:20 +08:00
|
|
|
self.debug = False
|
2023-08-26 17:01:19 +08:00
|
|
|
self.host = '127.0.0.1'
|
|
|
|
self.port = 12450
|
2020-02-03 16:18:21 +08:00
|
|
|
self.database_url = 'sqlite:///data/database.db'
|
2020-08-22 18:38:52 +08:00
|
|
|
self.tornado_xheaders = False
|
2020-08-30 17:46:04 +08:00
|
|
|
self.loader_url = ''
|
2023-07-30 15:29:40 +08:00
|
|
|
self.open_browser_at_startup = True
|
2022-02-27 22:05:37 +08:00
|
|
|
self.enable_upload_file = True
|
2021-04-20 21:30:57 +08:00
|
|
|
|
2023-09-07 00:56:32 +08:00
|
|
|
self.fetch_avatar_max_queue_size = 4
|
2023-08-05 21:25:59 +08:00
|
|
|
self.avatar_cache_size = 10000
|
2021-04-20 21:30:57 +08:00
|
|
|
|
2023-09-07 00:56:32 +08:00
|
|
|
self.open_live_access_key_id = ''
|
|
|
|
self.open_live_access_key_secret = ''
|
|
|
|
self.open_live_app_id = 0
|
|
|
|
|
2021-04-20 21:30:57 +08:00
|
|
|
self.enable_translate = True
|
|
|
|
self.allow_translate_rooms = set()
|
2023-08-05 21:25:59 +08:00
|
|
|
self.translate_max_queue_size = 10
|
2021-04-20 21:30:57 +08:00
|
|
|
self.translation_cache_size = 50000
|
2021-04-11 14:16:32 +08:00
|
|
|
self.translator_configs = []
|
2020-02-03 16:18:21 +08:00
|
|
|
|
2023-09-08 23:00:45 +08:00
|
|
|
self.text_emoticons = []
|
|
|
|
|
2023-09-07 00:56:32 +08:00
|
|
|
@property
|
|
|
|
def is_open_live_configured(self):
|
|
|
|
return (
|
|
|
|
self.open_live_access_key_id != '' and self.open_live_access_key_secret != '' and self.open_live_app_id != 0
|
|
|
|
)
|
|
|
|
|
2024-02-18 17:04:20 +08:00
|
|
|
def load_cmd_args(self, args):
|
|
|
|
if args.host is not None:
|
|
|
|
self.host = args.host
|
|
|
|
if args.port is not None:
|
|
|
|
self.port = args.port
|
|
|
|
self.debug = args.debug
|
|
|
|
|
2020-02-03 16:18:21 +08:00
|
|
|
def load(self, path):
|
|
|
|
try:
|
2020-08-22 18:38:52 +08:00
|
|
|
config = configparser.ConfigParser()
|
2021-07-17 13:17:40 +08:00
|
|
|
config.read(path, 'utf-8-sig')
|
2020-08-22 18:38:52 +08:00
|
|
|
|
2021-04-11 14:16:32 +08:00
|
|
|
self._load_app_config(config)
|
|
|
|
self._load_translator_configs(config)
|
2023-09-08 23:00:45 +08:00
|
|
|
self._load_text_emoticons(config)
|
2022-02-15 00:18:46 +08:00
|
|
|
except Exception: # noqa
|
2020-02-03 16:18:21 +08:00
|
|
|
logger.exception('Failed to load config:')
|
|
|
|
return False
|
|
|
|
return True
|
2021-04-11 14:16:32 +08:00
|
|
|
|
2022-02-27 22:05:37 +08:00
|
|
|
def _load_app_config(self, config: configparser.ConfigParser):
|
2021-04-11 14:16:32 +08:00
|
|
|
app_section = config['app']
|
2023-08-26 17:01:19 +08:00
|
|
|
self.host = app_section.get('host', self.host)
|
2023-09-07 00:56:32 +08:00
|
|
|
self.port = app_section.getint('port', self.port)
|
2022-02-27 22:05:37 +08:00
|
|
|
self.database_url = app_section.get('database_url', self.database_url)
|
2023-09-07 00:56:32 +08:00
|
|
|
self.tornado_xheaders = app_section.getboolean('tornado_xheaders', self.tornado_xheaders)
|
2022-02-27 22:05:37 +08:00
|
|
|
self.loader_url = app_section.get('loader_url', self.loader_url)
|
2023-09-07 00:56:32 +08:00
|
|
|
self.open_browser_at_startup = app_section.getboolean('open_browser_at_startup', self.open_browser_at_startup)
|
|
|
|
self.enable_upload_file = app_section.getboolean('enable_upload_file', self.enable_upload_file)
|
|
|
|
|
|
|
|
self.fetch_avatar_max_queue_size = app_section.getint(
|
|
|
|
'fetch_avatar_max_queue_size', self.fetch_avatar_max_queue_size
|
|
|
|
)
|
|
|
|
self.avatar_cache_size = app_section.getint('avatar_cache_size', self.avatar_cache_size)
|
2021-04-11 14:16:32 +08:00
|
|
|
|
2023-09-07 00:56:32 +08:00
|
|
|
self.open_live_access_key_id = app_section.get('open_live_access_key_id', self.open_live_access_key_id)
|
|
|
|
self.open_live_access_key_secret = app_section.get(
|
|
|
|
'open_live_access_key_secret', self.open_live_access_key_secret
|
|
|
|
)
|
|
|
|
self.open_live_app_id = app_section.getint('open_live_app_id', self.open_live_app_id)
|
2021-04-20 21:30:57 +08:00
|
|
|
|
2023-09-07 00:56:32 +08:00
|
|
|
self.enable_translate = app_section.getboolean('enable_translate', self.enable_translate)
|
2022-02-27 22:05:37 +08:00
|
|
|
self.allow_translate_rooms = _str_to_list(app_section.get('allow_translate_rooms', ''), int, set)
|
2023-08-05 21:25:59 +08:00
|
|
|
self.translate_max_queue_size = app_section.getint('translate_max_queue_size', self.translate_max_queue_size)
|
2022-02-27 22:05:37 +08:00
|
|
|
self.translation_cache_size = app_section.getint('translation_cache_size', self.translation_cache_size)
|
2021-04-20 21:30:57 +08:00
|
|
|
|
2022-02-27 22:05:37 +08:00
|
|
|
def _load_translator_configs(self, config: configparser.ConfigParser):
|
2021-04-11 14:16:32 +08:00
|
|
|
app_section = config['app']
|
2022-02-27 22:05:37 +08:00
|
|
|
section_names = _str_to_list(app_section.get('translator_configs', ''))
|
2021-04-11 14:16:32 +08:00
|
|
|
translator_configs = []
|
|
|
|
for section_name in section_names:
|
2022-02-27 22:05:37 +08:00
|
|
|
try:
|
|
|
|
section = config[section_name]
|
|
|
|
type_ = section['type']
|
|
|
|
|
|
|
|
translator_config = {
|
|
|
|
'type': type_,
|
|
|
|
'query_interval': section.getfloat('query_interval'),
|
|
|
|
}
|
|
|
|
if type_ == 'TencentTranslateFree':
|
|
|
|
translator_config['source_language'] = section['source_language']
|
|
|
|
translator_config['target_language'] = section['target_language']
|
|
|
|
elif type_ == 'BilibiliTranslateFree':
|
|
|
|
pass
|
|
|
|
elif type_ == 'TencentTranslate':
|
|
|
|
translator_config['source_language'] = section['source_language']
|
|
|
|
translator_config['target_language'] = section['target_language']
|
|
|
|
translator_config['secret_id'] = section['secret_id']
|
|
|
|
translator_config['secret_key'] = section['secret_key']
|
|
|
|
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']
|
2024-02-23 20:58:04 +08:00
|
|
|
elif type_ == 'GeminiTranslate':
|
|
|
|
translator_config['proxy'] = section['proxy']
|
2024-02-25 18:22:13 +08:00
|
|
|
translator_config['api_key'] = section['api_key']
|
|
|
|
translator_config['model_code'] = section['model_code']
|
2024-02-26 00:03:09 +08:00
|
|
|
translator_config['prompt'] = section['prompt'].replace('\n', ' ').replace('\\n', '\n')
|
2024-02-25 18:22:13 +08:00
|
|
|
translator_config['temperature'] = section.getfloat('temperature')
|
2022-02-27 22:05:37 +08:00
|
|
|
else:
|
|
|
|
raise ValueError(f'Invalid translator type: {type_}')
|
|
|
|
except Exception: # noqa
|
|
|
|
logger.exception('Failed to load translator=%s config:', section_name)
|
|
|
|
continue
|
2021-04-11 14:16:32 +08:00
|
|
|
|
|
|
|
translator_configs.append(translator_config)
|
|
|
|
self.translator_configs = translator_configs
|
|
|
|
|
2023-09-08 23:00:45 +08:00
|
|
|
def _load_text_emoticons(self, config: configparser.ConfigParser):
|
|
|
|
mappings_section = config['text_emoticon_mappings']
|
|
|
|
text_emoticons = []
|
|
|
|
for value in mappings_section.values():
|
|
|
|
keyword, _, url = value.partition(',')
|
|
|
|
text_emoticons.append({'keyword': keyword, 'url': url})
|
|
|
|
self.text_emoticons = text_emoticons
|
|
|
|
|
2021-04-11 14:16:32 +08:00
|
|
|
|
2021-07-17 13:03:45 +08:00
|
|
|
def _str_to_list(value, item_type: Type = str, container_type: Type = list):
|
2021-04-11 14:16:32 +08:00
|
|
|
value = value.strip()
|
|
|
|
if value == '':
|
|
|
|
return container_type()
|
|
|
|
items = value.split(',')
|
|
|
|
items = map(lambda item: item.strip(), items)
|
|
|
|
if item_type is not str:
|
|
|
|
items = map(lambda item: item_type(item), items)
|
|
|
|
return container_type(items)
|