nonebot2/nonebot/config.py
2020-10-06 22:29:05 +08:00

267 lines
7.5 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
配置
====
NoneBot 使用 `pydantic`_ 以及 `python-dotenv`_ 来读取配置。
配置项需符合特殊格式或 json 序列化格式。详情见 `pydantic Field Type`_ 文档。
.. _pydantic:
https://pydantic-docs.helpmanual.io/
.. _python-dotenv:
https://saurabh-kumar.com/python-dotenv/
.. _pydantic Field Type:
https://pydantic-docs.helpmanual.io/usage/types/
"""
import os
from pathlib import Path
from datetime import timedelta
from ipaddress import IPv4Address
from pydantic import BaseSettings, IPvAnyAddress
from pydantic.env_settings import SettingsError, env_file_sentinel, read_env_file
from nonebot.typing import Any, Set, Dict, Union, Mapping, Optional
class BaseConfig(BaseSettings):
def _build_environ(
self,
_env_file: Union[Path, str, None] = None,
_env_file_encoding: Optional[str] = None
) -> Dict[str, Optional[str]]:
"""
Build environment variables suitable for passing to the Model.
"""
d: Dict[str, Optional[str]] = {}
if self.__config__.case_sensitive:
env_vars: Mapping[str, Optional[str]] = os.environ
else:
env_vars = {k.lower(): v for k, v in os.environ.items()}
env_file_vars: Dict[str, Optional[str]] = {}
env_file = _env_file if _env_file != env_file_sentinel else self.__config__.env_file
env_file_encoding = _env_file_encoding if _env_file_encoding is not None else self.__config__.env_file_encoding
if env_file is not None:
env_path = Path(env_file)
if env_path.is_file():
env_file_vars = read_env_file(
env_path,
encoding=env_file_encoding,
case_sensitive=self.__config__.case_sensitive)
env_vars = {**env_file_vars, **env_vars}
for field in self.__fields__.values():
env_val: Optional[str] = None
for env_name in field.field_info.extra['env_names']:
env_val = env_vars.get(env_name)
if env_name in env_file_vars:
del env_file_vars[env_name]
if env_val is not None:
break
if env_val is None:
continue
if field.is_complex():
try:
env_val = self.__config__.json_loads(env_val)
except ValueError as e:
raise SettingsError(
f'error parsing JSON for "{env_name}"' # type: ignore
) from e
d[field.alias] = env_val
if env_file_vars:
for env_name, env_val in env_file_vars.items():
if (env_val is None or
len(env_val) == 0) and env_name in env_vars:
env_val = env_vars[env_name]
try:
env_val = self.__config__.json_loads(env_val)
except ValueError as e:
pass
d[env_name] = env_val
return d
def __getattr__(self, name: str) -> Any:
return self.__dict__.get(name)
class Env(BaseSettings):
"""
运行环境配置。大小写不敏感。
将会从 ``nonebot.init 参数`` > ``环境变量`` > ``.env 环境配置文件`` 的优先级读取配置。
"""
environment: str = "prod"
"""
- 类型: ``str``
- 默认值: ``"prod"``
- 说明:
当前环境名。 NoneBot 将从 ``.env.{environment}`` 文件中加载配置。
"""
class Config:
env_file = ".env"
class Config(BaseConfig):
"""
NoneBot 主要配置。大小写不敏感。
除了 NoneBot 的配置项外,还可以自行添加配置项到 ``.env.{environment}`` 文件中。
这些配置将会在 json 反序列化后一起带入 ``Config`` 类中。
"""
# nonebot configs
driver: str = "nonebot.drivers.fastapi"
"""
- 类型: ``str``
- 默认值: ``"nonebot.drivers.fastapi"``
- 说明:
NoneBot 运行所使用的 ``Driver`` 。继承自 ``nonebot.driver.BaseDriver`` 。
"""
host: IPvAnyAddress = IPv4Address("127.0.0.1") # type: ignore
"""
- 类型: ``IPvAnyAddress``
- 默认值: ``127.0.0.1``
- 说明:
NoneBot 的 HTTP 和 WebSocket 服务端监听的 IP/主机名。
"""
port: int = 8080
"""
- 类型: ``int``
- 默认值: ``8080``
- 说明:
NoneBot 的 HTTP 和 WebSocket 服务端监听的端口。
"""
debug: bool = False
"""
- 类型: ``bool``
- 默认值: ``False``
- 说明:
是否以调试模式运行 NoneBot。
"""
# bot connection configs
api_root: Dict[str, str] = {}
"""
- 类型: ``Dict[str, str]``
- 默认值: ``{}``
- 说明:
以机器人 ID 为键,上报地址为值的字典,环境变量或文件中应使用 json 序列化。
- 示例:
.. code-block:: default
API_ROOT={"123456": "http://127.0.0.1:5700"}
"""
api_timeout: Optional[float] = 30.
"""
- 类型: ``Optional[float]``
- 默认值: ``30.``
- 说明:
API 请求超时时间,单位: 秒。
"""
access_token: Optional[str] = None
"""
- 类型: ``Optional[str]``
- 默认值: ``None``
- 说明:
API 请求以及上报所需密钥,在请求头中携带。
- 示例:
.. code-block:: http
POST /cqhttp/ HTTP/1.1
Authorization: Bearer kSLuTF2GC2Q4q4ugm3
"""
secret: Optional[str] = None
"""
- 类型: ``Optional[str]``
- 默认值: ``None``
- 说明:
HTTP POST 形式上报所需签名,在请求头中携带。
- 示例:
.. code-block:: http
POST /cqhttp/ HTTP/1.1
X-Signature: sha1=f9ddd4863ace61e64f462d41ca311e3d2c1176e2
"""
# bot runtime configs
superusers: Set[int] = set()
"""
- 类型: ``Set[int]``
- 默认值: ``set()``
- 说明:
机器人超级用户。
- 示例:
.. code-block:: default
SUPER_USERS=[12345789]
"""
nickname: Set[str] = set()
"""
- 类型: ``Set[str]``
- 默认值: ``set()``
- 说明:
机器人昵称。
"""
command_start: Set[str] = {"/"}
"""
- 类型: ``Set[str]``
- 默认值: ``{"/"}``
- 说明:
命令的起始标记,用于判断一条消息是不是命令。
"""
command_sep: Set[str] = {"."}
"""
- 类型: ``Set[str]``
- 默认值: ``{"."}``
- 说明:
命令的分隔标记,用于将文本形式的命令切分为元组(实际的命令名)。
"""
session_expire_timeout: timedelta = timedelta(minutes=2)
"""
- 类型: ``timedelta``
- 默认值: ``timedelta(minutes=2)``
- 说明:
等待用户回复的超时时间。
- 示例:
.. code-block:: default
SESSION_EXPIRE_TIMEOUT=120 # 单位: 秒
SESSION_EXPIRE_TIMEOUT=[DD ][HH:MM]SS[.ffffff]
SESSION_EXPIRE_TIMEOUT=P[DD]DT[HH]H[MM]M[SS]S # ISO 8601
"""
apscheduler_config: dict = {"apscheduler.timezone": "Asia/Shanghai"}
"""
- 类型: ``dict``
- 默认值: ``{"apscheduler.timezone": "Asia/Shanghai"}``
- 说明:
APScheduler 的配置对象,见 `Configuring the Scheduler`_
.. _Configuring the Scheduler:
https://apscheduler.readthedocs.io/en/latest/userguide.html#configuring-the-scheduler
"""
# custom configs
# custom configs can be assigned during nonebot.init
# or from env file using json loads
class Config:
extra = "allow"
env_file = ".env.prod"