nonebot2/nonebot/config.py

326 lines
8.6 KiB
Python
Raw Normal View History

2020-08-20 16:34:07 +08:00
"""
配置
====
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
2020-08-06 17:54:55 +08:00
from datetime import timedelta
2020-07-04 22:51:10 +08:00
from ipaddress import IPv4Address
2021-09-27 00:19:30 +08:00
from typing import Any, Set, Dict, Tuple, Union, Mapping, Optional
2020-07-04 22:51:10 +08:00
2020-08-18 17:24:49 +08:00
from pydantic import BaseSettings, IPvAnyAddress
2021-09-27 00:19:30 +08:00
from pydantic.env_settings import (SettingsError, EnvSettingsSource,
InitSettingsSource, SettingsSourceCallable,
read_env_file, env_file_sentinel)
2021-02-28 00:35:40 +08:00
class CustomEnvSettings(EnvSettingsSource):
2021-02-28 00:35:40 +08:00
def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
"""
Build environment variables suitable for passing to the Model.
"""
d: Dict[str, Optional[str]] = {}
2021-02-28 00:35:40 +08:00
if settings.__config__.case_sensitive:
env_vars: Mapping[str, Optional[str]] = os.environ
else:
env_vars = {k.lower(): v for k, v in os.environ.items()}
2020-08-13 18:16:59 +08:00
env_file_vars: Dict[str, Optional[str]] = {}
2021-02-28 00:35:40 +08:00
env_file = self.env_file if self.env_file != env_file_sentinel else settings.__config__.env_file
env_file_encoding = self.env_file_encoding if self.env_file_encoding is not None else settings.__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(
2020-08-13 18:16:59 +08:00
env_path,
encoding=env_file_encoding,
2021-02-28 00:35:40 +08:00
case_sensitive=settings.__config__.case_sensitive)
env_vars = {**env_file_vars, **env_vars}
2021-02-28 00:35:40 +08:00
for field in settings.__fields__.values():
env_val: Optional[str] = None
2020-12-06 02:30:19 +08:00
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:
2021-02-28 00:35:40 +08:00
env_val = settings.__config__.json_loads(env_val)
except ValueError as e:
raise SettingsError(
f'error parsing JSON for "{env_name}"') 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:
2021-02-28 00:35:40 +08:00
if env_val:
env_val = settings.__config__.json_loads(env_val)
except ValueError as e:
pass
d[env_name] = env_val
return d
2020-07-04 22:51:10 +08:00
2021-02-28 00:35:40 +08:00
class BaseConfig(BaseSettings):
2020-08-20 15:07:05 +08:00
def __getattr__(self, name: str) -> Any:
return self.__dict__.get(name)
2021-02-28 00:35:40 +08:00
class Config:
@classmethod
def customise_sources(
cls,
2021-03-01 00:30:06 +08:00
init_settings: InitSettingsSource,
env_settings: EnvSettingsSource,
2021-02-28 00:35:40 +08:00
file_secret_settings: SettingsSourceCallable,
) -> Tuple[SettingsSourceCallable, ...]:
2021-03-01 00:30:06 +08:00
common_config = init_settings.init_kwargs.pop("_common_config", {})
return (init_settings,
CustomEnvSettings(env_settings.env_file,
env_settings.env_file_encoding),
InitSettingsSource(common_config), file_secret_settings)
2021-02-28 00:35:40 +08:00
2020-07-04 22:51:10 +08:00
class Env(BaseConfig):
2020-08-20 15:07:05 +08:00
"""
运行环境配置大小写不敏感
将会从 ``nonebot.init 参数`` > ``环境变量`` > ``.env 环境配置文件`` 的优先级读取配置
"""
2020-07-04 22:51:10 +08:00
environment: str = "prod"
2020-08-20 15:07:05 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``str``
- **默认值**: ``"prod"``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-08-20 15:07:05 +08:00
当前环境名 NoneBot 将从 ``.env.{environment}`` 文件中加载配置
"""
2020-07-04 22:51:10 +08:00
class Config:
extra = "allow"
2020-07-04 22:51:10 +08:00
env_file = ".env"
class Config(BaseConfig):
"""
2020-08-20 15:07:05 +08:00
NoneBot 主要配置大小写不敏感
2020-08-20 16:34:07 +08:00
除了 NoneBot 的配置项外还可以自行添加配置项到 ``.env.{environment}`` 文件中
这些配置将会在 json 反序列化后一起带入 ``Config`` 类中
"""
2020-08-01 22:03:40 +08:00
# nonebot configs
2020-07-04 22:51:10 +08:00
driver: str = "nonebot.drivers.fastapi"
2020-08-20 15:07:05 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``str``
- **默认值**: ``"nonebot.drivers.fastapi"``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 15:07:05 +08:00
NoneBot 运行所使用的 ``Driver`` 继承自 ``nonebot.driver.BaseDriver``
配置格式为 ``<module>[:<class>]``默认类名为 ``Driver``
2020-08-20 15:07:05 +08:00
"""
2020-08-18 17:24:49 +08:00
host: IPvAnyAddress = IPv4Address("127.0.0.1") # type: ignore
2020-08-20 15:07:05 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``IPvAnyAddress``
- **默认值**: ``127.0.0.1``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-09-17 18:21:13 +08:00
NoneBot HTTP WebSocket 服务端监听的 IP/主机名
2020-08-20 15:07:05 +08:00
"""
2020-07-04 22:51:10 +08:00
port: int = 8080
2020-08-20 15:07:05 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``int``
- **默认值**: ``8080``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 15:07:05 +08:00
NoneBot HTTP WebSocket 服务端监听的端口
"""
2020-07-04 22:51:10 +08:00
debug: bool = False
2020-08-20 15:07:05 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``bool``
- **默认值**: ``False``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 15:07:05 +08:00
是否以调试模式运行 NoneBot
"""
log_level: Optional[Union[int, str]] = None
"""
- **类型**: ``Union[int, str]``
- **默认值**: ``None``
:说明:
配置 NoneBot 日志输出等级可以为 ``int`` 类型等级或等级名称参考 `loguru 日志等级`_
:示例:
.. code-block:: default
LOG_LEVEL=25
LOG_LEVEL=INFO
.. _loguru 日志等级:
https://loguru.readthedocs.io/en/stable/api/logger.html#levels
"""
2020-07-04 22:51:10 +08:00
2020-08-01 22:03:40 +08:00
# bot connection configs
2020-08-13 15:23:04 +08:00
api_root: Dict[str, str] = {}
2020-08-20 16:34:07 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``Dict[str, str]``
- **默认值**: ``{}``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 16:34:07 +08:00
以机器人 ID 为键上报地址为值的字典环境变量或文件中应使用 json 序列化
2020-11-30 11:08:00 +08:00
2020-11-30 12:43:44 +08:00
:示例:
2020-08-20 16:34:07 +08:00
2020-09-14 21:40:05 +08:00
.. code-block:: default
2020-08-20 16:34:07 +08:00
API_ROOT={"123456": "http://127.0.0.1:5700"}
"""
2020-08-28 11:54:21 +08:00
api_timeout: Optional[float] = 30.
2020-08-20 16:34:07 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``Optional[float]``
- **默认值**: ``30.``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 16:34:07 +08:00
API 请求超时时间单位:
"""
2020-08-01 22:03:40 +08:00
access_token: Optional[str] = None
2020-08-20 16:34:07 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``Optional[str]``
- **默认值**: ``None``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-09-15 14:48:15 +08:00
API 请求以及上报所需密钥在请求头中携带
2020-11-30 11:08:00 +08:00
2020-11-30 12:43:44 +08:00
:示例:
2020-09-15 14:48:15 +08:00
.. code-block:: http
POST /cqhttp/ HTTP/1.1
Authorization: Bearer kSLuTF2GC2Q4q4ugm3
"""
secret: Optional[str] = None
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``Optional[str]``
- **默认值**: ``None``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-09-15 14:48:15 +08:00
HTTP POST 形式上报所需签名在请求头中携带
2020-11-30 11:08:00 +08:00
2020-11-30 12:43:44 +08:00
:示例:
2020-09-15 14:48:15 +08:00
.. code-block:: http
POST /cqhttp/ HTTP/1.1
X-Signature: sha1=f9ddd4863ace61e64f462d41ca311e3d2c1176e2
2020-08-20 16:34:07 +08:00
"""
2020-08-01 22:03:40 +08:00
# bot runtime configs
2020-12-17 21:09:30 +08:00
superusers: Set[str] = set()
2020-08-20 16:34:07 +08:00
"""
2020-12-17 21:09:30 +08:00
- **类型**: ``Set[str]``
2020-11-30 12:43:44 +08:00
- **默认值**: ``set()``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 16:34:07 +08:00
机器人超级用户
2020-11-30 11:08:00 +08:00
2020-11-30 12:43:44 +08:00
:示例:
2020-08-20 16:34:07 +08:00
2020-09-14 21:40:05 +08:00
.. code-block:: default
2020-08-20 16:34:07 +08:00
2021-01-05 23:06:36 +08:00
SUPERUSERS=["12345789"]
2020-08-20 16:34:07 +08:00
"""
2020-10-06 22:29:05 +08:00
nickname: Set[str] = set()
2020-08-20 16:34:07 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``Set[str]``
- **默认值**: ``set()``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 16:34:07 +08:00
机器人昵称
"""
2020-08-17 16:09:41 +08:00
command_start: Set[str] = {"/"}
2020-08-20 16:34:07 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``Set[str]``
- **默认值**: ``{"/"}``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 16:34:07 +08:00
命令的起始标记用于判断一条消息是不是命令
"""
2020-08-17 16:09:41 +08:00
command_sep: Set[str] = {"."}
2020-08-20 16:34:07 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``Set[str]``
- **默认值**: ``{"."}``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 16:34:07 +08:00
命令的分隔标记用于将文本形式的命令切分为元组实际的命令名
"""
2020-08-06 17:54:55 +08:00
session_expire_timeout: timedelta = timedelta(minutes=2)
2020-08-20 16:34:07 +08:00
"""
2020-11-30 12:43:44 +08:00
- **类型**: ``timedelta``
- **默认值**: ``timedelta(minutes=2)``
2020-12-13 12:53:33 +08:00
2020-11-30 12:43:44 +08:00
:说明:
2020-11-30 11:08:00 +08:00
2020-08-20 16:34:07 +08:00
等待用户回复的超时时间
2020-11-30 11:08:00 +08:00
2020-11-30 12:43:44 +08:00
:示例:
2020-08-20 16:34:07 +08:00
2020-09-14 21:40:05 +08:00
.. code-block:: default
2020-08-20 16:34:07 +08:00
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
"""
2020-07-04 22:51:10 +08:00
# adapter configs
# adapter configs are defined in adapter/config.py
2020-08-01 22:03:40 +08:00
# custom configs
# custom configs can be assigned during nonebot.init
# or from env file using json loads
2020-07-04 22:51:10 +08:00
class Config:
extra = "allow"
2020-07-04 22:51:10 +08:00
env_file = ".env.prod"